コード例 #1
0
ファイル: caps.py プロジェクト: gbd-consult/gbd-websuite
def _map_layers(root_el: gws.XmlElement,
                props) -> t.Dict[str, gws.SourceLayer]:
    no_wms_layers = set(_pval(props, 'WMSRestrictedLayers') or [])
    use_layer_ids = _pval(props, 'WMSUseLayerIDs')

    map_layers = {}

    for el in xml2.all(root_el, 'projectlayers maplayer'):
        sl = _map_layer(el)

        if not sl:
            continue

        title = sl.metadata.get('title')

        # no_wms_layers always contains titles, not ids (=names)
        if title in no_wms_layers:
            continue

        uid = xml2.text(el, 'id')
        if use_layer_ids:
            name = uid
        else:
            name = xml2.text(el, 'shortname') or xml2.text(el, 'layername')

        sl.title = title
        sl.name = name
        sl.metadata.set('name', name)

        map_layers[uid] = sl

    return map_layers
コード例 #2
0
def service_metadata(root_el: gws.XmlElement) -> gws.lib.metadata.Metadata:
    # wms
    #
    #   <Capabilities
    #       <Service...
    #           <Name>...
    #           <Title>...
    #           <ContactInformation>...
    #
    # ows
    #
    #   <Capabilities
    #       <ows:ServiceIdentification>
    #           <ows:Title>....
    #       <ows:ServiceProvider>
    #           <ows:ProviderName>...
    #           <ows:ServiceContact>...

    d = _metadata_dict(xml2.first(root_el, 'Service', 'ServiceIdentification'))
    d.update(_contact_dict(root_el))
    d['contactProviderName'] = xml2.text(root_el,
                                         'ServiceProvider ProviderName')
    d['contactProviderSite'] = xml2.text(root_el,
                                         'ServiceProvider ProviderSite')

    #   <Capabilities
    #       <ServiceMetadataURL

    link = _parse_link(xml2.first(root_el, 'ServiceMetadataURL'))
    if link:
        d['metaLinks'] = [link]

    return gws.lib.metadata.from_dict(gws.strip(d))
コード例 #3
0
def _f_GeoBAK(el: gws.XmlElement, fallback_crs, **kwargs):
    # GeoBAK (https://www.egovernment.sachsen.de/geodaten.html)
    #
    # <geobak_20:Sachdatenabfrage...
    #     <geobak_20:Kartenebene>....
    #     <geobak_20:Inhalt>
    #         <geobak_20:Datensatz>
    #             <geobak_20:Attribut>
    #                 <geobak_20:Name>...
    #                 <geobak_20:Wert>...
    #     <geobak_20:Inhalt>
    #         <geobak_20:Datensatz>
    #           ...
    #

    if not xml2.element_is(el, 'Sachdatenabfrage'):
        return None

    features = []

    layer_name = xml2.text(el, 'Kartenebene')

    for content_el in xml2.all(el, 'Inhalt'):
        for feature_el in xml2.all(content_el, 'Datensatz'):
            atts = {
                xml2.text(a, 'Name').strip(): xml2.text(a, 'Wert').strip()
                for a in xml2.all(feature_el, 'Attribut')
            }
            features.append(
                gws.gis.feature.from_args(category=layer_name,
                                          attributes=atts))

    return features
コード例 #4
0
def _layer(el: gws.XmlElement, parent: t.Optional[gws.SourceLayer] = None) -> gws.SourceLayer:
    sl = gws.SourceLayer()

    sl.is_queryable = xml2.attr(el, 'queryable') == '1'
    sl.is_visible = True
    sl.metadata = u.element_metadata(el)
    sl.name = sl.metadata.get('name', '')
    sl.styles = [u.parse_style(e) for e in xml2.all(el, 'Style')]
    sl.supported_bounds = u.supported_bounds(el)
    sl.title = sl.metadata.get('title', '')

    if not sl.name:
        # some folks have unnamed layers in their caps
        # we can't render or query them
        sl.is_queryable = False
        sl.is_image = False

    # @TODO: support ScaleHint (WMS 1.1)

    smin = xml2.text(el, 'MinScaleDenominator')
    smax = xml2.text(el, 'MaxScaleDenominator')
    if smax:
        sl.scale_range = [u.to_int(smin), u.to_int(smax)]

    # OGC 06-042, 7.2.4.8 Inheritance of layer properties

    if parent:
        crs = set(b.crs for b in sl.supported_bounds)
        for b in parent.supported_bounds:
            if b.crs not in crs:
                sl.supported_bounds.append(b)

        names = set(s.name for s in sl.styles)
        for s in parent.styles:
            if s.name not in names:
                sl.styles.append(s)

        sl.metadata.extend(parent.metadata)

    sl.layers = [_layer(e, sl) for e in xml2.all(el, 'Layer')]
    sl.is_group = len(sl.layers) > 0
    sl.is_image = len(sl.layers) == 0

    sl.default_style = u.default_style(sl.styles)
    if sl.default_style:
        sl.legend_url = sl.default_style.legend_url

    return sl
コード例 #5
0
ファイル: caps.py プロジェクト: gbd-consult/gbd-websuite
def _tile_matrix_set(el: gws.XmlElement):
    # <TileMatrixSet>
    #   <ows:Identifier>...
    #   <ows:SupportedCRS>...
    #   <TileMatrix>
    #     ...

    tms = gws.TileMatrixSet()

    tms.uid = xml2.text(el, 'Identifier')
    tms.crs = gws.gis.crs.require(xml2.text(el, 'SupportedCRS'))
    tms.matrices = sorted(
        [_tile_matrix(e) for e in xml2.all(el, 'TileMatrix')],
        key=lambda m: int('1' + m.uid))

    return tms
コード例 #6
0
def _metadata_dict(el: gws.XmlElement) -> dict:
    if not el:
        return {}

    d = {
        'abstract':
        xml2.text(el, 'Abstract'),
        'accessConstraints':
        xml2.text(el, 'AccessConstraints'),
        'attribution':
        xml2.text(el, 'Attribution Title'),
        'fees':
        xml2.text(el, 'Fees'),
        'keywords':
        xml2.text_list(el, 'Keywords', 'KeywordList', deep=True),
        'name':
        xml2.text(el, 'Name') or xml2.text(el, 'Identifier'),
        'title':
        xml2.text(el, 'Title'),
        'metaLinks':
        gws.compact(_parse_link(e) for e in xml2.all(el, 'MetadataURL')),
    }

    e = xml2.first(el, 'AuthorityURL')
    if e:
        d['authorityUrl'] = _parse_url(e)
        d['authorityName'] = xml2.attr(e, 'name')

    e = xml2.first(el, 'Identifier')
    if e:
        d['authorityIdentifier'] = e.text

    return gws.strip(d)
コード例 #7
0
ファイル: caps.py プロジェクト: gbd-consult/gbd-websuite
def _layer(el: gws.XmlElement, tms_map):
    # <Layer>
    #   <ows:Title>...
    #   <Style>...
    #   <Format>...
    #   <TileMatrixSetLink>
    #     <TileMatrixSet>...

    sl = gws.SourceLayer()

    sl.metadata = u.element_metadata(el)
    sl.name = sl.metadata.get('name', '')
    sl.title = sl.metadata.get('title', '')

    sl.styles = [u.parse_style(e) for e in xml2.all(el, 'Style')]
    sl.default_style = u.default_style(sl.styles)
    if sl.default_style:
        sl.legend_url = sl.default_style.legend_url

    sl.tile_matrix_ids = [
        xml2.text(e, 'TileMatrixSet')
        for e in xml2.all(el, 'TileMatrixSetLink')
    ]
    sl.tile_matrix_sets = [tms_map[tid] for tid in sl.tile_matrix_ids]

    extra_crsids = [tms.crs.srid for tms in sl.tile_matrix_sets]
    sl.supported_bounds = u.supported_bounds(el, extra_crsids)

    sl.is_image = True
    sl.is_visible = True

    sl.image_format = xml2.text(el, 'Format')

    sl.resource_urls = {
        xml2.attr(e, 'resourceType'): xml2.attr(e, 'template')
        for e in xml2.all(el, 'ResourceURL')
    }

    return sl
コード例 #8
0
ファイル: caps.py プロジェクト: gbd-consult/gbd-websuite
def _map_layer(layer_el: gws.XmlElement):
    sl = gws.SourceLayer()

    sl.metadata = _map_layer_metadata(layer_el)

    sl.supported_bounds = []

    crs = gws.gis.crs.get(xml2.text(layer_el, 'srs spatialrefsys authid'))
    ext = xml2.first(layer_el, 'extent')

    if crs and ext:
        sl.supported_bounds.append(
            gws.Bounds(crs=crs,
                       extent=(
                           _parse_float(xml2.text(ext, 'xmin')),
                           _parse_float(xml2.text(ext, 'ymin')),
                           _parse_float(xml2.text(ext, 'xmax')),
                           _parse_float(xml2.text(ext, 'ymax')),
                       )))

    if layer_el.attributes.get('hasScaleBasedVisibilityFlag') == '1':
        # in qgis, maxScale < minScale
        a = _parse_float(layer_el.attributes.get('maxScale'))
        z = _parse_float(layer_el.attributes.get('minScale'))
        if z > a:
            sl.scale_range = [a, z]

    prov = xml2.text(layer_el, 'provider').lower()
    ds = _parse_datasource(prov, xml2.text(layer_el, 'datasource'))
    if ds and 'provider' not in ds:
        ds['provider'] = prov
    sl.data_source = ds

    s = xml2.text(layer_el, 'layerOpacity')
    if s:
        sl.opacity = _parse_float(s)

    s = xml2.text(layer_el, 'flags Identifiable')
    sl.is_queryable = s == '1'

    return sl
コード例 #9
0
def _parse_link(el: gws.XmlElement) -> t.Optional[gws.MetadataLink]:
    # <MetadataURL type="...
    #       <Format...
    # 	    <OnlineResource...

    if not el:
        return None

    d = gws.strip({
        'url': _parse_url(el),
        'type': xml2.attr(el, 'type'),
        'formatName': xml2.text(el, 'Format'),
    })

    if d:
        return gws.MetadataLink(d)
コード例 #10
0
def _parse_bbox(el: gws.XmlElement):
    # note: bboxes are always converted to (x1, y1, x2, y2) with x1 < x2, y1 < y2

    # <BoundingBox/LatLonBoundingBox CRS="..." minx="0" miny="1" maxx="2" maxy="3"/>

    if xml2.attr(el, 'minx'):
        return [
            to_float(xml2.attr(el, 'minx')),
            to_float(xml2.attr(el, 'miny')),
            to_float(xml2.attr(el, 'maxx')),
            to_float(xml2.attr(el, 'maxy')),
        ]

    # <ows:BoundingBox/WGS84BoundingBox
    #       <ows:LowerCorner> 0 1
    #       <ows:UpperCorner> 2 3

    if xml2.first(el, 'LowerCorner'):
        x1, y1 = to_float_pair(xml2.text(el, 'LowerCorner'))
        x2, y2 = to_float_pair(xml2.text(el, 'UpperCorner'))
        return [
            min(x1, x2),
            min(y1, y2),
            max(x1, x2),
            max(y1, y2),
        ]

    # <EX_GeographicBoundingBox>
    #       <westBoundLongitude> 0
    #       <eastBoundLongitude> 2
    #       <southBoundLatitude> 1
    #       <northBoundLatitude> 3

    if xml2.first(el, 'westBoundLongitude'):
        x1 = to_float(xml2.text(el, 'eastBoundLongitude'))
        y1 = to_float(xml2.text(el, 'southBoundLatitude'))
        x2 = to_float(xml2.text(el, 'westBoundLongitude'))
        y2 = to_float(xml2.text(el, 'northBoundLatitude'))
        return [
            min(x1, x2),
            min(y1, y2),
            max(x1, x2),
            max(y1, y2),
        ]
コード例 #11
0
ファイル: caps.py プロジェクト: gbd-consult/gbd-websuite
def parse(xml: str) -> Caps:
    root_el = xml2.from_string(xml,
                               sort_atts=True,
                               strip_ns=True,
                               to_lower=True)

    ver = root_el.attributes.get('version', '').split('-')[0]
    if not ver.startswith('3'):
        raise gws.Error(f'unsupported QGIS version {ver!r}')

    caps = Caps(version=ver)

    caps.properties = _properties(xml2.first(root_el, 'properties'))
    caps.metadata = _project_meta_from_props(caps.properties)
    caps.project_crs = gws.gis.crs.get(
        xml2.text(root_el, 'projectCrs spatialrefsys authid'))
    caps.print_templates = _layouts(root_el)

    map_layers = _map_layers(root_el, caps.properties)
    root_group = _map_layer_tree(xml2.first(root_el, 'layer-tree-group'),
                                 map_layers)
    caps.source_layers = gws.gis.source.check_layers(root_group.layers)

    return caps
コード例 #12
0
ファイル: caps.py プロジェクト: gbd-consult/gbd-websuite
def _tile_matrix(el: gws.XmlElement):
    # <TileMatrix>
    #   <ows:Identifier>
    #   <ScaleDenominator>
    #   ...

    tm = gws.TileMatrix()
    tm.uid = xml2.text(el, 'Identifier')
    tm.scale = u.to_float(xml2.text(el, 'ScaleDenominator'))

    p = u.to_float_pair(xml2.text(el, 'TopLeftCorner'))
    tm.x = p[0]
    tm.y = p[1]

    tm.width = u.to_int(xml2.text(el, 'MatrixWidth'))
    tm.height = u.to_int(xml2.text(el, 'MatrixHeight'))

    tm.tile_width = u.to_int(xml2.text(el, 'TileWidth'))
    tm.tile_height = u.to_int(xml2.text(el, 'TileHeight'))

    tm.extent = _extent_for_matrix(tm)

    return tm
コード例 #13
0
ファイル: caps.py プロジェクト: gbd-consult/gbd-websuite
 def tx(s):
     return xml2.text(layer_el, s)