This provides mechanism for externalizing and sharing data sources.  The datasource configs are
    python files, and layers reference sections within that config:
    
    <DataSourcesConfig src="datasources.cfg" />
    <Layer class="road major" source_name="planet_osm_major_roads" />
    <Layer class="road minor" source_name="planet_osm_minor_roads" />
    
    See example_dscfg.mml and example.cfg at the root of the cascadenik directory for an example.

def expand_source_declarations(map_el, dirs, local_conf):
    """ This provides mechanism for externalizing and sharing data sources.  The datasource configs are
    python files, and layers reference sections within that config:
    
    <DataSourcesConfig src="datasources.cfg" />
    <Layer class="road major" source_name="planet_osm_major_roads" />
    <Layer class="road minor" source_name="planet_osm_minor_roads" />
    
    See example_dscfg.mml and example.cfg at the root of the cascadenik directory for an example.
    """

    
    
    ds = sources.DataSources(dirs.source, local_conf)

    # build up the configuration
    for spec in map_el.findall('DataSourcesConfig'):
        map_el.remove(spec)
        src_text, local_base = fetch_embedded_or_remote_src(spec, dirs)
        if not src_text:
            continue

        ds.add_config(src_text, local_base)    
    
    # now transform the xml

    # add in base datasources
    for base_name in ds.templates:
        b = Element("Datasource", name=base_name)
        for pname, pvalue in ds.sources[base_name]['parameters'].items():
            p = Element("Parameter", name=pname)
            p.text = str(pvalue)
            b.append(p)
        map_el.insert(0, b)
    
    # expand layer data sources
    for layer in map_el.findall('Layer'):
        if 'source_name' not in layer.attrib:
            continue
        
        if layer.attrib['source_name'] not in ds.sources:
            raise Exception("Datasource '%s' referenced, but not defined in layer:\n%s" % (layer.attrib['source_name'], ElementTree.tostring(layer)))
                
        # create the nested datasource object 
        b = Element("Datasource")
        dsrc = ds.sources[layer.attrib['source_name']]

        if 'template' in dsrc:
            b.attrib['base'] = dsrc['template']
        
        # set the SRS if present
        if 'layer_srs' in dsrc:
            layer.attrib['srs'] = dsrc['layer_srs']
        
        for pname, pvalue in dsrc['parameters'].items():
            p = Element("Parameter", name=pname)
            p.text = pvalue
            b.append(p)
        
        layer.append(b)
        del layer.attrib['source_name']