Beispiel #1
0
def write_extent(bbox, nsmap):
    ''' Generate BBOX extent '''

    from shapely.wkt import loads

    if bbox is not None:
        try:
            bbox2 = util.wkt2geom(bbox)
        except:
            return None
        extent = etree.Element(util.nspath_eval('dif:Spatial_Coverage', nsmap))
        etree.SubElement(extent,
                         util.nspath_eval('dif:Southernmost_Latitude',
                                          nsmap)).text = str(bbox2[1])
        etree.SubElement(extent,
                         util.nspath_eval('dif:Northernmost_Latitude',
                                          nsmap)).text = str(bbox2[3])
        etree.SubElement(extent,
                         util.nspath_eval('dif:Westernmost_Longitude',
                                          nsmap)).text = str(bbox2[0])
        etree.SubElement(extent,
                         util.nspath_eval('dif:Easternmost_Longitude',
                                          nsmap)).text = str(bbox2[2])
        return extent
    return None
Beispiel #2
0
def write_extent(bbox, nsmap):
    ''' Generate BBOX extent '''

    if bbox is not None:
        try:
            bbox2 = util.wkt2geom(bbox)
        except:
            return None
        bounding_box = etree.Element(
            util.nspath_eval('gm03:GM03_2_1Core.Core.EX_GeographicBoundingBox',
                             NAMESPACES))
        etree.SubElement(bounding_box,
                         util.nspath_eval('gm03:northBoundLatitude',
                                          nsmap)).text = str(bbox2[3])
        etree.SubElement(bounding_box,
                         util.nspath_eval('gm03:southBoundLatitude',
                                          nsmap)).text = str(bbox2[1])
        etree.SubElement(bounding_box,
                         util.nspath_eval('gm03:eastBoundLongitude',
                                          nsmap)).text = str(bbox2[0])
        etree.SubElement(bounding_box,
                         util.nspath_eval('gm03:westBoundLongitude',
                                          nsmap)).text = str(bbox2[2])
        return bounding_box
    return None
Beispiel #3
0
    def cswrecord2atom(self, rec):
        entry = etree.Element(util.nspath_eval('atom:entry', self.namespaces))

        etree.SubElement(entry, util.nspath_eval('atom:id', self.context.namespaces)).text = rec.xpath('dc:identifier', namespaces=self.context.namespaces)[0].text
        etree.SubElement(entry, util.nspath_eval('dc:identifier', self.context.namespaces)).text = rec.xpath('dc:identifier', namespaces=self.context.namespaces)[0].text
        etree.SubElement(entry, util.nspath_eval('atom:title', self.context.namespaces)).text = rec.xpath('dc:title', namespaces=self.context.namespaces)[0].text

        dc_date = rec.xpath('dc:date', namespaces=self.context.namespaces)
        if dc_date:
            etree.SubElement(entry, util.nspath_eval('atom:updated', self.context.namespaces)).text = dc_date[0].text

        for s in rec.xpath('dc:subject', namespaces=self.context.namespaces):
            etree.SubElement(entry, util.nspath_eval('atom:category', self.context.namespaces), term=s.text)

        for d in rec.xpath('dct:references', namespaces=self.context.namespaces):
            link = etree.SubElement(entry, util.nspath_eval('atom:link', self.context.namespaces))
            link.attrib['href'] = d.text

            scheme = d.attrib.get('scheme')
            if scheme is not None:
                if scheme == 'enclosure':
                    link.attrib['rel'] = scheme
                    link.attrib['type'] = 'application/octet-stream'
                else:
                    link.attrib['type'] = scheme

        bbox = rec.xpath('ows:BoundingBox|ows20:BoundingBox', namespaces=self.context.namespaces)
        if bbox:
            where = etree.SubElement(entry, util.nspath_eval('georss:where', {'georss': 'http://www.georss.org/georss'}))
            envelope = etree.SubElement(where, util.nspath_eval('gml:Envelope', self.context.namespaces))
            envelope.attrib['srsName'] = bbox[0].attrib.get('crs')
            etree.SubElement(envelope, util.nspath_eval('gml:lowerCorner', self.context.namespaces)).text = bbox[0].xpath('ows:LowerCorner|ows20:LowerCorner', namespaces=self.context.namespaces)[0].text
            etree.SubElement(envelope, util.nspath_eval('gml:upperCorner', self.context.namespaces)).text = bbox[0].xpath('ows:UpperCorner|ows20:UpperCorner', namespaces=self.context.namespaces)[0].text

        return entry
Beispiel #4
0
def cql2fes1(cql, namespaces):
    """transforms Common Query Language (CQL) query into OGC fes1 syntax"""

    filters = []
    tmp_list = []
    logical_op = None

    LOGGER.debug('CQL: %s', cql)

    if ' or ' in cql:
        logical_op = etree.Element(util.nspath_eval('ogc:Or', namespaces))
        tmp_list = cql.split(' or ')
    elif ' OR ' in cql:
        logical_op = etree.Element(util.nspath_eval('ogc:Or', namespaces))
        tmp_list = cql.split(' OR ')
    elif ' and ' in cql:
        logical_op = etree.Element(util.nspath_eval('ogc:And', namespaces))
        tmp_list = cql.split(' and ')
    elif ' AND ' in cql:
        logical_op = etree.Element(util.nspath_eval('ogc:And', namespaces))
        tmp_list = cql.split(' AND ')

    if tmp_list:
        LOGGER.debug('Logical operator found (AND/OR)')
    else:
        tmp_list.append(cql)

    for t in tmp_list:
        filters.append(_parse_condition(t))

    root = etree.Element(util.nspath_eval('ogc:Filter', namespaces))

    if logical_op is not None:
        root.append(logical_op)

    for flt in filters:
        condition = etree.Element(util.nspath_eval(flt[0], namespaces))

        etree.SubElement(
            condition,
            util.nspath_eval('ogc:PropertyName', namespaces)).text = flt[1]

        etree.SubElement(
            condition,
            util.nspath_eval('ogc:Literal', namespaces)).text = flt[2]

        if logical_op is not None:
            logical_op.append(condition)
        else:
            root.append(condition)

    LOGGER.debug('Resulting OGC Filter: %s',
                 etree.tostring(root, pretty_print=1))

    return root
Beispiel #5
0
def _get_pt_freeurl(val, language):
    freeurl = etree.Element(
        util.nspath_eval('gm03:GM03_2_1Core.Core.PT_FreeURL', NAMESPACES))
    urlgroup = etree.SubElement(freeurl,
                                util.nspath_eval('gm03:URLGroup', NAMESPACES))
    ptgroup = etree.SubElement(
        urlgroup,
        util.nspath_eval('gm03:GM03_2_1Core.Core.PT_URLGroup', NAMESPACES))
    if language:
        etree.SubElement(ptgroup, util.nspath_eval('gm03:language',
                                                   NAMESPACES)).text = language
    etree.SubElement(ptgroup, util.nspath_eval('gm03:plainURL',
                                               NAMESPACES)).text = val

    return freeurl
Beispiel #6
0
def write_extent(bbox, nsmap):
    ''' Generate BBOX extent '''

    if bbox is not None:
        try:
            bbox2 = util.wkt2geom(bbox)
        except:
            return None
        where = etree.Element(util.nspath_eval('georss:where', NAMESPACES))
        envelope = etree.SubElement(where, util.nspath_eval('gml:Envelope', nsmap), srsName='http://www.opengis.net/def/crs/EPSG/0/4326')
        etree.SubElement(envelope, util.nspath_eval('gml:lowerCorner', nsmap)).text = '%s %s' % (bbox2[1], bbox2[0])
        etree.SubElement(envelope, util.nspath_eval('gml:upperCorner', nsmap)).text = '%s %s' % (bbox2[3], bbox2[2])

        return where
    return None
Beispiel #7
0
def _get_pt_freetext(val, language):
    freetext = etree.Element(
        util.nspath_eval('gm03:GM03_2_1Core.Core.PT_FreeText', NAMESPACES))
    textgroup = etree.SubElement(
        freetext, util.nspath_eval('gm03:textGroup', NAMESPACES))
    ptgroup = etree.SubElement(
        textgroup,
        util.nspath_eval('gm03:GM03_2_1Core.Core.PT_Group', NAMESPACES))
    if language:
        etree.SubElement(ptgroup, util.nspath_eval('gm03:language',
                                                   NAMESPACES)).text = language
    etree.SubElement(ptgroup, util.nspath_eval('gm03:plainText',
                                               NAMESPACES)).text = val

    return freetext
Beispiel #8
0
def write_extent(bbox):
    ''' Generate BBOX extent '''

    if bbox is not None:
        try:
            bbox2 = util.wkt2geom(bbox)
        except:
            return None

        spdom = etree.Element('spdom')
        bounding = etree.SubElement(spdom, 'bounding')
        etree.SubElement(bounding, 'westbc').text = str(bbox2[0])
        etree.SubElement(bounding, 'eastbc').text = str(bbox2[2])
        etree.SubElement(bounding, 'northbc').text = str(bbox2[3])
        etree.SubElement(bounding, 'southbc').text = str(bbox2[1])
        return spdom
    return None
Beispiel #9
0
def gen_sitemap(context, database, table, url, output_file):
    """generate an XML sitemap from all records in repository"""

    # get configuration and init repo connection
    repos = repository.Repository(database, context, table=table)

    # write out sitemap document
    urlset = etree.Element(util.nspath_eval('sitemap:urlset',
                                            context.namespaces),
                           nsmap=context.namespaces)

    schema_loc = util.nspath_eval('xsi:schemaLocation', context.namespaces)

    urlset.attrib[schema_loc] = \
        '%s http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd' % \
        context.namespaces['sitemap']

    # get all records
    count, records = repos.query(constraint={}, maxrecords=99999999)

    LOGGER.info('Found %s records', count)

    for rec in records:
        url_ = etree.SubElement(
            urlset, util.nspath_eval('sitemap:url', context.namespaces))
        uri = '%s?service=CSW&version=2.0.2&request=GetRepositoryItem&id=%s' % \
            (url,
             getattr(rec,
                     context.md_core_model['mappings']['pycsw:Identifier']))
        etree.SubElement(url_,
                         util.nspath_eval('sitemap:loc',
                                          context.namespaces)).text = uri

    # write to file
    LOGGER.info('Writing to %s', output_file)
    with open(output_file, 'wb') as ofile:
        ofile.write(
            etree.tostring(urlset,
                           pretty_print=1,
                           encoding='utf8',
                           xml_declaration=1))
Beispiel #10
0
    def exceptionreport2diagnostic(self, element):
        """transform a CSW exception into an SRU diagnostic"""
        node = etree.Element(util.nspath_eval('zs:searchRetrieveResponse',
                                              self.namespaces),
                             nsmap=self.namespaces)

        etree.SubElement(node, util.nspath_eval(
            'zs:version', self.namespaces)).text = self.sru_version

        diagnostics = etree.SubElement(
            node, util.nspath_eval('zs:diagnostics', self.namespaces))

        diagnostic = etree.SubElement(
            diagnostics, util.nspath_eval('zs:diagnostic', self.namespaces))

        etree.SubElement(diagnostic, util.nspath_eval('zd:diagnostic', self.namespaces)).text = \
            'info:srw/diagnostic/1/7'

        etree.SubElement(diagnostic, util.nspath_eval('zd:message', self.namespaces)).text = \
            element.xpath('//ows:Exception/ows:ExceptionText|//ows20:Exception/ows20:ExceptionText', namespaces=self.context.namespaces)[0].text

        etree.SubElement(diagnostic, util.nspath_eval('zd:details', self.namespaces)).text = \
            element.xpath('//ows:Exception|//ows20:Exception', namespaces=self.context.namespaces)[0].attrib.get('exceptionCode')

        return node
Beispiel #11
0
    def _gen_soap_wrapper(self):
        """ Generate SOAP wrapper """
        LOGGER.info('Writing SOAP wrapper.')
        node = etree.Element(
            util.nspath_eval('soapenv:Envelope', self.context.namespaces),
            nsmap=self.context.namespaces
        )

        schema_location_ns = util.nspath_eval('xsi:schemaLocation',
                                              self.context.namespaces)
        node.attrib[schema_location_ns] = '%s %s' % (
            self.context.namespaces['soapenv'],
            self.context.namespaces['soapenv']
        )

        node2 = etree.SubElement(
            node, util.nspath_eval('soapenv:Body', self.context.namespaces))

        if self.exception:
            node3 = etree.SubElement(
                node2,
                util.nspath_eval('soapenv:Fault', self.context.namespaces)
            )
            node4 = etree.SubElement(
                node3,
                util.nspath_eval('soapenv:Code', self.context.namespaces)
            )

            etree.SubElement(
                node4,
                util.nspath_eval('soapenv:Value', self.context.namespaces)
            ).text = 'soap:Server'

            node4 = etree.SubElement(
                node3,
                util.nspath_eval('soapenv:Reason', self.context.namespaces)
            )

            etree.SubElement(
                node4,
                util.nspath_eval('soapenv:Text', self.context.namespaces)
            ).text = 'A server exception was encountered.'

            node4 = etree.SubElement(
                node3,
                util.nspath_eval('soapenv:Detail', self.context.namespaces)
            )
            node4.append(self.response)
        else:
            node2.append(self.response)

        self.response = node
Beispiel #12
0
    def _transform_element(self, parent, element, elname):
        """tests for existence of a given xpath, writes out text if exists"""

        xpath = self.metadata_formats[self.metadata_prefix][elname.split(':')[1]]
        if xpath.startswith('//'):
            value = element.xpath(xpath, namespaces=self.context.namespaces)
            if value:
                value = value[0].text
        else:  # bare string literal
            value = xpath
        el = etree.SubElement(parent, util.nspath_eval(elname, self.context.namespaces))
        if value:
            if elname == 'oai:setSpec': 
                value = None
                for k, v in self.metadata_sets.items():
                    if v[1] == elname:
                        value = k
                        break
            el.text = value
Beispiel #13
0
def write_record(result, esn, context, url=None):
    ''' Return csw:SearchResults child as lxml.etree.Element '''

    typename = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:Typename'])

    if typename == 'gm03:TRANSFER':
        # dump record as is and exit
        # TODO: provide brief and summary elementsetname's
        return etree.fromstring(
            util.getqattr(result,
                          context.md_core_model['mappings']['pycsw:XML']),
            context.parser)

    node = etree.Element(util.nspath_eval('gm03:TRANSFER', NAMESPACES),
                         nsmap=NAMESPACES)

    header = etree.SubElement(
        node, util.nspath_eval('gm03:HEADERSECTION', NAMESPACES))
    header.attrib['version'] = '2.3'
    header.attrib['sender'] = 'pycsw'

    etree.SubElement(header, util.nspath_eval('gm03:MODELS', NAMESPACES))

    data = etree.SubElement(node,
                            util.nspath_eval('gm03:DATASECTION', NAMESPACES))

    core = etree.SubElement(
        data, util.nspath_eval('gm03:GM03_2_1Core.Core', NAMESPACES))
    core_meta = etree.SubElement(
        core, util.nspath_eval('gm03:GM03_2_1Core.Core.MD_Metadata',
                               NAMESPACES))

    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Identifier'])
    etree.SubElement(core_meta,
                     util.nspath_eval('gm03:fileIdentifier',
                                      NAMESPACES)).text = val

    language = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:Language'])
    etree.SubElement(core_meta, util.nspath_eval('gm03:language',
                                                 NAMESPACES)).text = language

    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Modified'])
    etree.SubElement(core_meta, util.nspath_eval('gm03:dateStamp',
                                                 NAMESPACES)).text = val

    hierarchy_level_val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:Type'])

    # metadata standard name
    standard = etree.SubElement(
        core_meta, util.nspath_eval('gm03:metadataStandardName',
                                    NAMESPACES)).text = 'GM03'

    # metadata standard version
    standardver = etree.SubElement(
        core_meta, util.nspath_eval('gm03:metadataStandardVersion',
                                    NAMESPACES)).text = '2.3'

    # hierarchy level
    hierarchy_level = etree.SubElement(
        core_meta, util.nspath_eval('gm03:hierarchyLevel', NAMESPACES))
    scope_code = etree.SubElement(
        hierarchy_level,
        util.nspath_eval('gm03:GM03_2_1Core.Core.MD_ScopeCode_', NAMESPACES))
    etree.SubElement(scope_code,
                     util.nspath_eval('gm03:value',
                                      NAMESPACES)).text = hierarchy_level_val

    # parent identifier
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:ParentIdentifier'])
    parent_identifier = etree.SubElement(
        core_meta, util.nspath_eval('gm03:parentIdentifier', NAMESPACES))
    scope_code = etree.SubElement(
        parent_identifier,
        util.nspath_eval('gm03:GM03_2_1Core.Core.MD_ScopeCode_', NAMESPACES))
    etree.SubElement(scope_code, util.nspath_eval('gm03:value',
                                                  NAMESPACES)).text = val

    # title
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Title'])
    citation = etree.SubElement(
        core, util.nspath_eval('gm03:GM03_2_1Core.Core.CI_Citation',
                               NAMESPACES))
    title = etree.SubElement(citation,
                             util.nspath_eval('gm03:title', NAMESPACES))
    title.append(_get_pt_freetext(val, language))

    # abstract
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Abstract'])
    data_ident = etree.SubElement(
        core,
        util.nspath_eval('gm03:GM03_2_1Core.Core.MD_DataIdentification',
                         NAMESPACES))
    abstract = etree.SubElement(data_ident,
                                util.nspath_eval('gm03:abstract', NAMESPACES))
    abstract.append(_get_pt_freetext(val, language))

    # resource language
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:ResourceLanguage'])
    if val:
        topicategory = etree.SubElement(
            data_ident, util.nspath_eval('gm03:language', NAMESPACES))
        cat_code = etree.SubElement(
            topicategory,
            util.nspath_eval('gm03:CodeISO.LanguageCodeISO_', NAMESPACES))
        etree.SubElement(cat_code, util.nspath_eval('gm03:value',
                                                    NAMESPACES)).text = val

    # topic category
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:TopicCategory'])
    if val:
        topicategory = etree.SubElement(
            data_ident, util.nspath_eval('gm03:topicCategory', NAMESPACES))
        cat_code = etree.SubElement(
            topicategory,
            util.nspath_eval('gm03:GM03_2_1Core.Core.MD_TopicCategoryCode_',
                             NAMESPACES))
        etree.SubElement(cat_code, util.nspath_eval('gm03:value',
                                                    NAMESPACES)).text = val

    # keywords
    keywords_val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:Keywords'])

    if keywords_val:
        md_keywords = etree.SubElement(
            core,
            util.nspath_eval('gm03:GM03_2_1Core.Core.MD_Keywords', NAMESPACES))

        val = util.getqattr(
            result, context.md_core_model['mappings']['pycsw:KeywordType'])
        if val:
            etree.SubElement(md_keywords,
                             util.nspath_eval('gm03:type',
                                              NAMESPACES)).text = val

        keyword = etree.SubElement(
            md_keywords, util.nspath_eval('gm03:keyword', NAMESPACES))
        for kw in keywords_val.split(','):
            keyword.append(_get_pt_freetext(kw, language))

    # format
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Format'])
    if val:
        md_format = etree.SubElement(
            core,
            util.nspath_eval('gm03:GM03_2_1Core.Core.MD_Format', NAMESPACES))
        etree.SubElement(md_format, util.nspath_eval('gm03:name',
                                                     NAMESPACES)).text = val

    # creation date
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:CreationDate'])
    if val:
        ci_date = etree.SubElement(
            core, util.nspath_eval('gm03:GM03_2_1Core.Core.CI_Date',
                                   NAMESPACES))
        etree.SubElement(ci_date, util.nspath_eval('gm03:date',
                                                   NAMESPACES)).text = val
        etree.SubElement(ci_date,
                         util.nspath_eval('gm03:dateType',
                                          NAMESPACES)).text = 'creation'

    # revision date
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:RevisionDate'])
    if val:
        ci_date = etree.SubElement(
            core, util.nspath_eval('gm03:GM03_2_1Core.Core.CI_Date',
                                   NAMESPACES))
        etree.SubElement(ci_date, util.nspath_eval('gm03:date',
                                                   NAMESPACES)).text = val
        etree.SubElement(ci_date,
                         util.nspath_eval('gm03:dateType',
                                          NAMESPACES)).text = 'revision'

    # publication date
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:PublicationDate'])
    if val:
        ci_date = etree.SubElement(
            core, util.nspath_eval('gm03:GM03_2_1Core.Core.CI_Date',
                                   NAMESPACES))
        etree.SubElement(ci_date, util.nspath_eval('gm03:date',
                                                   NAMESPACES)).text = val
        etree.SubElement(ci_date,
                         util.nspath_eval('gm03:dateType',
                                          NAMESPACES)).text = 'publication'

    # bbox extent
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:BoundingBox'])
    bboxel = write_extent(val, context.namespaces)
    if bboxel is not None:
        core.append(bboxel)

    # geographic description
    val = util.getqattr(
        result,
        context.md_core_model['mappings']['pycsw:GeographicDescriptionCode'])
    if val:
        geo_desc = etree.SubElement(
            core,
            util.nspath_eval('gm03:GM03_2_1Core.Core.EX_GeographicDescription',
                             NAMESPACES))
        etree.SubElement(
            geo_desc, util.nspath_eval('gm03:geographicIdentifier',
                                       NAMESPACES)).text = val

    # crs
    val = util.getqattr(result, context.md_core_model['mappings']['pycsw:CRS'])
    if val:
        rs_identifier = etree.SubElement(
            core,
            util.nspath_eval('gm03:GM03_2_1Core.Core.RS_Identifier',
                             NAMESPACES))
        rs_code = etree.SubElement(rs_identifier,
                                   util.nspath_eval('gm03:code', NAMESPACES))
        rs_code.append(_get_pt_freetext(val, language))

    # temporal extent
    time_begin = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:TempExtent_begin'])
    time_end = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:TempExtent_end'])
    if time_begin:
        temp_ext = etree.SubElement(
            core,
            util.nspath_eval('gm03:GM03_2_1Core.Core.EX_TemporalExtent',
                             NAMESPACES))
        extent = etree.SubElement(temp_ext,
                                  util.nspath_eval('gm03:extent', NAMESPACES))
        tm_primitive = etree.SubElement(
            extent,
            util.nspath_eval('gm03:GM03_2_1Core.Core.TM_Primitive',
                             NAMESPACES))
        etree.SubElement(tm_primitive,
                         util.nspath_eval('gm03:begin',
                                          NAMESPACES)).text = time_begin
        if time_end:
            etree.SubElement(tm_primitive,
                             util.nspath_eval('gm03:end',
                                              NAMESPACES)).text = time_end

    # links
    rlinks = util.getqattr(result,
                           context.md_core_model['mappings']['pycsw:Links'])
    if rlinks:
        for link in util.jsonify_links(rlinks):
            online_resource = etree.SubElement(
                core,
                util.nspath_eval('gm03:GM03_2_1Core.Core.OnlineResource',
                                 NAMESPACES))
            if link['protocol']:
                etree.SubElement(
                    online_resource,
                    util.nspath_eval('gm03:protocol',
                                     NAMESPACES)).text = link['protocol']
            if link['description']:
                desc = etree.SubElement(
                    online_resource,
                    util.nspath_eval('gm03:description', NAMESPACES))
                desc.append(_get_pt_freetext(link['description'], language))
            if link['name']:
                name_el = etree.SubElement(
                    online_resource, util.nspath_eval('gm03:name', NAMESPACES))
                name_el.append(_get_pt_freetext(link['name'], language))
            linkage = etree.SubElement(
                online_resource, util.nspath_eval('gm03:linkage', NAMESPACES))
            linkage.append(_get_pt_freeurl(link['url'], language))

    return node
Beispiel #14
0
def evaluate_literal(context, pname, pvalue):
    """
    Transforms OpenSearch EO mathematical notation
    to OGC FES syntax

    :param pname: parameter name
    :param pvalue: parameter value

    :returns: lxml Element of predicate
    """

    LOGGER.debug('property name: {}'.format(pname))
    LOGGER.debug('property value: {}'.format(pvalue))

    if pvalue.startswith('{') and pvalue.endswith('}'):
        # {n1,n2,…} equals to field=n1 OR field=n2 OR …
        values = pvalue.lstrip('{').rstrip('}').split(',')
        el = etree.Element(util.nspath_eval('ogc:Or', context.namespaces))

        for value in values:
            el2 = etree.SubElement(el, util.nspath_eval('ogc:PropertyIsEqualTo', context.namespaces))
            etree.SubElement(el2, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
            etree.SubElement(el2, util.nspath_eval('ogc:Literal', context.namespaces)).text = value

    elif pvalue.startswith('[') and pvalue.endswith(']'):
        # [n1,n2] equal to n1 <= field <= n2
        values = pvalue.lstrip('[').rstrip(']').split(',')
        el = etree.Element(util.nspath_eval('ogc:And', context.namespaces))

        el2 = etree.SubElement(el, util.nspath_eval('ogc:PropertyIsLessThanOrEqualTo', context.namespaces))
        etree.SubElement(el2, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el2, util.nspath_eval('ogc:Literal', context.namespaces)).text = values[0]

        el3 = etree.SubElement(el, util.nspath_eval('ogc:PropertyIsGreaterThanOrEqualTo', context.namespaces))
        etree.SubElement(el3, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el3, util.nspath_eval('ogc:Literal', context.namespaces)).text = values[1]

    elif pvalue.startswith(']') and pvalue.endswith('['):
        # ]n1,n2[ equals to n1 < field < n2
        values = pvalue.lstrip(']').rstrip('[').split(',')
        el = etree.Element(util.nspath_eval('ogc:And', context.namespaces))

        el2 = etree.SubElement(el, util.nspath_eval('ogc:PropertyIsLessThan', context.namespaces))
        etree.SubElement(el2, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el2, util.nspath_eval('ogc:Literal', context.namespaces)).text = values[0]

        el3 = etree.SubElement(el, util.nspath_eval('ogc:PropertyIsGreaterThan', context.namespaces))
        etree.SubElement(el3, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el3, util.nspath_eval('ogc:Literal', context.namespaces)).text = values[1]

    elif pvalue.startswith('['):
        # [n1 equals to n1<= field
        el = etree.Element(util.nspath_eval('ogc:PropertyIsGreaterThanOrEqualTo', context.namespaces))
        etree.SubElement(el, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el, util.nspath_eval('ogc:Literal', context.namespaces)).text = pvalue.lstrip('[')

    elif pvalue.endswith(']'):
        # n2] equals to field <= n2
        el = etree.Element(util.nspath_eval('ogc:PropertyIsLessThanOrEqualTo', context.namespaces))
        etree.SubElement(el, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el, util.nspath_eval('ogc:Literal', context.namespaces)).text = pvalue.rstrip(']')

    elif pvalue.startswith('[') and pvalue.endswith('['):
        # [n1,n2[ equals to n1 <= field < n2
        values = pvalue.lstrip('[').rstrip('[').split(',')
        el = etree.Element(util.nspath_eval('ogc:And', context.namespaces))

        el2 = etree.SubElement(el, util.nspath_eval('ogc:PropertyIsLessThanOrEqualTo', context.namespaces))
        etree.SubElement(el2, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el2, util.nspath_eval('ogc:Literal', context.namespaces)).text = values[0]

        el3 = etree.SubElement(el, util.nspath_eval('ogc:PropertyIsGreaterThan', context.namespaces))
        etree.SubElement(el3, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el3, util.nspath_eval('ogc:Literal', context.namespaces)).text = values[1]

    elif pvalue.startswith(']') and pvalue.endswith(']'):
        # ]n1,n2] equal to n1 < field <= n2
        values = pvalue.lstrip(']').rstrip(']').split(',')
        el = etree.Element(util.nspath_eval('ogc:And', context.namespaces))

        el2 = etree.SubElement(el, util.nspath_eval('ogc:PropertyIsLessThan', context.namespaces))
        etree.SubElement(el2, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el2, util.nspath_eval('ogc:Literal', context.namespaces)).text = values[0]

        el3 = etree.SubElement(el, util.nspath_eval('ogc:PropertyIsGreaterThanOrEqualTo', context.namespaces))
        etree.SubElement(el3, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el3, util.nspath_eval('ogc:Literal', context.namespaces)).text = values[1]

    elif pvalue.startswith(']'):
        # ]n1 equals to n1 < field
        el = etree.Element(util.nspath_eval('ogc:PropertyIsGreaterThan', context.namespaces))
        etree.SubElement(el, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el, util.nspath_eval('ogc:Literal', context.namespaces)).text = pvalue.lstrip(']')

    elif pvalue.endswith('['):
        # n2[ equals to field < n2
        el = etree.Element(util.nspath_eval('ogc:PropertyIsLessThan', context.namespaces))
        etree.SubElement(el, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el, util.nspath_eval('ogc:Literal', context.namespaces)).text = pvalue.rstrip('[')

    else:
        # n1 equal to field = n1
        el = etree.Element(util.nspath_eval('ogc:PropertyIsEqualTo', context.namespaces))
        etree.SubElement(el, util.nspath_eval('ogc:PropertyName', context.namespaces)).text = pname
        etree.SubElement(el, util.nspath_eval('ogc:Literal', context.namespaces)).text = pvalue

    return el
Beispiel #15
0
def kvp2filterxml(kvp, context, profiles, fes_version='1.0'):
    ''' transform kvp to filter XML string '''

    bbox_element = None
    time_element = None
    anytext_elements = []
    query_temporal_by_iso = False

    eo_parentidentifier_element = None
    eo_bands_element = None
    eo_cloudcover_element = None
    eo_instrument_element = None
    eo_orbitdirection_element = None
    eo_orbitnumber_element = None
    eo_platform_element = None
    eo_processinglevel_element = None
    eo_producttype_element = None
    eo_sensortype_element = None
    eo_snowcover_element = None

    if profiles is not None and 'plugins' in profiles and 'APISO' in profiles['plugins']:
        query_temporal_by_iso = True

    # Count parameters
    par_count = 0
    for p in ['q','bbox','time']:
        if p in kvp and kvp[p] != '':
            par_count += 1

    # Create root element for FilterXML
    root = etree.Element(util.nspath_eval('ogc:Filter', context.namespaces))

    # bbox to FilterXML
    if 'bbox' in kvp and kvp['bbox'] != '':
        LOGGER.debug('Detected bbox parameter')
        bbox_list = [x.strip() for x in kvp['bbox'].split(',')]
        bbox_element = etree.Element(util.nspath_eval('ogc:BBOX',
                    context.namespaces))
        el = etree.Element(util.nspath_eval('ogc:PropertyName',
                    context.namespaces))
        el.text = 'ows:BoundingBox'
        bbox_element.append(el)
        env = etree.Element(util.nspath_eval('gml:Envelope',
                    context.namespaces))
        el = etree.Element(util.nspath_eval('gml:lowerCorner',
                    context.namespaces))

        if len(bbox_list) == 5:  # add srsName
            LOGGER.debug('Found CRS')
            env.attrib['srsName'] = bbox_list[4]
        else:
            LOGGER.debug('Assuming 4326')
            env.attrib['srsName'] = 'urn:ogc:def:crs:OGC:1.3:CRS84'
            if not validate_4326(bbox_list):
                msg = '4326 coordinates out of range: %s' % bbox_list
                LOGGER.error(msg)
                raise RuntimeError(msg)

        try:
            el.text = "%s %s" % (bbox_list[0], bbox_list[1])
        except Exception as err:
            errortext = 'Exception: OpenSearch bbox not valid.\nError: %s.' % str(err)
            LOGGER.exception(errortext)
        env.append(el)
        el = etree.Element(util.nspath_eval('gml:upperCorner',
                    context.namespaces))
        try:
            el.text = "%s %s" % (bbox_list[2], bbox_list[3])
        except Exception as err:
            errortext = 'Exception: OpenSearch bbox not valid.\nError: %s.' % str(err)
            LOGGER.exception(errortext)
        env.append(el)
        bbox_element.append(env)

    # q to FilterXML
    if 'q' in kvp and kvp['q'] != '':
        LOGGER.debug('Detected q parameter')
        qvals = kvp['q'].split()
        LOGGER.debug(qvals)
        if len(qvals) > 1:
            par_count += 1
        for qval in qvals:
            LOGGER.debug('processing q token')
            anytext_element = etree.Element(util.nspath_eval('ogc:PropertyIsEqualTo',
                        context.namespaces))
            el = etree.Element(util.nspath_eval('ogc:PropertyName',
                        context.namespaces))
            el.text = 'csw:AnyText'
            anytext_element.append(el)
            el = etree.Element(util.nspath_eval('ogc:Literal',
                        context.namespaces))
            el.text = qval
            anytext_element.append(el)
            anytext_elements.append(anytext_element)

    if ('start' in kvp or 'stop' in kvp) and 'time' not in kvp:
        LOGGER.debug('Detected start/stop in KVP')
        kvp['time'] = ''
        if 'start' in kvp and kvp['start'] != '':
            kvp['time'] = kvp['start'] + '/'
        if 'stop' in kvp and kvp['stop'] != '':
            if len(kvp['time']) > 0:
                kvp['time'] += kvp['stop']
            else:
                kvp['time'] = '/' + kvp['stop']
            LOGGER.debug('new KVP time: {}'.format(kvp['time']))

    # time to FilterXML
    if 'time' in kvp and kvp['time'] != '':
        LOGGER.debug('Detected time parameter %s', kvp['time'])
        time_list = kvp['time'].split("/")

        LOGGER.debug('TIMELIST: %s', time_list) 

        if len(time_list) == 2:
            if '' not in time_list:  # both dates present
                LOGGER.debug('Both dates present')
                if query_temporal_by_iso:
                    LOGGER.debug('Querying by ISO data extent')
                    time_element = etree.Element(util.nspath_eval('ogc:And',
                                   context.namespaces))
    
                    begin_element = etree.Element(util.nspath_eval('ogc:PropertyIsGreaterThanOrEqualTo',
                                    context.namespaces))
                    etree.SubElement(begin_element, util.nspath_eval('ogc:PropertyName',
                                    context.namespaces)).text = 'apiso:TempExtent_begin'
                    etree.SubElement(begin_element, util.nspath_eval('ogc:Literal',
                                     context.namespaces)).text = time_list[0]
    
                    end_element = etree.Element(util.nspath_eval('ogc:PropertyIsLessThanOrEqualTo',
                                  context.namespaces))
                    etree.SubElement(end_element, util.nspath_eval('ogc:PropertyName',
                                     context.namespaces)).text = 'apiso:TempExtent_end'
                    etree.SubElement(end_element, util.nspath_eval('ogc:Literal',
                                     context.namespaces)).text = time_list[1]
    
                    time_element.append(begin_element)
                    time_element.append(end_element)

                else:
                    LOGGER.debug('Querying by DC date')
                    time_element = etree.Element(util.nspath_eval('ogc:PropertyIsBetween',
                                   context.namespaces))
                    el = etree.Element(util.nspath_eval('ogc:PropertyName',
                                       context.namespaces))
                    el.text = 'dc:date'
                    time_element.append(el)
                    el = etree.Element(util.nspath_eval('ogc:LowerBoundary',
                                       context.namespaces))
                    el2 = etree.Element(util.nspath_eval('ogc:Literal',
                                        context.namespaces))
                    el2.text = time_list[0]
                    el.append(el2)
                    time_element.append(el)
                    el = etree.Element(util.nspath_eval('ogc:UpperBoundary',
                                context.namespaces))
                    el2 = etree.Element(util.nspath_eval('ogc:Literal',
                                context.namespaces))
                    el2.text = time_list[1]
                    el.append(el2)
                    time_element.append(el)
    
            else:   # one is empty
                LOGGER.debug('Querying by open-ended date')
                if time_list == ['', '']:
                    par_count -= 1
                # One of two is empty
                elif time_list[1] == '':  # start datetime but no end datetime
                    time_element = etree.Element(util.nspath_eval('ogc:PropertyIsGreaterThanOrEqualTo',
                                context.namespaces))
                    el = etree.Element(util.nspath_eval('ogc:PropertyName',
                                context.namespaces))
                    if query_temporal_by_iso:
                        el.text = 'apiso:TempExtent_begin'
                    else:
                        el.text = 'dc:date'
                    time_element.append(el)
                    el = etree.Element(util.nspath_eval('ogc:Literal',
                                context.namespaces))
                    el.text = time_list[0]
                    time_element.append(el)
                else:  # end datetime but no start datetime
                    time_element = etree.Element(util.nspath_eval('ogc:PropertyIsLessThanOrEqualTo',
                                context.namespaces))
                    el = etree.Element(util.nspath_eval('ogc:PropertyName',
                                context.namespaces))
                    if query_temporal_by_iso:
                        el.text = 'apiso:TempExtent_end'
                    else:
                        el.text = 'dc:date'
                    time_element.append(el)
                    el = etree.Element(util.nspath_eval('ogc:Literal',
                                context.namespaces))
                    el.text = time_list[1]
                    time_element.append(el)
        elif ((len(time_list) == 1) and ('' not in time_list)):
            LOGGER.debug('Querying time instant via dc:date')
            # This is an equal request
            time_element = etree.Element(util.nspath_eval('ogc:PropertyIsEqualTo',
                        context.namespaces))
            el = etree.Element(util.nspath_eval('ogc:PropertyName',
                        context.namespaces))
            el.text = 'dc:date'
            time_element.append(el)
            el = etree.Element(util.nspath_eval('ogc:Literal',
                        context.namespaces))
            el.text = time_list[0]
            time_element.append(el)
        else:
            # Error
            errortext = 'Exception: OpenSearch time not valid: %s.' % str(kvp['time'])
            LOGGER.error(errortext)

    LOGGER.debug('Processing EO queryables')
    if not util.is_none_or_empty(kvp.get('eo:parentidentifier')):
        par_count += 1
        eo_parentidentifier_element = etree.Element(util.nspath_eval('ogc:PropertyIsEqualTo', context.namespaces))
        etree.SubElement(eo_parentidentifier_element,
           util.nspath_eval('ogc:PropertyName', context.namespaces)).text = 'apiso:ParentIdentifier'
        etree.SubElement(eo_parentidentifier_element, util.nspath_eval(
            'ogc:Literal', context.namespaces)).text = kvp['eo:parentidentifier']

    if not util.is_none_or_empty(kvp.get('eo:producttype')):
        par_count += 1
        eo_producttype_element = etree.Element(util.nspath_eval('ogc:PropertyIsLike', context.namespaces),
            matchCase='false', wildCard='*', singleChar='?', escapeChar='\\')
        etree.SubElement(eo_producttype_element,
           util.nspath_eval('ogc:PropertyName', context.namespaces)).text = 'apiso:Subject'
        etree.SubElement(eo_producttype_element, util.nspath_eval(
            'ogc:Literal', context.namespaces)).text = '*eo:productType:%s*' % kvp['eo:producttype']

    if not util.is_none_or_empty(kvp.get('eo:platform')):
        par_count += 1
        eo_platform_element = etree.Element(util.nspath_eval('ogc:PropertyIsEqualTo', context.namespaces))
        etree.SubElement(eo_platform_element,
           util.nspath_eval('ogc:PropertyName', context.namespaces)).text = 'apiso:Platform'
        etree.SubElement(eo_platform_element, util.nspath_eval(
            'ogc:Literal', context.namespaces)).text = kvp['eo:platform']

    if not util.is_none_or_empty(kvp.get('eo:processinglevel')):
        par_count += 1
        eo_processinglevel_element = etree.Element(util.nspath_eval('ogc:PropertyIsLike', context.namespaces),
            matchCase='false', wildCard='*', singleChar='?', escapeChar='\\')
        etree.SubElement(eo_processinglevel_element,
           util.nspath_eval('ogc:PropertyName', context.namespaces)).text = 'apiso:Subject'
        etree.SubElement(eo_processinglevel_element, util.nspath_eval(
            'ogc:Literal', context.namespaces)).text = '*eo:processingLevel:%s*' % kvp['eo:processinglevel']

    if not util.is_none_or_empty(kvp.get('eo:instrument')):
        par_count += 1
        eo_instrument_element = etree.Element(util.nspath_eval('ogc:PropertyIsEqualTo', context.namespaces))
        etree.SubElement(eo_instrument_element,
           util.nspath_eval('ogc:PropertyName', context.namespaces)).text = 'apiso:Instrument'
        etree.SubElement(eo_instrument_element, util.nspath_eval(
            'ogc:Literal', context.namespaces)).text = kvp['eo:instrument']

    if not util.is_none_or_empty(kvp.get('eo:sensortype')):
        par_count += 1
        eo_sensortype_element = etree.Element(util.nspath_eval('ogc:PropertyIsEqualTo', context.namespaces))
        etree.SubElement(eo_sensortype_element,
           util.nspath_eval('ogc:PropertyName', context.namespaces)).text = 'apiso:SensorType'
        etree.SubElement(eo_sensortype_element, util.nspath_eval(
            'ogc:Literal', context.namespaces)).text = kvp['eo:sensortype']

    if not util.is_none_or_empty(kvp.get('eo:cloudcover')):
        par_count += 1
        eo_cloudcover_element = evaluate_literal(context, 'apiso:CloudCover', kvp['eo:cloudcover'])

    if not util.is_none_or_empty(kvp.get('eo:snowcover')):
        par_count += 1
        eo_snowcover_element = etree.Element(util.nspath_eval('ogc:PropertyIsLike', context.namespaces),
            matchCase='false', wildCard='*', singleChar='?', escapeChar='\\')
        etree.SubElement(eo_snowcover_element,
           util.nspath_eval('ogc:PropertyName', context.namespaces)).text = 'apiso:Subject'
        etree.SubElement(eo_snowcover_element, util.nspath_eval(
            'ogc:Literal', context.namespaces)).text = '*eo:snowCover:%s*' % kvp['eo:snowcover']

    if not util.is_none_or_empty(kvp.get('eo:spectralrange')):
        par_count += 1
        eo_bands_element = etree.Element(util.nspath_eval('ogc:PropertyIsLike', context.namespaces),
            matchCase='false', wildCard='*', singleChar='?', escapeChar='\\')
        etree.SubElement(eo_bands_element,
           util.nspath_eval('ogc:PropertyName', context.namespaces)).text = 'apiso:Bands'
        etree.SubElement(eo_bands_element, util.nspath_eval(
            'ogc:Literal', context.namespaces)).text = '*%s*' % kvp['eo:spectralrange']

    if not util.is_none_or_empty(kvp.get('eo:orbitnumber')):
        par_count += 1
        eo_orbitnumber_element = etree.Element(util.nspath_eval('ogc:PropertyIsLike', context.namespaces),
            matchCase='false', wildCard='*', singleChar='?', escapeChar='\\')
        etree.SubElement(eo_orbitnumber_element,
           util.nspath_eval('ogc:PropertyName', context.namespaces)).text = 'apiso:Subject'
        etree.SubElement(eo_orbitnumber_element, util.nspath_eval(
            'ogc:Literal', context.namespaces)).text = '*eo:orbitNumber:%s*' % kvp['eo:orbitnumber']

    if not util.is_none_or_empty(kvp.get('eo:orbitdirection')):
        par_count += 1
        eo_orbitdirection_element = etree.Element(util.nspath_eval('ogc:PropertyIsLike', context.namespaces),
            matchCase='false', wildCard='*', singleChar='?', escapeChar='\\')
        etree.SubElement(eo_orbitdirection_element,
           util.nspath_eval('ogc:PropertyName', context.namespaces)).text = 'apiso:Subject'
        etree.SubElement(eo_orbitdirection_element, util.nspath_eval(
            'ogc:Literal', context.namespaces)).text = '*eo:orbitDirection:%s*' % kvp['eo:orbitdirection']

    LOGGER.info('Query parameter count: %s', par_count)
    if par_count == 0:
        return ''
    elif par_count == 1:
        LOGGER.debug('Single predicate filter')
        # Only one OpenSearch parameter exists
        if 'bbox' in kvp and kvp['bbox'] != '':
            LOGGER.debug('Adding bbox')
            root.append(bbox_element)
        elif time_element is not None:
            LOGGER.debug('Adding time')
            root.append(time_element)
        elif anytext_elements:
            LOGGER.debug('Adding anytext')
            root.extend(anytext_elements)
    elif par_count > 1:
        LOGGER.debug('ogc:And query (%d predicates)', par_count)
        # Since more than 1 parameter, append the AND logical operator
        logical_and = etree.Element(util.nspath_eval('ogc:And',
                context.namespaces))
        if bbox_element is not None:
            logical_and.append(bbox_element)
        if time_element is not None:
            logical_and.append(time_element)
        if anytext_elements is not None:
            logical_and.extend(anytext_elements)
        root.append(logical_and)

    if par_count == 1:
        node_to_append = root
    elif par_count > 1:
        node_to_append = logical_and

    LOGGER.debug('Adding EO queryables')
    for eo_element in [eo_producttype_element, eo_platform_element, eo_instrument_element,
                       eo_sensortype_element, eo_cloudcover_element, eo_snowcover_element,
                       eo_bands_element, eo_orbitnumber_element, eo_orbitdirection_element,
                       eo_processinglevel_element, eo_parentidentifier_element]:
        if eo_element is not None:
            node_to_append.append(eo_element)

    # Render etree to string XML
    LOGGER.debug(etree.tostring(root, encoding='unicode'))
    filterstring = etree.tostring(root, encoding='unicode')
    if fes_version == '2.0':
        filterstring = filterstring.replace('PropertyName', 'ValueReference')\
                                   .replace('xmlns:ogc="http://www.opengis.net/ogc"', 'xmlns:fes20="http://www.opengis.net/fes/2.0"')\
                                   .replace('ogc:', 'fes20:')
    return filterstring
Beispiel #16
0
    def write_record(self, result, esn, outputschema, queryables):
        ''' Return csw:SearchResults child as lxml.etree.Element '''

        specialPycswKeys = [
            constants.PYCSW_BOUNDING_BOX, constants.PYCSW_KEYWORDS,
            constants.PYCSW_LINKS
        ]

        specialDbcols = [queryables[x] for x in specialPycswKeys]

        typename = util.getqattr(
            result,
            self.context.md_core_model['mappings'][constants.PYCSW_TYPENAME])

        if typename == self.typename:
            # dump record as is and exit
            return etree.fromstring(
                util.getqattr(result, queryables[constants.PYCSW_XML]),
                self.context.parser)

        else:
            dbcol2xpath = _get_dbcol_to_xpath_dict(
                self.repository['queryables'])

            record = etree.Element(
                util.nspath_eval(self.typename, self.namespaces))

            # Sorted for consistency
            for dbcol in sorted(vars(result).keys()):
                value = util.getqattr(result, dbcol)
                if not dbcol.startswith('_') and value is not None:
                    elementName = dbcol2xpath.get(dbcol, None)
                    if elementName is not None:
                        if dbcol not in specialDbcols:
                            _build_xpath(record, elementName,
                                         self.context.namespaces, value)

                        elif dbcol == queryables[constants.PYCSW_KEYWORDS]:
                            for keyword in value.split(','):
                                etree.SubElement(
                                    record,
                                    util.nspath_eval(elementName,
                                                     self.context.namespaces)
                                ).text = keyword

                        elif dbcol == queryables[constants.PYCSW_LINKS]:
                            for link in value.split('^'):
                                linkComponents = link.split(',')
                                scheme = linkComponents[2]
                                uri = linkComponents[-1]
                                etree.SubElement(record,
                                                 util.nspath_eval(
                                                     elementName,
                                                     self.context.namespaces),
                                                 scheme=scheme).text = uri

                        elif dbcol == queryables[constants.PYCSW_BOUNDING_BOX]:
                            bbox = write_boundingbox(value,
                                                     self.context.namespaces)
                            record.append(bbox)

            return record
Beispiel #17
0
    def _csw3_2_os(self):
        """CSW 3.0.0 Capabilities to OpenSearch Description"""

        response_name = etree.QName(self.exml).localname
        if response_name == 'GetRecordsResponse':

            startindex = int(self.exml.xpath('//@nextRecord')[0]) - int(
                        self.exml.xpath('//@numberOfRecordsReturned')[0])
            if startindex < 1:
                startindex = 1

            node = etree.Element(util.nspath_eval('atom:feed',
                       self.context.namespaces), nsmap=self.namespaces)
            etree.SubElement(node, util.nspath_eval('atom:id',
                       self.context.namespaces)).text = self.cfg.get('server', 'url')
            etree.SubElement(node, util.nspath_eval('atom:title',
                       self.context.namespaces)).text = self.cfg.get('metadata:main',
                       'identification_title')
            author = etree.SubElement(node, util.nspath_eval('atom:author', self.context.namespaces))
            etree.SubElement(author, util.nspath_eval('atom:name', self.context.namespaces)).text = self.cfg.get('metadata:main',
                       'provider_name')
            etree.SubElement(node, util.nspath_eval('atom:link',
                       self.context.namespaces), rel='search',
                           type='application/opensearchdescription+xml',
                           href='%smode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities' % self.bind_url)

            etree.SubElement(node, util.nspath_eval('atom:updated',
                self.context.namespaces)).text = self.exml.xpath('//@timestamp')[0]

            etree.SubElement(node, util.nspath_eval('os:Query', self.context.namespaces), role='request')

            matched = sum(int(x) for x in self.exml.xpath('//@numberOfRecordsMatched'))

            etree.SubElement(node, util.nspath_eval('os:totalResults', self.context.namespaces)).text = str(matched)

            etree.SubElement(node, util.nspath_eval('os:startIndex',
                        self.context.namespaces)).text = str(startindex)

            returned = sum(int(x) for x in self.exml.xpath('//@numberOfRecordsReturned'))

            etree.SubElement(node, util.nspath_eval('os:itemsPerPage', self.context.namespaces)).text = str(returned)

            for rec in self.exml.xpath('//atom:entry', namespaces=self.context.namespaces):
                LOGGER.debug('ADDING ATOM ENTRY')
                node.append(rec)

            for rec in self.exml.xpath('//csw30:Record|//csw30:BriefRecord|//csw30:SummaryRecord', namespaces=self.context.namespaces):
                node.append(self.cswrecord2atom(rec))

        elif response_name == 'Capabilities':
            node = etree.Element(util.nspath_eval('os:OpenSearchDescription', self.namespaces), nsmap=self.namespaces)
            etree.SubElement(node, util.nspath_eval('os:ShortName', self.namespaces)).text = self.exml.xpath('//ows20:Title', namespaces=self.context.namespaces)[0].text[:16]
            etree.SubElement(node, util.nspath_eval('os:LongName', self.namespaces)).text = self.exml.xpath('//ows20:Title', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Description', self.namespaces)).text = self.exml.xpath('//ows20:Abstract', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Tags', self.namespaces)).text = ' '.join(x.text for x in self.exml.xpath('//ows20:Keyword', namespaces=self.context.namespaces))

            # Requirement-022
            node1 = etree.SubElement(node, util.nspath_eval('os:Url', self.namespaces))
            node1.set('type', 'application/xml')

            kvps = {
                'service': 'CSW',
                'version': '3.0.0',
                'request': 'GetRecords',
                'elementsetname': 'full',
                'typenames': 'csw:Record',
                'outputformat': 'application/xml',
                'outputschema': 'http://www.opengis.net/cat/csw/3.0',
                'recordids': '{geo:uid?}',
                'q': '{searchTerms?}',
                'bbox': '{geo:box?}',
                'time': '{time:start?}/{time:end?}',
                'start': '{time:start?}',
                'stop': '{time:end?}',
                'startposition': '{startIndex?}',
                'maxrecords': '{count?}',
                'eo:cloudCover': '{eo:cloudCover?}',
                'eo:instrument': '{eo:instrument?}',
                'eo:orbitDirection': '{eo:orbitDirection?}',
                'eo:orbitNumber': '{eo:orbitNumber?}',
                'eo:parentIdentifier': '{eo:parentIdentifier?}',
                'eo:platform': '{eo:platform?}',
                'eo:processingLevel': '{eo:processingLevel?}',
                'eo:productType': '{eo:productType?}',
                'eo:sensorType': '{eo:sensorType?}',
                'eo:snowCover': '{eo:snowCover?}',
                'eo:spectralRange': '{eo:spectralRange?}'
            }

            node1.set('template', '%s%s' % (self.bind_url,
                '&'.join('{}={}'.format(*i) for i in kvps.items())))

            # Requirement-023
            node1 = etree.SubElement(node, util.nspath_eval('os:Url', self.namespaces))
            node1.set('type', 'application/atom+xml')

            kvps['outputformat'] = r'application%2Fatom%2Bxml'
            kvps['mode'] = 'opensearch'

            node1.set('template', '%s%s' % (self.bind_url,
                '&'.join('{}={}'.format(*i) for i in kvps.items())))

            node1 = etree.SubElement(node, util.nspath_eval('os:Image', self.namespaces))
            node1.set('type', 'image/vnd.microsoft.icon')
            node1.set('width', '16')
            node1.set('height', '16')
            node1.text = 'https://pycsw.org/img/favicon.ico'

            os_query = etree.SubElement(node, util.nspath_eval('os:Query', self.namespaces), role='example', searchTerms='cat')

            etree.SubElement(node, util.nspath_eval('os:Developer', self.namespaces)).text = self.exml.xpath('//ows20:IndividualName', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Contact', self.namespaces)).text = self.exml.xpath('//ows20:ElectronicMailAddress', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Attribution', self.namespaces)).text = self.exml.xpath('//ows20:ProviderName', namespaces=self.context.namespaces)[0].text
        elif response_name == 'ExceptionReport':
            node = self.exml
        else:  # GetRecordById output
            node = etree.Element(util.nspath_eval('atom:feed',
                       self.context.namespaces), nsmap=self.namespaces)
            etree.SubElement(node, util.nspath_eval('atom:id',
                       self.context.namespaces)).text = self.cfg.get('server', 'url')
            etree.SubElement(node, util.nspath_eval('atom:title',
                       self.context.namespaces)).text = self.cfg.get('metadata:main',
                       'identification_title')
            #etree.SubElement(node, util.nspath_eval('atom:updated',
            #  self.context.namespaces)).text = self.exml.xpath('//@timestamp')[0]

            etree.SubElement(node, util.nspath_eval('os:totalResults',
                        self.context.namespaces)).text = '1'
            etree.SubElement(node, util.nspath_eval('os:startIndex',
                        self.context.namespaces)).text = '1'
            etree.SubElement(node, util.nspath_eval('os:itemsPerPage',
                        self.context.namespaces)).text = '1'

            for rec in self.exml.xpath('//atom:entry', namespaces=self.context.namespaces):
                #node.append(rec)
                node = rec
        return node
Beispiel #18
0
    def _csw2_2_os(self):
        """CSW 2.0.2 Capabilities to OpenSearch Description"""

        operation_name = etree.QName(self.exml).localname
        if operation_name == 'GetRecordsResponse':

            startindex = int(self.exml.xpath('//@nextRecord')[0]) - int(
                        self.exml.xpath('//@numberOfRecordsReturned')[0])
            if startindex < 1:
                startindex = 1

            node = etree.Element(util.nspath_eval('atom:feed',
                       self.context.namespaces), nsmap=self.namespaces)
            etree.SubElement(node, util.nspath_eval('atom:id',
                       self.context.namespaces)).text = self.cfg.get('server', 'url')
            etree.SubElement(node, util.nspath_eval('atom:title',
                       self.context.namespaces)).text = self.cfg.get('metadata:main',
                       'identification_title')
            #etree.SubElement(node, util.nspath_eval('atom:updated',
            #  self.context.namespaces)).text = self.exml.xpath('//@timestamp')[0]

            etree.SubElement(node, util.nspath_eval('os:totalResults',
                        self.context.namespaces)).text = self.exml.xpath(
                        '//@numberOfRecordsMatched')[0]
            etree.SubElement(node, util.nspath_eval('os:startIndex',
                        self.context.namespaces)).text = str(startindex)
            etree.SubElement(node, util.nspath_eval('os:itemsPerPage',
                        self.context.namespaces)).text = self.exml.xpath(
                        '//@numberOfRecordsReturned')[0]

            for rec in self.exml.xpath('//atom:entry',
                        namespaces=self.context.namespaces):
                node.append(rec)
            for rec in self.exml.xpath('//csw:Record|//csw:BriefRecord|//csw:SummaryRecord',
                        namespaces=self.context.namespaces):
                node.append(self.cswrecord2atom(rec))
        elif operation_name == 'Capabilities':
            node = etree.Element(util.nspath_eval('os:OpenSearchDescription', self.namespaces), nsmap=self.namespaces)
            etree.SubElement(node, util.nspath_eval('os:ShortName', self.namespaces)).text = self.exml.xpath('//ows:Title', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:LongName', self.namespaces)).text = self.exml.xpath('//ows:Title', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Description', self.namespaces)).text = self.exml.xpath('//ows:Abstract', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Tags', self.namespaces)).text = ' '.join(x.text for x in self.exml.xpath('//ows:Keyword', namespaces=self.context.namespaces))

            node1 = etree.SubElement(node, util.nspath_eval('os:Url', self.namespaces))
            node1.set('type', 'application/atom+xml')
            node1.set('method', 'get')

            kvps = {
                'mode': 'opensearch',
                'service': 'CSW',
                'version': '2.0.2',
                'request': 'GetRecords',
                'elementsetname': 'full',
                'typenames': 'csw:Record',
                'resulttype': 'results',
                'q': '{searchTerms?}',
                'bbox': '{geo:box?}',
                'time': '{time:start?}/{time:end?}',
                'start': '{time:start?}',
                'stop': '{time:end?}',
                'startposition': '{startIndex?}',
                'maxrecords': '{count?}',
                'eo:cloudCover': '{eo:cloudCover?}',
                'eo:instrument': '{eo:instrument?}',
                'eo:orbitDirection': '{eo:orbitDirection?}',
                'eo:orbitNumber': '{eo:orbitNumber?}',
                'eo:parentIdentifier': '{eo:parentIdentifier?}',
                'eo:platform': '{eo:platform?}',
                'eo:processingLevel': '{eo:processingLevel?}',
                'eo:productType': '{eo:productType?}',
                'eo:sensorType': '{eo:sensorType?}',
                'eo:snowCover': '{eo:snowCover?}',
                'eo:spectralRange': '{eo:spectralRange?}'
            }

            node1.set('template', '%s%s' % (self.bind_url,
                '&'.join('{}={}'.format(*i) for i in kvps.items())))


            #node1.set('template', '%smode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q={searchTerms?}&bbox={geo:box?}&time={time:start?}/{time:end?}&start={time:start?}&stop={time:end?}&startposition={startIndex?}&maxrecords={count?}' % self.bind_url)

            node1 = etree.SubElement(node, util.nspath_eval('os:Image', self.namespaces))
            node1.set('type', 'image/vnd.microsoft.icon')
            node1.set('width', '16')
            node1.set('height', '16')
            node1.text = 'https://pycsw.org/img/favicon.ico'

            etree.SubElement(node, util.nspath_eval('os:Developer', self.namespaces)).text = self.exml.xpath('//ows:IndividualName', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Context', self.namespaces)).text = self.exml.xpath('//ows:ElectronicMailAddress', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Attribution', self.namespaces)).text = self.exml.xpath('//ows:ProviderName', namespaces=self.context.namespaces)[0].text
        elif operation_name == 'ExceptionReport':
            node = self.exml
        else:  # return Description document
            node = etree.Element(util.nspath_eval('os:Description', self.context.namespaces))

        return node
Beispiel #19
0
def write_record(recobj, esn, context, url=None):
    ''' Return csw:SearchResults child as lxml.etree.Element '''
    typename = util.getqattr(
        recobj, context.md_core_model['mappings']['pycsw:Typename'])
    if esn == 'full' and typename == 'fgdc:metadata':
        # dump record as is and exit
        return etree.fromstring(
            util.getqattr(recobj,
                          context.md_core_model['mappings']['pycsw:XML']))

    node = etree.Element('metadata')
    node.attrib[util.nspath_eval('xsi:noNamespaceSchemaLocation', context.namespaces)] = \
    'http://www.fgdc.gov/metadata/fgdc-std-001-1998.xsd'

    idinfo = etree.SubElement(node, 'idinfo')
    # identifier
    etree.SubElement(idinfo, 'datasetid').text = util.getqattr(
        recobj, context.md_core_model['mappings']['pycsw:Identifier'])

    citation = etree.SubElement(idinfo, 'citation')
    citeinfo = etree.SubElement(citation, 'citeinfo')

    # title
    val = util.getqattr(recobj,
                        context.md_core_model['mappings']['pycsw:Title'])
    etree.SubElement(citeinfo, 'title').text = val

    # publisher
    publinfo = etree.SubElement(citeinfo, 'publinfo')
    val = util.getqattr(
        recobj, context.md_core_model['mappings']['pycsw:Publisher']) or ''
    etree.SubElement(publinfo, 'publish').text = val

    # origin
    val = util.getqattr(
        recobj, context.md_core_model['mappings']['pycsw:Creator']) or ''
    etree.SubElement(citeinfo, 'origin').text = val

    # keywords
    val = util.getqattr(recobj,
                        context.md_core_model['mappings']['pycsw:Keywords'])
    if val:
        keywords = etree.SubElement(idinfo, 'keywords')
        theme = etree.SubElement(keywords, 'theme')
        for v in val.split(','):
            etree.SubElement(theme, 'themekey').text = v

    # accessconstraints
    val = util.getqattr(
        recobj,
        context.md_core_model['mappings']['pycsw:AccessConstraints']) or ''
    etree.SubElement(idinfo, 'accconst').text = val

    # abstract
    descript = etree.SubElement(idinfo, 'descript')
    val = util.getqattr(
        recobj, context.md_core_model['mappings']['pycsw:Abstract']) or ''
    etree.SubElement(descript, 'abstract').text = val

    # time
    datebegin = util.getqattr(
        recobj, context.md_core_model['mappings']['pycsw:TempExtent_begin'])
    dateend = util.getqattr(
        recobj, context.md_core_model['mappings']['pycsw:TempExtent_end'])
    if all([datebegin, dateend]):
        timeperd = etree.SubElement(idinfo, 'timeperd')
        timeinfo = etree.SubElement(timeperd, 'timeinfo')
        rngdates = etree.SubElement(timeinfo, 'timeinfo')
        begdate = etree.SubElement(rngdates, 'begdate').text = datebegin
        enddate = etree.SubElement(rngdates, 'enddate').text = dateend

    # bbox extent
    val = util.getqattr(recobj,
                        context.md_core_model['mappings']['pycsw:BoundingBox'])
    bboxel = write_extent(val)
    if bboxel is not None:
        idinfo.append(bboxel)

    # contributor
    val = util.getqattr(
        recobj, context.md_core_model['mappings']['pycsw:Contributor']) or ''
    etree.SubElement(idinfo, 'datacred').text = val

    # direct
    spdoinfo = etree.SubElement(idinfo, 'spdoinfo')
    val = util.getqattr(recobj,
                        context.md_core_model['mappings']['pycsw:Type']) or ''
    etree.SubElement(spdoinfo, 'direct').text = val

    # formname
    distinfo = etree.SubElement(node, 'distinfo')
    stdorder = etree.SubElement(distinfo, 'stdorder')
    digform = etree.SubElement(stdorder, 'digform')
    digtinfo = etree.SubElement(digform, 'digtinfo')
    val = util.getqattr(
        recobj, context.md_core_model['mappings']['pycsw:Format']) or ''
    etree.SubElement(digtinfo, 'formname').text = val
    etree.SubElement(citeinfo, 'geoform').text = val

    # source
    lineage = etree.SubElement(node, 'lineage')
    srcinfo = etree.SubElement(lineage, 'srcinfo')
    srccite = etree.SubElement(srcinfo, 'srccite')
    sciteinfo = etree.SubElement(srccite, 'citeinfo')
    val = util.getqattr(
        recobj, context.md_core_model['mappings']['pycsw:Source']) or ''
    etree.SubElement(sciteinfo, 'title').text = val

    val = util.getqattr(
        recobj, context.md_core_model['mappings']['pycsw:Relation']) or ''
    etree.SubElement(citeinfo, 'onlink').text = val

    # links
    rlinks = util.getqattr(recobj,
                           context.md_core_model['mappings']['pycsw:Links'])
    if rlinks:
        for link in rlinks.split('^'):
            linkset = link.split(',')
            etree.SubElement(citeinfo, 'onlink',
                             type=linkset[2]).text = linkset[-1]

    # metd
    metainfo = etree.SubElement(node, 'metainfo')
    val = util.getqattr(
        recobj, context.md_core_model['mappings']['pycsw:Modified']) or ''
    etree.SubElement(metainfo, 'metd').text = val

    return node
Beispiel #20
0
def write_record(result, esn, context, url=None):
    ''' Return csw:SearchResults child as lxml.etree.Element '''

    typename = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:Typename'])

    if esn == 'full' and typename == 'atom:entry':
        # dump record as is and exit
        return etree.fromstring(
            util.getqattr(result,
                          context.md_core_model['mappings']['pycsw:XML']),
            context.parser)

    node = etree.Element(util.nspath_eval('atom:entry', NAMESPACES),
                         nsmap=NAMESPACES)
    node.attrib[util.nspath_eval('xsi:schemaLocation', context.namespaces)] = \
            '%s http://www.kbcafe.com/rss/atom.xsd.xml' % NAMESPACES['atom']

    # author
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Creator'])
    if val:
        author = etree.SubElement(node,
                                  util.nspath_eval('atom:author', NAMESPACES))
        etree.SubElement(author, util.nspath_eval('atom:name',
                                                  NAMESPACES)).text = val

    # category
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Keywords'])

    if val:
        for kw in val.split(','):
            etree.SubElement(node,
                             util.nspath_eval('atom:category', NAMESPACES),
                             term=kw)

    for qval in ['pycsw:Contributor', 'pycsw:Identifier']:
        val = util.getqattr(result, context.md_core_model['mappings'][qval])
        if val:
            etree.SubElement(
                node, util.nspath_eval(XPATH_MAPPINGS[qval],
                                       NAMESPACES)).text = val
            if qval == 'pycsw:Identifier':
                etree.SubElement(
                    node, util.nspath_eval('dc:identifier',
                                           context.namespaces)).text = val

    rlinks = util.getqattr(result,
                           context.md_core_model['mappings']['pycsw:Links'])
    if rlinks:
        for link in util.jsonify_links(rlinks):
            url2 = etree.SubElement(node,
                                    util.nspath_eval('atom:link', NAMESPACES),
                                    href=link['url'])

            if link['description']:
                url2.attrib['title'] = link['description']

            if link['protocol']:
                if link['protocol'] == 'enclosure':
                    url2.attrib['rel'] = link['protocol']
                    url2.attrib['type'] = 'application/octet-stream'
                else:
                    url2.attrib['type'] = link['protocol']

    etree.SubElement(
        node,
        util.nspath_eval('atom:link', NAMESPACES),
        href='%s?service=CSW&version=2.0.2&request=GetRepositoryItem&id=%s' %
        (url,
         util.getqattr(result,
                       context.md_core_model['mappings']['pycsw:Identifier'])))

    # atom:title
    el = etree.SubElement(
        node, util.nspath_eval(XPATH_MAPPINGS['pycsw:Title'], NAMESPACES))
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Title'])
    if val:
        el.text = val

    # atom:updated
    el = etree.SubElement(
        node, util.nspath_eval(XPATH_MAPPINGS['pycsw:Modified'], NAMESPACES))
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Modified'])
    if val:
        el.text = val
    else:
        val = util.getqattr(
            result, context.md_core_model['mappings']['pycsw:InsertDate'])
        el.text = val

    for qval in [
            'pycsw:PublicationDate', 'pycsw:AccessConstraints', 'pycsw:Source',
            'pycsw:Abstract'
    ]:
        val = util.getqattr(result, context.md_core_model['mappings'][qval])
        if val:
            etree.SubElement(
                node, util.nspath_eval(XPATH_MAPPINGS[qval],
                                       NAMESPACES)).text = val

    # bbox extent
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:BoundingBox'])
    bboxel = write_extent(val, context.namespaces)
    if bboxel is not None:
        node.append(bboxel)

    return node
Beispiel #21
0
def write_record(result, esn, context, url=None):
    ''' Return csw:SearchResults child as lxml.etree.Element '''

    typename = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:Typename'])

    if esn == 'full' and typename == 'dif:DIF':
        # dump record as is and exit
        return etree.fromstring(
            util.getqattr(result,
                          context.md_core_model['mappings']['pycsw:XML']),
            context.parser)

    node = etree.Element(util.nspath_eval('dif:DIF', NAMESPACES))
    node.attrib[util.nspath_eval('xsi:schemaLocation', context.namespaces)] = \
    '%s http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/dif.xsd' % NAMESPACE

    # identifier
    etree.SubElement(node, util.nspath_eval(
        'dif:Entry_ID', NAMESPACES)).text = util.getqattr(
            result, context.md_core_model['mappings']['pycsw:Identifier'])

    # title
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Title'])
    if not val:
        val = ''
    etree.SubElement(node, util.nspath_eval('dif:Entry_Title',
                                            NAMESPACES)).text = val

    # citation
    citation = etree.SubElement(
        node, util.nspath_eval('dif:Data_Set_Citation', NAMESPACES))

    # creator
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Creator'])
    etree.SubElement(citation,
                     util.nspath_eval('dif:Dataset_Creator',
                                      NAMESPACES)).text = val

    # date
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:PublicationDate'])
    etree.SubElement(citation,
                     util.nspath_eval('dif:Dataset_Release_Date',
                                      NAMESPACES)).text = val

    # publisher
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Publisher'])
    etree.SubElement(citation,
                     util.nspath_eval('dif:Dataset_Publisher',
                                      NAMESPACES)).text = val

    # format
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Format'])
    etree.SubElement(
        citation, util.nspath_eval('dif:Data_Presentation_Form',
                                   NAMESPACES)).text = val

    # iso topic category
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:TopicCategory'])
    etree.SubElement(node,
                     util.nspath_eval('dif:ISO_Topic_Category',
                                      NAMESPACES)).text = val

    # keywords
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Keywords'])

    if val:
        for kw in val.split(','):
            etree.SubElement(node, util.nspath_eval('dif:Keyword',
                                                    NAMESPACES)).text = kw

    # temporal
    temporal = etree.SubElement(
        node, util.nspath_eval('dif:Temporal_Coverage', NAMESPACES))
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:TempExtent_begin'])
    val2 = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:TempExtent_end'])
    etree.SubElement(temporal, util.nspath_eval('dif:Start_Date',
                                                NAMESPACES)).text = val
    etree.SubElement(temporal, util.nspath_eval('dif:End_Date',
                                                NAMESPACES)).text = val2

    # bbox extent
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:BoundingBox'])
    bboxel = write_extent(val, NAMESPACES)
    if bboxel is not None:
        node.append(bboxel)

    # access constraints
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:AccessConstraints'])
    etree.SubElement(node,
                     util.nspath_eval('dif:Access_Constraints',
                                      NAMESPACES)).text = val

    # language
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:ResourceLanguage'])
    etree.SubElement(node, util.nspath_eval('dif:Data_Set_Language',
                                            NAMESPACES)).text = val

    # contributor
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:OrganizationName'])
    etree.SubElement(node,
                     util.nspath_eval('dif:Originating_Center',
                                      NAMESPACES)).text = val

    # abstract
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Abstract'])
    if not val:
        val = ''
    etree.SubElement(node, util.nspath_eval('dif:Summary',
                                            NAMESPACES)).text = val

    # date
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:CreationDate'])
    etree.SubElement(node, util.nspath_eval('dif:DIF_Creation_Date',
                                            NAMESPACES)).text = val

    # URL
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Relation'])
    url = etree.SubElement(node, util.nspath_eval('dif:Related_URL',
                                                  NAMESPACES))
    etree.SubElement(url, util.nspath_eval('dif:URL', NAMESPACES)).text = val

    rlinks = util.getqattr(result,
                           context.md_core_model['mappings']['pycsw:Links'])
    if rlinks:
        for link in util.jsonify_links(rlinks):
            url2 = etree.SubElement(
                node, util.nspath_eval('dif:Related_URL', NAMESPACES))

            urltype = etree.SubElement(
                url2, util.nspath_eval('dif:URL_Content_Type', NAMESPACES))
            etree.SubElement(urltype, util.nspath_eval(
                'dif:Type', NAMESPACES)).text = link['protocol']

            etree.SubElement(url2,
                             util.nspath_eval('dif:URL',
                                              NAMESPACES)).text = link['url']
            etree.SubElement(
                url2, util.nspath_eval('dif:Description',
                                       NAMESPACES)).text = link['description']

    etree.SubElement(node, util.nspath_eval('dif:Metadata_Name',
                                            NAMESPACES)).text = 'CEOS IDN DIF'
    etree.SubElement(node, util.nspath_eval('dif:Metadata_Version',
                                            NAMESPACES)).text = '9.7'

    return node
Beispiel #22
0
def write_record(result, esn, context, url=None):
    """ Return csw:SearchResults child as lxml.etree.Element """

    node = etree.Element("collection")

    etree.SubElement(node, "stac_version").text = STAC_VERSION

    val = util.getqattr(result, "identifier")
    if val:
        etree.SubElement(node, "id").text = val

    val = util.getqattr(result, "abstract")
    if val:
        etree.SubElement(node, "description").text = val

    val = util.getqattr(result, "conditionapplyingtoaccessanduse")
    if val:
        etree.SubElement(node, "license").text = val

    val = util.getqattr(result, "title")
    if val:
        etree.SubElement(node, "title").text = val

    val = util.getqattr(result, "keywords")
    for keyword in val.split(","):
        etree.SubElement(node, "keywords").text = keyword

    extent = etree.SubElement(node, "extent")

    ext_temporal = etree.SubElement(extent, "temporal")
    interval_str = '[[' + format_time(util.getqattr(
        result, "time_begin")) + ',' + format_time(
            util.getqattr(result, "time_end")) + ']]'
    etree.SubElement(ext_temporal, "interval").text = interval_str

    ext_spatial = etree.SubElement(extent, "spatial")
    val = util.getqattr(result,
                        context.md_core_model["mappings"]["pycsw:BoundingBox"])
    if val:
        bbox = util.wkt2geom(val)
        etree.SubElement(ext_spatial,
                         "bbox").text = '[' + str(list(bbox)) + ']'

    return node
Beispiel #23
0
    def response(self, response, kvp, repository, server_url):
        """process OAI-PMH request"""

        mode = kvp.pop('mode', None)
        if 'config' in kvp:
            config_val = kvp.pop('config')
        url = '%smode=oaipmh' % util.bind_url(server_url)

        node = etree.Element(util.nspath_eval('oai:OAI-PMH', self.namespaces),
                             nsmap=self.namespaces)
        node.set(
            util.nspath_eval('xsi:schemaLocation', self.namespaces),
            '%s http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd' %
            self.namespaces['oai'])
        LOGGER.info(etree.tostring(node))

        etree.SubElement(node,
                         util.nspath_eval(
                             'oai:responseDate',
                             self.namespaces)).text = util.get_today_and_now()
        etree.SubElement(node,
                         util.nspath_eval('oai:request', self.namespaces),
                         attrib=kvp).text = url

        if 'verb' not in kvp:
            etree.SubElement(
                node,
                util.nspath_eval('oai:error', self.namespaces),
                code='badArgument').text = 'Missing \'verb\' parameter'
            return node

        if kvp['verb'] not in self.request_model.keys():
            etree.SubElement(
                node,
                util.nspath_eval('oai:error', self.namespaces),
                code='badArgument').text = 'Unknown verb \'%s\'' % kvp['verb']
            return node

        if util.xmltag_split(response.tag) == 'ExceptionReport':
            etree.SubElement(node,
                             util.nspath_eval('oai:error', self.namespaces),
                             code='badArgument').text = response.xpath(
                                 '//ows:ExceptionText|//ows20:ExceptionText',
                                 namespaces=self.context.namespaces)[0].text
            return node

        verb = kvp.pop('verb')

        if verb in ['GetRecord', 'ListIdentifiers', 'ListRecords']:
            if 'metadataprefix' not in kvp:
                etree.SubElement(node,
                                 util.nspath_eval('oai:error',
                                                  self.namespaces),
                                 code='badArgument'
                                 ).text = 'Missing metadataPrefix parameter'
                return node
            elif kvp['metadataprefix'] not in self.metadata_formats.keys():
                etree.SubElement(node,
                                 util.nspath_eval('oai:error',
                                                  self.namespaces),
                                 code='badArgument'
                                 ).text = 'Invalid metadataPrefix parameter'
                return node

        for key, value in kvp.iteritems():
            if key != 'mode' and key not in self.request_model[verb]:
                etree.SubElement(
                    node,
                    util.nspath_eval('oai:error', self.namespaces),
                    code='badArgument').text = 'Illegal parameter \'%s\'' % key
                return node

        verbnode = etree.SubElement(
            node, util.nspath_eval('oai:%s' % verb, self.namespaces))

        if verb == 'Identify':
            etree.SubElement(
                verbnode,
                util.nspath_eval('oai:repositoryName',
                                 self.namespaces)).text = self.config.get(
                                     'metadata:main', 'identification_title')
            etree.SubElement(verbnode,
                             util.nspath_eval('oai:baseURL',
                                              self.namespaces)).text = url
            etree.SubElement(
                verbnode,
                util.nspath_eval('oai:protocolVersion',
                                 self.namespaces)).text = '2.0'
            etree.SubElement(
                verbnode,
                util.nspath_eval('oai:adminEmail',
                                 self.namespaces)).text = self.config.get(
                                     'metadata:main', 'contact_email')
            etree.SubElement(
                verbnode,
                util.nspath_eval(
                    'oai:earliestDatestamp',
                    self.namespaces)).text = repository.query_insert('min')
            etree.SubElement(
                verbnode, util.nspath_eval('oai:deletedRecord',
                                           self.namespaces)).text = 'no'
            etree.SubElement(
                verbnode, util.nspath_eval(
                    'oai:granularity',
                    self.namespaces)).text = 'YYYY-MM-DDThh:mm:ssZ'

        elif verb == 'ListSets':
            for key, value in self.metadata_sets.iteritems():
                setnode = etree.SubElement(
                    verbnode, util.nspath_eval('oai:set', self.namespaces))
                etree.SubElement(
                    setnode, util.nspath_eval('oai:setSpec',
                                              self.namespaces)).text = key
                etree.SubElement(
                    setnode, util.nspath_eval('oai:setName',
                                              self.namespaces)).text = value[0]

        elif verb == 'ListMetadataFormats':
            for key, value in self.metadata_formats.iteritems():
                mdfnode = etree.SubElement(
                    verbnode,
                    util.nspath_eval('oai:metadataFormat', self.namespaces))
                etree.SubElement(
                    mdfnode,
                    util.nspath_eval('oai:metadataPrefix',
                                     self.namespaces)).text = key
                etree.SubElement(
                    mdfnode,
                    util.nspath_eval('oai:schema',
                                     self.namespaces)).text = value['schema']
                etree.SubElement(
                    mdfnode,
                    util.nspath_eval(
                        'oai:metadataNamespace',
                        self.namespaces)).text = value['namespace']

        elif verb in ['GetRecord', 'ListIdentifiers', 'ListRecords']:
            if verb == 'GetRecord':  # GetRecordById
                records = response.getchildren()
            else:  # GetRecords
                records = response.getchildren()[1].getchildren()
            for child in records:
                recnode = etree.SubElement(
                    verbnode, util.nspath_eval('oai:record', self.namespaces))
                header = etree.SubElement(
                    recnode, util.nspath_eval('oai:header', self.namespaces))
                self._transform_element(header, response, 'oai:identifier')
                self._transform_element(header, response, 'oai:dateStamp')
                self._transform_element(header, response, 'oai:setSpec')
                if verb in ['GetRecord', 'ListRecords']:
                    metadata = etree.SubElement(
                        recnode,
                        util.nspath_eval('oai:metadata', self.namespaces))
                    if 'metadataprefix' in kvp and kvp[
                            'metadataprefix'] == 'oai_dc':
                        child.tag = util.nspath_eval('oai_dc:dc',
                                                     self.namespaces)
                    metadata.append(child)
            if verb != 'GetRecord':
                complete_list_size = response.xpath(
                    '//@numberOfRecordsMatched')[0]
                next_record = response.xpath('//@nextRecord')[0]
                cursor = str(int(complete_list_size) - int(next_record) - 1)

                resumption_token = etree.SubElement(
                    verbnode,
                    util.nspath_eval('oai:resumptionToken', self.namespaces),
                    completeListSize=complete_list_size,
                    cursor=cursor).text = next_record
        return node
Beispiel #24
0
def kvp2filterxml(kvp, context, profiles):
    ''' transform kvp to filter XML string '''

    bbox_element = None
    time_element = None
    anytext_elements = []
    query_temporal_by_iso = False

    if profiles is not None and 'plugins' in profiles and 'APISO' in profiles[
            'plugins']:
        query_temporal_by_iso = True

    # Count parameters
    par_count = 0
    for p in ['q', 'bbox', 'time']:
        if p in kvp and kvp[p] != '':
            par_count += 1

    # Create root element for FilterXML
    root = etree.Element(util.nspath_eval('ogc:Filter', context.namespaces))

    # bbox to FilterXML
    if 'bbox' in kvp and kvp['bbox'] != '':
        LOGGER.debug('Detected bbox parameter')
        bbox_list = [x.strip() for x in kvp['bbox'].split(',')]
        bbox_element = etree.Element(
            util.nspath_eval('ogc:BBOX', context.namespaces))
        el = etree.Element(
            util.nspath_eval('ogc:PropertyName', context.namespaces))
        el.text = 'ows:BoundingBox'
        bbox_element.append(el)
        env = etree.Element(
            util.nspath_eval('gml:Envelope', context.namespaces))
        el = etree.Element(
            util.nspath_eval('gml:lowerCorner', context.namespaces))

        if len(bbox_list) == 5:  # add srsName
            LOGGER.debug('Found CRS')
            env.attrib['srsName'] = bbox_list[4]
        else:
            LOGGER.debug('Assuming 4326')
            env.attrib['srsName'] = 'urn:ogc:def:crs:OGC:1.3:CRS84'
            if not validate_4326(bbox_list):
                msg = '4326 coordinates out of range: %s' % bbox_list
                LOGGER.error(msg)
                raise RuntimeError(msg)

        try:
            el.text = "%s %s" % (bbox_list[0], bbox_list[1])
        except Exception as err:
            errortext = 'Exception: OpenSearch bbox not valid.\nError: %s.' % str(
                err)
            LOGGER.exception(errortext)
        env.append(el)
        el = etree.Element(
            util.nspath_eval('gml:upperCorner', context.namespaces))
        try:
            el.text = "%s %s" % (bbox_list[2], bbox_list[3])
        except Exception as err:
            errortext = 'Exception: OpenSearch bbox not valid.\nError: %s.' % str(
                err)
            LOGGER.exception(errortext)
        env.append(el)
        bbox_element.append(env)

    # q to FilterXML
    if 'q' in kvp and kvp['q'] != '':
        LOGGER.debug('Detected q parameter')
        qvals = kvp['q'].split()
        LOGGER.debug(qvals)
        if len(qvals) > 1:
            par_count += 1
        for qval in qvals:
            LOGGER.debug('processing q token')
            anytext_element = etree.Element(
                util.nspath_eval('ogc:PropertyIsEqualTo', context.namespaces))
            el = etree.Element(
                util.nspath_eval('ogc:PropertyName', context.namespaces))
            el.text = 'csw:AnyText'
            anytext_element.append(el)
            el = etree.Element(
                util.nspath_eval('ogc:Literal', context.namespaces))
            el.text = qval
            anytext_element.append(el)
            anytext_elements.append(anytext_element)

    if ('start' in kvp or 'stop' in kvp) and 'time' not in kvp:
        LOGGER.debug('Detected start/stop in KVP')
        kvp['time'] = ''
        if 'start' in kvp and kvp['start'] != '':
            kvp['time'] = kvp['start'] + '/'
        if 'stop' in kvp and kvp['stop'] != '':
            if len(kvp['time']) > 0:
                kvp['time'] += kvp['stop']
            else:
                kvp['time'] = '/' + kvp['stop']
            LOGGER.debug('new KVP time: {}'.format(kvp['time']))

    # time to FilterXML
    if 'time' in kvp and kvp['time'] != '':
        LOGGER.debug('Detected time parameter %s', kvp['time'])
        time_list = kvp['time'].split("/")

        LOGGER.debug('TIMELIST: %s', time_list)

        if len(time_list) == 2:
            if '' not in time_list:  # both dates present
                LOGGER.debug('Both dates present')
                if query_temporal_by_iso:
                    LOGGER.debug('Querying by ISO data extent')
                    time_element = etree.Element(
                        util.nspath_eval('ogc:And', context.namespaces))

                    begin_element = etree.Element(
                        util.nspath_eval('ogc:PropertyIsGreaterThanOrEqualTo',
                                         context.namespaces))
                    etree.SubElement(
                        begin_element,
                        util.nspath_eval('ogc:PropertyName', context.namespaces
                                         )).text = 'apiso:TempExtent_begin'
                    etree.SubElement(
                        begin_element,
                        util.nspath_eval(
                            'ogc:Literal',
                            context.namespaces)).text = time_list[0]

                    end_element = etree.Element(
                        util.nspath_eval('ogc:PropertyIsLessThanOrEqualTo',
                                         context.namespaces))
                    etree.SubElement(
                        end_element,
                        util.nspath_eval(
                            'ogc:PropertyName',
                            context.namespaces)).text = 'apiso:TempExtent_end'
                    etree.SubElement(
                        end_element,
                        util.nspath_eval(
                            'ogc:Literal',
                            context.namespaces)).text = time_list[1]

                    time_element.append(begin_element)
                    time_element.append(end_element)

                else:
                    LOGGER.debug('Querying by DC date')
                    time_element = etree.Element(
                        util.nspath_eval('ogc:PropertyIsBetween',
                                         context.namespaces))
                    el = etree.Element(
                        util.nspath_eval('ogc:PropertyName',
                                         context.namespaces))
                    el.text = 'dc:date'
                    time_element.append(el)
                    el = etree.Element(
                        util.nspath_eval('ogc:LowerBoundary',
                                         context.namespaces))
                    el2 = etree.Element(
                        util.nspath_eval('ogc:Literal', context.namespaces))
                    el2.text = time_list[0]
                    el.append(el2)
                    time_element.append(el)
                    el = etree.Element(
                        util.nspath_eval('ogc:UpperBoundary',
                                         context.namespaces))
                    el2 = etree.Element(
                        util.nspath_eval('ogc:Literal', context.namespaces))
                    el2.text = time_list[1]
                    el.append(el2)
                    time_element.append(el)

            else:  # one is empty
                LOGGER.debug('Querying by open-ended date')
                if time_list == ['', '']:
                    par_count -= 1
                # One of two is empty
                elif time_list[1] == '':  # start datetime but no end datetime
                    time_element = etree.Element(
                        util.nspath_eval('ogc:PropertyIsGreaterThanOrEqualTo',
                                         context.namespaces))
                    el = etree.Element(
                        util.nspath_eval('ogc:PropertyName',
                                         context.namespaces))
                    if query_temporal_by_iso:
                        el.text = 'apiso:TempExtent_begin'
                    else:
                        el.text = 'dc:date'
                    time_element.append(el)
                    el = etree.Element(
                        util.nspath_eval('ogc:Literal', context.namespaces))
                    el.text = time_list[0]
                    time_element.append(el)
                else:  # end datetime but no start datetime
                    time_element = etree.Element(
                        util.nspath_eval('ogc:PropertyIsLessThanOrEqualTo',
                                         context.namespaces))
                    el = etree.Element(
                        util.nspath_eval('ogc:PropertyName',
                                         context.namespaces))
                    if query_temporal_by_iso:
                        el.text = 'apiso:TempExtent_end'
                    else:
                        el.text = 'dc:date'
                    time_element.append(el)
                    el = etree.Element(
                        util.nspath_eval('ogc:Literal', context.namespaces))
                    el.text = time_list[1]
                    time_element.append(el)
        elif ((len(time_list) == 1) and ('' not in time_list)):
            LOGGER.debug('Querying time instant via dc:date')
            # This is an equal request
            time_element = etree.Element(
                util.nspath_eval('ogc:PropertyIsEqualTo', context.namespaces))
            el = etree.Element(
                util.nspath_eval('ogc:PropertyName', context.namespaces))
            el.text = 'dc:date'
            time_element.append(el)
            el = etree.Element(
                util.nspath_eval('ogc:Literal', context.namespaces))
            el.text = time_list[0]
            time_element.append(el)
        else:
            # Error
            errortext = 'Exception: OpenSearch time not valid: %s.' % str(
                kvp['time'])
            LOGGER.error(errortext)

    if par_count == 0:
        return ''
    elif par_count == 1:
        LOGGER.debug('Single predicate filter')
        # Only one OpenSearch parameter exists
        if 'bbox' in kvp and kvp['bbox'] != '':
            LOGGER.debug('Adding bbox')
            root.append(bbox_element)
        elif time_element is not None:
            LOGGER.debug('Adding time')
            root.append(time_element)
        elif anytext_elements:
            LOGGER.debug('Adding anytext')
            root.extend(anytext_elements)
    elif (par_count > 1):
        LOGGER.debug('ogc:And query (%d predicates)', par_count)
        # Since more than 1 parameter, append the AND logical operator
        logical_and = etree.Element(
            util.nspath_eval('ogc:And', context.namespaces))
        if bbox_element is not None:
            logical_and.append(bbox_element)
        if time_element is not None:
            logical_and.append(time_element)
        if anytext_elements is not None:
            logical_and.extend(anytext_elements)
        root.append(logical_and)

    # Render etree to string XML
    LOGGER.debug(etree.tostring(root, encoding='unicode'))
    return etree.tostring(root, encoding='unicode')
    def _csw3_2_os(self):
        """CSW 3.0.0 Capabilities to OpenSearch Description"""

        if util.xmltag_split(self.exml.tag) == 'GetRecordsResponse':

            startindex = int(self.exml.xpath('//@nextRecord')[0]) - int(
                        self.exml.xpath('//@numberOfRecordsReturned')[0])
            if startindex < 1:
                startindex = 1

            node = etree.Element(util.nspath_eval('atom:feed',
                       self.context.namespaces), nsmap=self.namespaces)
            etree.SubElement(node, util.nspath_eval('atom:id',
                       self.context.namespaces)).text = self.cfg.get('server', 'url')
            etree.SubElement(node, util.nspath_eval('atom:title',
                       self.context.namespaces)).text = self.cfg.get('metadata:main',
                       'identification_title')
            author = etree.SubElement(node, util.nspath_eval('atom:author', self.context.namespaces))
            etree.SubElement(author, util.nspath_eval('atom:name', self.context.namespaces)).text = self.cfg.get('metadata:main',
                       'provider_name')
            etree.SubElement(node, util.nspath_eval('atom:link',
                       self.context.namespaces), rel='search',
                           type='application/opensearchdescription+xml',
                           href='%smode=opensearch&service=CSW&version=3.0.0&request=GetCapabilities' % self.bind_url)

            etree.SubElement(node, util.nspath_eval('atom:updated',
                self.context.namespaces)).text = self.exml.xpath('//@timestamp')[0]

            etree.SubElement(node, util.nspath_eval('os:Query', self.context.namespaces), role='request')

            etree.SubElement(node, util.nspath_eval('os:totalResults',
                        self.context.namespaces)).text = self.exml.xpath(
                        '//@numberOfRecordsMatched')[0]
            etree.SubElement(node, util.nspath_eval('os:startIndex',
                        self.context.namespaces)).text = str(startindex)
            etree.SubElement(node, util.nspath_eval('os:itemsPerPage',
                        self.context.namespaces)).text = self.exml.xpath(
                        '//@numberOfRecordsReturned')[0]

            for rec in self.exml.xpath('//atom:entry',
                        namespaces=self.context.namespaces):
                node.append(rec)
        elif util.xmltag_split(self.exml.tag) == 'Capabilities':
            node = etree.Element(util.nspath_eval('os:OpenSearchDescription', self.namespaces), nsmap=self.namespaces)
            etree.SubElement(node, util.nspath_eval('os:ShortName', self.namespaces)).text = self.exml.xpath('//ows20:Title', namespaces=self.context.namespaces)[0].text[:16]
            etree.SubElement(node, util.nspath_eval('os:LongName', self.namespaces)).text = self.exml.xpath('//ows20:Title', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Description', self.namespaces)).text = self.exml.xpath('//ows20:Abstract', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Tags', self.namespaces)).text = ' '.join(x.text for x in self.exml.xpath('//ows20:Keyword', namespaces=self.context.namespaces))

            # Requirement-022
            node1 = etree.SubElement(node, util.nspath_eval('os:Url', self.namespaces))
            node1.set('type', 'application/xml')
            node1.set('template', '%sservice=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q={searchTerms?}&bbox={geo:box?}&time={time:start?}/{time:end?}&outputformat=application/xml&outputschema=http://www.opengis.net/cat/csw/3.0&startposition={startIndex?}&maxrecords={count?}&recordids={geo:uid}' % self.bind_url)

            # Requirement-023
            node1 = etree.SubElement(node, util.nspath_eval('os:Url', self.namespaces))
            node1.set('type', 'application/atom+xml')
            node1.set('template', '%smode=opensearch&service=CSW&version=3.0.0&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q={searchTerms?}&bbox={geo:box?}&time={time:start?}/{time:end?}&outputformat=application/atom+xml&&startposition={startIndex?}&maxrecords={count?}&recordids={geo:uid}' % self.bind_url)

            node1 = etree.SubElement(node, util.nspath_eval('os:Image', self.namespaces))
            node1.set('type', 'image/vnd.microsoft.icon')
            node1.set('width', '16')
            node1.set('height', '16')
            node1.text = 'http://pycsw.org/img/favicon.ico'

            os_query = etree.SubElement(node, util.nspath_eval('os:Query', self.namespaces), role='example')
            os_query.attrib[util.nspath_eval('geo:box', self.namespaces)] = '-180,-90,180,90'

            etree.SubElement(node, util.nspath_eval('os:Developer', self.namespaces)).text = self.exml.xpath('//ows20:IndividualName', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Contact', self.namespaces)).text = self.exml.xpath('//ows20:ElectronicMailAddress', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Attribution', self.namespaces)).text = self.exml.xpath('//ows20:ProviderName', namespaces=self.context.namespaces)[0].text
        elif util.xmltag_split(self.exml.tag) == 'ExceptionReport':
            node = self.exml
        else:  # GetRecordById output
            node = etree.Element(util.nspath_eval('atom:feed',
                       self.context.namespaces), nsmap=self.namespaces)
            etree.SubElement(node, util.nspath_eval('atom:id',
                       self.context.namespaces)).text = self.cfg.get('server', 'url')
            etree.SubElement(node, util.nspath_eval('atom:title',
                       self.context.namespaces)).text = self.cfg.get('metadata:main',
                       'identification_title')
            #etree.SubElement(node, util.nspath_eval('atom:updated',
            #  self.context.namespaces)).text = self.exml.xpath('//@timestamp')[0]

            etree.SubElement(node, util.nspath_eval('os:totalResults',
                        self.context.namespaces)).text = '1'
            etree.SubElement(node, util.nspath_eval('os:startIndex',
                        self.context.namespaces)).text = '1'
            etree.SubElement(node, util.nspath_eval('os:itemsPerPage',
                        self.context.namespaces)).text = '1'

            for rec in self.exml.xpath('//atom:entry', namespaces=self.context.namespaces):
                #node.append(rec)
                node = rec
        return node
Beispiel #26
0
def write_record(result, esn, context, url=None):
    ''' Return csw:SearchResults child as lxml.etree.Element '''

    typename = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:Typename'])

    if esn == 'full' and typename == 'dif:DIF':
        # dump record as is and exit
        return etree.fromstring(
            util.getqattr(result,
                          context.md_core_model['mappings']['pycsw:XML']),
            context.parser)

    node = etree.Element(util.nspath_eval('dif:DIF', NAMESPACES))
    node.attrib[util.nspath_eval('xsi:schemaLocation', context.namespaces)] = \
    '%s http://gcmd.gsfc.nasa.gov/Aboutus/xml/dif/dif.xsd' % NAMESPACE

    # identifier
    etree.SubElement(node, util.nspath_eval(
        'dif:Entry_ID', NAMESPACES)).text = util.getqattr(
            result, context.md_core_model['mappings']['pycsw:Identifier'])

    # title
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Title'])
    if not val:
        val = ''
    etree.SubElement(node, util.nspath_eval('dif:Entry_Title',
                                            NAMESPACES)).text = val

    # citation
    citation = etree.SubElement(
        node, util.nspath_eval('dif:Data_Set_Citation', NAMESPACES))

    # creator
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Creator'])
    etree.SubElement(citation,
                     util.nspath_eval('dif:Dataset_Creator',
                                      NAMESPACES)).text = val

    # date
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:PublicationDate'])
    etree.SubElement(citation,
                     util.nspath_eval('dif:Dataset_Release_Date',
                                      NAMESPACES)).text = val

    # publisher
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Publisher'])
    etree.SubElement(citation,
                     util.nspath_eval('dif:Dataset_Publisher',
                                      NAMESPACES)).text = val

    # format
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Format'])
    etree.SubElement(
        citation, util.nspath_eval('dif:Data_Presentation_Form',
                                   NAMESPACES)).text = val

    # keywords dif:Parameters
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Keywords'])
    if val:
        kws = val.split(',')
        parameters_indexes = []
        for index, kw in enumerate(kws):
            if "Earth Science".lower() in kw.lower() and len(
                    kw.split(">")) >= 2:
                values = kw.upper().split(">")
                parameters = etree.SubElement(node,
                                              util.nspath_eval(
                                                  'dif:Parameters',
                                                  NAMESPACES))  # .text = kw
                etree.SubElement(
                    parameters, util.nspath_eval(
                        'dif:Category',
                        NAMESPACES)).text = values[0].strip().upper()
                etree.SubElement(
                    parameters, util.nspath_eval(
                        'dif:Topic',
                        NAMESPACES)).text = values[1].strip().upper()
                etree.SubElement(
                    parameters, util.nspath_eval(
                        'dif:Term',
                        NAMESPACES)).text = values[2].strip().upper()
                for i, v in enumerate(values[3:]):
                    etree.SubElement(
                        parameters,
                        util.nspath_eval(f'dif:Variable_Level_{i + 1}',
                                         NAMESPACES)).text = v.strip()
                parameters_indexes.append(index)
                # kws.pop(index)

    # iso topic category
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:TopicCategory'])
    etree.SubElement(node,
                     util.nspath_eval('dif:ISO_Topic_Category',
                                      NAMESPACES)).text = val

    # keywords dif:keywords
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Keywords'])
    if val:
        kws = val.split(',')
        kws = [i for j, i in enumerate(kws) if j not in parameters_indexes]
        for index, kw in enumerate(kws):
            etree.SubElement(node,
                             util.nspath_eval('dif:Keyword',
                                              NAMESPACES)).text = kw.strip()

    # temporal
    temporal = etree.SubElement(
        node, util.nspath_eval('dif:Temporal_Coverage', NAMESPACES))
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:TempExtent_begin'])
    val2 = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:TempExtent_end'])
    etree.SubElement(temporal, util.nspath_eval('dif:Start_Date',
                                                NAMESPACES)).text = val
    etree.SubElement(temporal, util.nspath_eval('dif:End_Date',
                                                NAMESPACES)).text = val2

    # bbox extent
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:BoundingBox'])
    bboxel = write_extent(val, NAMESPACES)
    if bboxel is not None:
        node.append(bboxel)

    # access constraints
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:AccessConstraints'])
    etree.SubElement(node,
                     util.nspath_eval('dif:Access_Constraints',
                                      NAMESPACES)).text = val

    # language
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:ResourceLanguage'])
    etree.SubElement(node, util.nspath_eval('dif:Data_Set_Language',
                                            NAMESPACES)).text = val

    # contributor
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:OrganizationName'])
    etree.SubElement(node,
                     util.nspath_eval('dif:Originating_Center',
                                      NAMESPACES)).text = val

    # abstract
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Abstract'])
    if not val:
        val = ''
    etree.SubElement(node, util.nspath_eval('dif:Summary',
                                            NAMESPACES)).text = val

    # URL
    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Relation'])
    if val:
        url = etree.SubElement(node,
                               util.nspath_eval('dif:Related_URL', NAMESPACES))
        etree.SubElement(url, util.nspath_eval('dif:URL',
                                               NAMESPACES)).text = val

    rlinks = util.getqattr(result,
                           context.md_core_model['mappings']['pycsw:Links'])
    if rlinks:
        for link in util.jsonify_links(rlinks):
            url2 = etree.SubElement(
                node, util.nspath_eval('dif:Related_URL', NAMESPACES))

            urltype = etree.SubElement(
                url2, util.nspath_eval('dif:URL_Content_Type', NAMESPACES))
            if link['protocol'] == 'download':
                etree.SubElement(urltype,
                                 util.nspath_eval(
                                     'dif:Type', NAMESPACES)).text = 'GET DATA'
            elif link['protocol'] == 'OPENDAP:OPENDAP':
                etree.SubElement(urltype,
                                 util.nspath_eval(
                                     'dif:Type', NAMESPACES)).text = 'GET DATA'
                etree.SubElement(urltype,
                                 util.nspath_eval(
                                     'dif:Subtype',
                                     NAMESPACES)).text = 'OPENDAP DATA (DODS)'
            elif link['protocol'] == 'OGC:WMS':
                etree.SubElement(
                    urltype, util.nspath_eval('dif:Type',
                                              NAMESPACES)).text = 'GET SERVICE'
                etree.SubElement(
                    urltype, util.nspath_eval(
                        'dif:Subtype',
                        NAMESPACES)).text = 'GET WEB MAP SERVICE (WMS)'
            else:
                etree.SubElement(urltype,
                                 util.nspath_eval(
                                     'dif:Type', NAMESPACES)).text = 'GET DATA'

            etree.SubElement(url2,
                             util.nspath_eval('dif:URL',
                                              NAMESPACES)).text = link['url']
            if link['description']:
                etree.SubElement(
                    url2,
                    util.nspath_eval('dif:Description',
                                     NAMESPACES)).text = link['description']

    val = util.getqattr(result,
                        context.md_core_model['mappings']['pycsw:Source'])
    if val:
        url2 = etree.SubElement(
            node, util.nspath_eval('dif:Related_URL', NAMESPACES))
        urltype = etree.SubElement(
            url2, util.nspath_eval('dif:URL_Content_Type', NAMESPACES))
        etree.SubElement(urltype, util.nspath_eval(
            'dif:Type', NAMESPACES)).text = 'DATASET LANDING PAGE'
        etree.SubElement(url2, util.nspath_eval('dif:URL',
                                                NAMESPACES)).text = val

    etree.SubElement(node, util.nspath_eval('dif:Metadata_Name',
                                            NAMESPACES)).text = 'CEOS IDN DIF'
    etree.SubElement(node, util.nspath_eval('dif:Metadata_Version',
                                            NAMESPACES)).text = '9.7'

    # date
    val = util.getqattr(
        result, context.md_core_model['mappings']['pycsw:CreationDate'])
    etree.SubElement(node, util.nspath_eval('dif:DIF_Creation_Date',
                                            NAMESPACES)).text = val

    return node
Beispiel #27
0
    def response_csw2sru(self, element, environ):
        """transform a CSW response into an SRU response"""

        response_name = etree.QName(element).localname
        if response_name == 'Capabilities':  # explain
            node = etree.Element(util.nspath_eval('sru:explainResponse', self.namespaces), nsmap=self.namespaces)

            etree.SubElement(node, util.nspath_eval('sru:version', self.namespaces)).text = self.sru_version

            record = etree.SubElement(node, util.nspath_eval('sru:record', self.namespaces))

            etree.SubElement(record, util.nspath_eval('sru:recordPacking', self.namespaces)).text = 'XML'
            etree.SubElement(record, util.nspath_eval('sru:recordSchema', self.namespaces)).text = 'http://explain.z3950.org/dtd/2.1/'

            recorddata = etree.SubElement(record, util.nspath_eval('sru:recordData', self.namespaces))

            explain = etree.SubElement(recorddata, util.nspath_eval('zr:explain', self.namespaces))

            serverinfo = etree.SubElement(explain, util.nspath_eval('zr:serverInfo', self.namespaces), protocol='SRU', version=self.sru_version, transport='http', method='GET POST SOAP')

            etree.SubElement(serverinfo, util.nspath_eval('zr:host', self.namespaces)).text = environ.get('HTTP_HOST', environ["SERVER_NAME"])  # WSGI allows for either of these
            etree.SubElement(serverinfo, util.nspath_eval('zr:port', self.namespaces)).text = environ['SERVER_PORT']
            etree.SubElement(serverinfo, util.nspath_eval('zr:database', self.namespaces)).text = 'pycsw'

            databaseinfo = etree.SubElement(explain, util.nspath_eval('zr:databaseInfo', self.namespaces))

            etree.SubElement(databaseinfo, util.nspath_eval('zr:title', self.namespaces), lang='en', primary='true').text = element.xpath('//ows:Title|//ows20:Title', namespaces=self.context.namespaces)[0].text
            etree.SubElement(databaseinfo, util.nspath_eval('zr:description', self.namespaces), lang='en', primary='true').text = element.xpath('//ows:Abstract|//ows20:Abstract', namespaces=self.context.namespaces)[0].text

            indexinfo = etree.SubElement(explain, util.nspath_eval('zr:indexInfo', self.namespaces))
            etree.SubElement(indexinfo, util.nspath_eval('zr:set', self.namespaces), name='dc', identifier='info:srw/cql-context-set/1/dc-v1.1')

            for key, value in sorted(self.mappings['csw:Record']['index'].items()):
                zrindex = etree.SubElement(indexinfo, util.nspath_eval('zr:index', self.namespaces), id=value)
                etree.SubElement(zrindex, util.nspath_eval('zr:title', self.namespaces)).text = key
                zrmap = etree.SubElement(zrindex, util.nspath_eval('zr:map', self.namespaces))
                etree.SubElement(zrmap, util.nspath_eval('zr:map', self.namespaces), set='dc').text = key

            zrindex = etree.SubElement(indexinfo, util.nspath_eval('zr:index', self.namespaces))
            zrmap = etree.SubElement(zrindex, util.nspath_eval('zr:map', self.namespaces))
            etree.SubElement(zrmap, util.nspath_eval('zr:name', self.namespaces), set='dc').text = 'title222'

            schemainfo = etree.SubElement(explain, util.nspath_eval('zr:schemaInfo', self.namespaces))
            zrschema = etree.SubElement(schemainfo, util.nspath_eval('zr:schema', self.namespaces), name='dc', identifier='info:srw/schema/1/dc-v1.1')
            etree.SubElement(zrschema, util.nspath_eval('zr:title', self.namespaces)).text = 'Simple Dublin Core'

            configinfo = etree.SubElement(explain, util.nspath_eval('zr:configInfo', self.namespaces))
            etree.SubElement(configinfo, util.nspath_eval('zr:default', self.namespaces), type='numberOfRecords').text = '0'

        elif response_name == 'GetRecordsResponse':

            recpos = int(element.xpath('//@nextRecord')[0]) - int(element.xpath('//@numberOfRecordsReturned')[0])

            node = etree.Element(util.nspath_eval('zs:searchRetrieveResponse', self.namespaces), nsmap=self.namespaces)
            etree.SubElement(node, util.nspath_eval('zs:version', self.namespaces)).text = self.sru_version
            etree.SubElement(node, util.nspath_eval('zs:numberOfRecords', self.namespaces)).text = element.xpath('//@numberOfRecordsMatched')[0]

            for rec in element.xpath('//csw:BriefRecord', namespaces=self.context.namespaces):
                record = etree.SubElement(node, util.nspath_eval('zs:record', self.namespaces))
                etree.SubElement(node, util.nspath_eval('zs:recordSchema', self.namespaces)).text = 'info:srw/schema/1/dc-v1.1'
                etree.SubElement(node, util.nspath_eval('zs:recordPacking', self.namespaces)).text = 'xml'

                recorddata = etree.SubElement(record, util.nspath_eval('zs:recordData', self.namespaces))
                rec.tag = util.nspath_eval('srw_dc:srw_dc', self.namespaces)
                recorddata.append(rec)

                etree.SubElement(record, util.nspath_eval('zs:recordPosition', self.namespaces)).text = str(recpos)
                recpos += 1

        elif response_name == 'ExceptionReport':
            node = self.exceptionreport2diagnostic(element)
        return node
    def _csw2_2_os(self):
        """CSW 2.0.2 Capabilities to OpenSearch Description"""

        if util.xmltag_split(self.exml.tag) == 'GetRecordsResponse':

            startindex = int(self.exml.xpath('//@nextRecord')[0]) - int(
                        self.exml.xpath('//@numberOfRecordsReturned')[0])
            if startindex < 1:
                startindex = 1

            node = etree.Element(util.nspath_eval('atom:feed',
                       self.context.namespaces), nsmap=self.namespaces)
            etree.SubElement(node, util.nspath_eval('atom:id',
                       self.context.namespaces)).text = self.cfg.get('server', 'url')
            etree.SubElement(node, util.nspath_eval('atom:title',
                       self.context.namespaces)).text = self.cfg.get('metadata:main',
                       'identification_title')
            #etree.SubElement(node, util.nspath_eval('atom:updated',
            #  self.context.namespaces)).text = self.exml.xpath('//@timestamp')[0]

            etree.SubElement(node, util.nspath_eval('os:totalResults',
                        self.context.namespaces)).text = self.exml.xpath(
                        '//@numberOfRecordsMatched')[0]
            etree.SubElement(node, util.nspath_eval('os:startIndex',
                        self.context.namespaces)).text = str(startindex)
            etree.SubElement(node, util.nspath_eval('os:itemsPerPage',
                        self.context.namespaces)).text = self.exml.xpath(
                        '//@numberOfRecordsReturned')[0]

            for rec in self.exml.xpath('//atom:entry',
                        namespaces=self.context.namespaces):
                node.append(rec)
        elif util.xmltag_split(self.exml.tag) == 'Capabilities':
            node = etree.Element(util.nspath_eval('os:OpenSearchDescription', self.namespaces), nsmap=self.namespaces)
            etree.SubElement(node, util.nspath_eval('os:ShortName', self.namespaces)).text = self.exml.xpath('//ows:Title', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:LongName', self.namespaces)).text = self.exml.xpath('//ows:Title', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Description', self.namespaces)).text = self.exml.xpath('//ows:Abstract', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Tags', self.namespaces)).text = ' '.join(x.text for x in self.exml.xpath('//ows:Keyword', namespaces=self.context.namespaces))

            node1 = etree.SubElement(node, util.nspath_eval('os:Url', self.namespaces))
            node1.set('type', 'application/atom+xml')
            node1.set('method', 'get')
            node1.set('template', '%smode=opensearch&service=CSW&version=2.0.2&request=GetRecords&elementsetname=full&typenames=csw:Record&resulttype=results&q={searchTerms?}&bbox={geo:box?}&time={time:start?}/{time:end?}&startposition={startIndex?}&maxrecords={count?}' % self.bind_url)

            node1 = etree.SubElement(node, util.nspath_eval('os:Image', self.namespaces))
            node1.set('type', 'image/vnd.microsoft.icon')
            node1.set('width', '16')
            node1.set('height', '16')
            node1.text = 'http://pycsw.org/img/favicon.ico'

            etree.SubElement(node, util.nspath_eval('os:Developer', self.namespaces)).text = self.exml.xpath('//ows:IndividualName', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Context', self.namespaces)).text = self.exml.xpath('//ows:ElectronicMailAddress', namespaces=self.context.namespaces)[0].text
            etree.SubElement(node, util.nspath_eval('os:Attribution', self.namespaces)).text = self.exml.xpath('//ows:ProviderName', namespaces=self.context.namespaces)[0].text
        elif util.xmltag_split(self.exml.tag) == 'ExceptionReport':
            node = self.exml
        else:  # return Description document
            node = etree.Element(util.nspath_eval('os:Description', self.context.namespaces))

        return node
Beispiel #29
0
    def write_record(self, result, esn, outputschema, queryables):
        ''' Return csw:SearchResults child as lxml.etree.Element '''

        identifier = util.getqattr(
            result, self.context.md_core_model['mappings']['pycsw:Identifier'])
        typename = util.getqattr(
            result, self.context.md_core_model['mappings']['pycsw:Typename'])

        if esn == 'full' and typename == 'rim:RegistryObject':
            # dump record as is and exit
            return etree.fromstring(
                util.getqattr(result, queryables['pycsw:XML']['dbcol']),
                self.context.parser)

        if typename == 'csw:Record':  # transform csw:Record -> rim:RegistryObject model mappings
            util.transform_mappings(queryables,
                                    self.repository['mappings']['csw:Record'])

        node = etree.Element(
            util.nspath_eval('rim:ExtrinsicObject', self.namespaces))
        node.attrib[util.nspath_eval('xsi:schemaLocation', self.context.namespaces)] = \
        '%s %s/csw/2.0.2/profiles/ebrim/1.0/csw-ebrim.xsd' % (self.namespaces['wrs'], self.ogc_schemas_base)

        node.attrib['id'] = identifier
        node.attrib['lid'] = identifier
        node.attrib['objectType'] = str(
            util.getqattr(
                result, self.context.md_core_model['mappings']['pycsw:Type']))
        node.attrib[
            'status'] = 'urn:oasis:names:tc:ebxml-regrep:StatusType:Submitted'

        etree.SubElement(node,
                         util.nspath_eval('rim:VersionInfo', self.namespaces),
                         versionName='')

        if esn in ['summary', 'full']:
            etree.SubElement(node,
                             util.nspath_eval('rim:ExternalIdentifier',
                                              self.namespaces),
                             value=identifier,
                             identificationScheme='foo',
                             registryObject=str(
                                 util.getqattr(
                                     result,
                                     self.context.md_core_model['mappings']
                                     ['pycsw:Relation'])),
                             id=identifier)

            name = etree.SubElement(
                node, util.nspath_eval('rim:Name', self.namespaces))
            etree.SubElement(name,
                             util.nspath_eval('rim:LocalizedString',
                                              self.namespaces),
                             value=text_type(
                                 util.getqattr(
                                     result,
                                     self.context.md_core_model['mappings']
                                     ['pycsw:Title'])))

            description = etree.SubElement(
                node, util.nspath_eval('rim:Description', self.namespaces))
            etree.SubElement(description,
                             util.nspath_eval('rim:LocalizedString',
                                              self.namespaces),
                             value=text_type(
                                 util.getqattr(
                                     result,
                                     self.context.md_core_model['mappings']
                                     ['pycsw:Abstract'])))

            val = util.getqattr(
                result,
                self.context.md_core_model['mappings']['pycsw:BoundingBox'])
            bboxel = write_boundingbox(val, self.context.namespaces)

            if bboxel is not None:
                bboxslot = etree.SubElement(
                    node,
                    util.nspath_eval('rim:Slot', self.namespaces),
                    slotType='urn:ogc:def:dataType:ISO-19107:2003:GM_Envelope')

                valuelist = etree.SubElement(
                    bboxslot, util.nspath_eval('rim:ValueList',
                                               self.namespaces))
                value = etree.SubElement(
                    valuelist, util.nspath_eval('rim:Value', self.namespaces))
                value.append(bboxel)

            rkeywords = util.getqattr(
                result,
                self.context.md_core_model['mappings']['pycsw:Keywords'])
            if rkeywords is not None:
                subjectslot = etree.SubElement(
                    node,
                    util.nspath_eval('rim:Slot', self.namespaces),
                    name='http://purl.org/dc/elements/1.1/subject')
                valuelist = etree.SubElement(
                    subjectslot,
                    util.nspath_eval('rim:ValueList', self.namespaces))
                for keyword in rkeywords.split(','):
                    etree.SubElement(
                        valuelist,
                        util.nspath_eval('rim:Value',
                                         self.namespaces)).text = keyword

        return node