Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    def response_csw2opensearch(self, element, cfg):
        """transform a CSW response into an OpenSearch response"""

        LOGGER.debug('RESPONSE: %s', util.xmltag_split(element.tag))
        try:
            version = element.xpath('//@version')[0]
        except Exception as err:
            version = '3.0.0'

        self.exml = element
        self.cfg = cfg
        self.bind_url = util.bind_url(self.cfg.get('server', 'url'))

        if version == '2.0.2':
            return self._csw2_2_os()
        elif version == '3.0.0':
            return self._csw3_2_os()
Ejemplo n.º 4
0
    def response_csw2opensearch(self, element, cfg):
        """transform a CSW response into an OpenSearch response"""

        LOGGER.debug('RESPONSE: %s', util.xmltag_split(element.tag))
        try:
            version = element.xpath('//@version')[0]
        except Exception as err:
            version = '3.0.0'

        self.exml = element
        self.cfg = cfg
        self.bind_url = util.bind_url(self.cfg.get('server', 'url'))

        if version == '2.0.2':
            return self._csw2_2_os()
        elif version == '3.0.0':
            return self._csw3_2_os()
Ejemplo n.º 5
0
    def __init__(self, element, nsmap):
        """initialize geometry parser"""

        self.nsmap = nsmap
        self.type = None
        self.wkt = None
        self.crs = None
        self._exml = element

        # return OGC WKT for GML geometry

        operand = element.xpath(
            '|'.join(TYPES), namespaces={'gml':
                                         'http://www.opengis.net/gml'})[0]

        if 'srsName' in operand.attrib:
            LOGGER.debug('geometry srsName detected')
            self.crs = crs.Crs(operand.attrib['srsName'])
        else:
            LOGGER.debug('setting default geometry srsName %s', DEFAULT_SRS)
            self.crs = DEFAULT_SRS

        self.type = util.xmltag_split(operand.tag)

        if self.type == 'Point':
            self._get_point()
        elif self.type == 'LineString':
            self._get_linestring()
        elif self.type == 'Polygon':
            self._get_polygon()
        elif self.type == 'Envelope':
            self._get_envelope()
        else:
            raise RuntimeError(
                'Unsupported geometry type (Must be one of %s)' %
                ','.join(TYPES))

        # reproject data if needed
        if self.crs is not None and self.crs.code not in [4326, 'CRS84']:
            LOGGER.debug('transforming geometry to 4326')
            try:
                self.wkt = self.transform(self.crs.code, DEFAULT_SRS.code)
            except Exception as err:
                raise RuntimeError('Reprojection error: Invalid srsName '
                                   '"%s": %s' % (self.crs.id, str(err)))
Ejemplo n.º 6
0
    def __init__(self, element, nsmap):
        """initialize geometry parser"""

        self.nsmap = nsmap
        self.type = None
        self.wkt = None
        self.crs = None
        self._exml = element

        # return OGC WKT for GML geometry

        operand = element.xpath(
            '|'.join(TYPES),
            namespaces={'gml': 'http://www.opengis.net/gml'})[0]

        if 'srsName' in operand.attrib:
            LOGGER.debug('geometry srsName detected')
            self.crs = crs.Crs(operand.attrib['srsName'])
        else:
            LOGGER.debug('setting default geometry srsName %s' % DEFAULT_SRS)
            self.crs = DEFAULT_SRS

        self.type = util.xmltag_split(operand.tag)

        if self.type == 'Point':
            self._get_point()
        elif self.type == 'LineString':
            self._get_linestring()
        elif self.type == 'Polygon':
            self._get_polygon()
        elif self.type == 'Envelope':
            self._get_envelope()
        else:
            raise RuntimeError('Unsupported geometry type (Must be one of %s)'
                               % ','.join(TYPES))

        # reproject data if needed
        if self.crs is not None and self.crs.code not in [4326, 'CRS84']:
            LOGGER.debug('transforming geometry to 4326')
            try:
                self.wkt = self.transform(self.crs.code, DEFAULT_SRS.code)
            except Exception as err:
                raise RuntimeError('Reprojection error: Invalid srsName '
                                   '"%s": %s' % (self.crs.id, str(err)))
Ejemplo n.º 7
0
    def response_csw2opensearch(self, element, cfg):
        """transform a CSW response into an OpenSearch response"""

        root_tag = util.xmltag_split(element.tag)
        if root_tag == "ExceptionReport":
            return element

        LOGGER.debug("RESPONSE: %s", root_tag)
        try:
            version = element.xpath("//@version")[0]
        except Exception as err:
            version = "3.0.0"

        self.exml = element
        self.cfg = cfg
        self.bind_url = util.bind_url(self.cfg.get("server", "url"))

        if version == "2.0.2":
            return self._csw2_2_os()
        elif version == "3.0.0":
            return self._csw3_2_os()
Ejemplo n.º 8
0
    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%%2Bxml&&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
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
def _get_comparison_operator(element):
    """return the SQL operator based on Filter query"""

    return MODEL['ComparisonOperators']['ogc:%s' % util.xmltag_split(
        element.tag)]['opvalue']
Ejemplo n.º 11
0
def _get_spatial_operator(geomattr,
                          element,
                          dbtype,
                          nsmap,
                          postgis_geometry_column='wkb_geometry'):
    """return the spatial predicate function"""
    property_name = element.find(util.nspath_eval('ogc:PropertyName', nsmap))
    distance = element.find(util.nspath_eval('ogc:Distance', nsmap))

    distance = 'false' if distance is None else distance.text

    LOGGER.debug('Scanning for spatial property name')

    if property_name is None:
        raise RuntimeError('Missing ogc:PropertyName in spatial filter')
    if (property_name.text.find('BoundingBox') == -1
            and property_name.text.find('Envelope') == -1):
        raise RuntimeError('Invalid ogc:PropertyName in spatial filter: %s' %
                           property_name.text)

    geometry = gml3.Geometry(element, nsmap)

    #make decision to apply spatial ranking to results
    set_spatial_ranking(geometry)

    spatial_predicate = util.xmltag_split(element.tag).lower()

    LOGGER.debug('Spatial predicate: %s' % spatial_predicate)

    if dbtype == 'mysql':  # adjust spatial query for MySQL
        LOGGER.debug('Adjusting spatial query for MySQL')
        if spatial_predicate == 'bbox':
            spatial_predicate = 'intersects'

        if spatial_predicate == 'beyond':
            spatial_query = "ifnull(distance(geomfromtext(%s), \
            geomfromtext('%s')) > convert(%s, signed),false)"                                                              % \
                (geomattr, geometry.wkt, distance)
        elif spatial_predicate == 'dwithin':
            spatial_query = "ifnull(distance(geomfromtext(%s), \
            geomfromtext('%s')) <= convert(%s, signed),false)"                                                               % \
                (geomattr, geometry.wkt, distance)
        else:
            spatial_query = "ifnull(%s(geomfromtext(%s), \
            geomfromtext('%s')),false)"                                        % \
                (spatial_predicate, geomattr, geometry.wkt)

    elif dbtype == 'postgresql+postgis+wkt':  # adjust spatial query for PostGIS with WKT geometry column
        LOGGER.debug('Adjusting spatial query for PostgreSQL+PostGIS+WKT')
        if spatial_predicate == 'bbox':
            spatial_predicate = 'intersects'

        if spatial_predicate == 'beyond':
            spatial_query = "not st_dwithin(st_geomfromtext(%s), \
            st_geomfromtext('%s'), %f)"                                        % \
                (geomattr, geometry.wkt, float(distance))
        elif spatial_predicate == 'dwithin':
            spatial_query = "st_dwithin(st_geomfromtext(%s), \
            st_geomfromtext('%s'), %f)"                                        % \
                (geomattr, geometry.wkt, float(distance))
        else:
            spatial_query = "st_%s(st_geomfromtext(%s), \
            st_geomfromtext('%s'))"                                    % \
                (spatial_predicate, geomattr, geometry.wkt)

    elif dbtype == 'postgresql+postgis+native':  # adjust spatial query for PostGIS with native geometry
        LOGGER.debug('Adjusting spatial query for PostgreSQL+PostGIS+native')
        if spatial_predicate == 'bbox':
            spatial_predicate = 'intersects'

        if spatial_predicate == 'beyond':
            spatial_query = "not st_dwithin(%s, \
            st_geomfromtext('%s',4326), %f)"                                             % \
                (postgis_geometry_column, geometry.wkt, float(distance))
        elif spatial_predicate == 'dwithin':
            spatial_query = "st_dwithin(%s, \
            st_geomfromtext('%s',4326), %f)"                                             % \
                (postgis_geometry_column, geometry.wkt, float(distance))
        else:
            spatial_query = "st_%s(%s, \
            st_geomfromtext('%s',4326))"                                         % \
                (spatial_predicate, postgis_geometry_column, geometry.wkt)

    else:
        LOGGER.debug('Adjusting spatial query')
        spatial_query = "query_spatial(%s,'%s','%s','%s')" % \
                        (geomattr, geometry.wkt, spatial_predicate, distance)

    return spatial_query
Ejemplo n.º 12
0
def parse(element,
          queryables,
          dbtype,
          nsmap,
          orm='sqlalchemy',
          language='english',
          fts=False):
    """OGC Filter object support"""

    boq = None
    is_pg = dbtype.startswith('postgresql')

    tmp = element.xpath('ogc:And|ogc:Or|ogc:Not', namespaces=nsmap)
    if len(tmp) > 0:  # this is binary logic query
        boq = ' %s ' % util.xmltag_split(tmp[0].tag).lower()
        LOGGER.debug('Binary logic detected; operator=%s' % boq)
        tmp = tmp[0]
    else:
        tmp = element

    pvalue_serial = [0]  # in list as python 2 has no nonlocal variable

    def assign_param():
        if orm == 'django':
            return '%s'
        param = ':pvalue%d' % pvalue_serial[0]
        pvalue_serial[0] += 1
        return param

    def _get_comparison_expression(elem):
        """return the SQL expression based on Filter query"""
        fname = None
        matchcase = elem.attrib.get('matchCase')
        wildcard = elem.attrib.get('wildCard')
        singlechar = elem.attrib.get('singleChar')
        expression = None

        if wildcard is None:
            wildcard = '%'

        if singlechar is None:
            singlechar = '_'

        if (elem.xpath('child::*')[0].tag == util.nspath_eval(
                'ogc:Function', nsmap)):
            LOGGER.debug('ogc:Function detected')
            if (elem.xpath('child::*')[0].attrib['name']
                    not in MODEL['Functions']):
                raise RuntimeError('Invalid ogc:Function: %s' %
                                   (elem.xpath('child::*')[0].attrib['name']))
            fname = elem.xpath('child::*')[0].attrib['name']

            try:
                LOGGER.debug('Testing existence of ogc:PropertyName')
                pname = queryables[elem.find(
                    util.nspath_eval('ogc:Function/ogc:PropertyName',
                                     nsmap)).text]['dbcol']
            except Exception as err:
                raise RuntimeError(
                    'Invalid PropertyName: %s.  %s' % (elem.find(
                        util.nspath_eval('ogc:Function/ogc:PropertyName',
                                         nsmap)).text, str(err)))

        else:
            try:
                LOGGER.debug('Testing existence of ogc:PropertyName')
                pname = queryables[elem.find(
                    util.nspath_eval('ogc:PropertyName', nsmap)).text]['dbcol']
            except Exception as err:
                raise RuntimeError(
                    'Invalid PropertyName: %s.  %s' %
                    (elem.find(util.nspath_eval('ogc:PropertyName',
                                                nsmap)).text, str(err)))

        if (elem.tag != util.nspath_eval('ogc:PropertyIsBetween', nsmap)):
            if elem.tag in [
                    util.nspath_eval('ogc:%s' % n, nsmap)
                    for n in MODEL['SpatialOperators']['values']
            ]:
                boolean_true = '\'true\''
                boolean_false = '\'false\''
                if dbtype == 'mysql':
                    boolean_true = 'true'
                    boolean_false = 'false'

                return "%s = %s" % (_get_spatial_operator(
                    queryables['pycsw:BoundingBox'], elem, dbtype,
                    nsmap), boolean_true)
            else:
                pval = elem.find(util.nspath_eval('ogc:Literal', nsmap)).text

        com_op = _get_comparison_operator(elem)
        LOGGER.debug('Comparison operator: %s' % com_op)

        # if this is a case insensitive search
        # then set the DB-specific LIKE comparison operator

        LOGGER.debug('Setting csw:AnyText property')

        anytext = queryables['csw:AnyText']['dbcol']
        if ((matchcase is not None and matchcase == 'false')
                or pname == anytext):
            com_op = 'ilike' if is_pg else 'like'

        if (elem.tag == util.nspath_eval('ogc:PropertyIsBetween', nsmap)):
            com_op = 'between'
            lower_boundary = elem.find(
                util.nspath_eval('ogc:LowerBoundary/ogc:Literal', nsmap)).text
            upper_boundary = elem.find(
                util.nspath_eval('ogc:UpperBoundary/ogc:Literal', nsmap)).text
            expression = "%s %s %s and %s" % \
                           (pname, com_op, assign_param(), assign_param())
            values.append(lower_boundary)
            values.append(upper_boundary)
        else:
            if pname == anytext and is_pg and fts:
                LOGGER.debug('PostgreSQL FTS specific search')
                # do nothing, let FTS do conversion (#212)
                pvalue = pval
            else:
                LOGGER.debug('PostgreSQL non-FTS specific search')
                pvalue = pval.replace(wildcard, '%').replace(singlechar, '_')

                if pname == anytext:  # pad anytext with wildcards
                    LOGGER.debug('PostgreSQL non-FTS specific anytext search')
                    LOGGER.debug('old value: %s', pval)

                    pvalue = '%%%s%%' % pvalue.rstrip('%').lstrip('%')

                    LOGGER.debug('new value: %s', pvalue)

            values.append(pvalue)

            if boq == ' not ':
                if fname is not None:
                    expression = "%s is null or not %s(%s) %s %s" % \
                                   (pname, fname, pname, com_op, assign_param())
                elif pname == anytext and is_pg and fts:
                    LOGGER.debug('PostgreSQL FTS specific search')
                    expression = (
                        "%s is null or not plainto_tsquery('%s', %s) @@ anytext_tsvector"
                        % (anytext, language, assign_param()))
                else:
                    LOGGER.debug('PostgreSQL non-FTS specific search')
                    expression = "%s is null or not %s %s %s" % \
                                   (pname, pname, com_op, assign_param())
            else:
                if fname is not None:
                    expression = "%s(%s) %s %s" % \
                                   (fname, pname, com_op, assign_param())
                elif pname == anytext and is_pg and fts:
                    LOGGER.debug('PostgreSQL FTS specific search')
                    expression = (
                        "plainto_tsquery('%s', %s) @@ anytext_tsvector" %
                        (language, assign_param()))
                else:
                    LOGGER.debug('PostgreSQL non-FTS specific search')
                    expression = "%s %s %s" % (pname, com_op, assign_param())

        return expression

    queries = []
    queries_nested = []
    values = []

    LOGGER.debug('Scanning children elements')
    for child in tmp.xpath('child::*'):
        com_op = ''
        boolean_true = '\'true\''
        boolean_false = '\'false\''

        if dbtype == 'mysql':
            boolean_true = 'true'
            boolean_false = 'false'

        if child.tag == util.nspath_eval('ogc:Not', nsmap):
            LOGGER.debug('ogc:Not query detected')
            child_not = child.xpath('child::*')[0]
            if child_not.tag in \
                [util.nspath_eval('ogc:%s' % n, nsmap) for n in
                    MODEL['SpatialOperators']['values']]:
                LOGGER.debug('ogc:Not / spatial operator detected: %s' %
                             child.tag)
                queries.append("%s = %s" % (_get_spatial_operator(
                    queryables['pycsw:BoundingBox'],
                    child.xpath('child::*')[0], dbtype, nsmap), boolean_false))
            else:
                LOGGER.debug('ogc:Not / comparison operator detected: %s' %
                             child.tag)
                queries.append('not %s' %
                               _get_comparison_expression(child_not))

        elif child.tag in \
            [util.nspath_eval('ogc:%s' % n, nsmap) for n in
                MODEL['SpatialOperators']['values']]:
            LOGGER.debug('spatial operator detected: %s' % child.tag)
            if boq is not None and boq == ' not ':
                # for ogc:Not spatial queries in PostGIS we must explictly
                # test that pycsw:BoundingBox is null as well
                # TODO: Do we need the same for 'postgresql+postgis+native'???
                if dbtype == 'postgresql+postgis+wkt':
                    LOGGER.debug('Setting bbox is null test in PostgreSQL')
                    queries.append(
                        "%s = %s or %s is null" %
                        (_get_spatial_operator(queryables['pycsw:BoundingBox'],
                                               child, dbtype, nsmap),
                         boolean_false, queryables['pycsw:BoundingBox']))
                else:
                    queries.append("%s = %s" % (_get_spatial_operator(
                        queryables['pycsw:BoundingBox'], child, dbtype,
                        nsmap), boolean_false))
            else:
                queries.append("%s = %s" % (_get_spatial_operator(
                    queryables['pycsw:BoundingBox'], child, dbtype,
                    nsmap), boolean_true))

        elif child.tag == util.nspath_eval('ogc:FeatureId', nsmap):
            LOGGER.debug('ogc:FeatureId filter detected')
            queries.append("%s = %s" %
                           (queryables['pycsw:Identifier'], assign_param()))
            values.append(child.attrib.get('fid'))
        else:  # comparison operator
            LOGGER.debug('Comparison operator processing')
            tagname = ' %s ' % util.xmltag_split(child.tag).lower()
            if tagname in [' or ',
                           ' and ']:  # this is a nested binary logic query
                LOGGER.debug('Nested binary logic detected; operator=%s' %
                             tagname)
                for child2 in child.xpath('child::*'):
                    queries_nested.append(_get_comparison_expression(child2))
                queries.append('(%s)' % tagname.join(queries_nested))
            else:
                queries.append(_get_comparison_expression(child))

    where = boq.join(queries) if (boq is not None and boq != ' not ') \
        else queries[0]

    return where, values
Ejemplo n.º 13
0
def parse(element, queryables, dbtype, nsmap, orm='sqlalchemy', language='english', fts=False):
    """OGC Filter object support"""

    boq = None
    is_pg = dbtype.startswith('postgresql')

    tmp = element.xpath('ogc:And|ogc:Or|ogc:Not', namespaces=nsmap)
    if len(tmp) > 0:  # this is binary logic query
        boq = ' %s ' % util.xmltag_split(tmp[0].tag).lower()
        LOGGER.debug('Binary logic detected; operator=%s' % boq)
        tmp = tmp[0]
    else:
        tmp = element

    pvalue_serial = [0]  # in list as python 2 has no nonlocal variable
    def assign_param():
        if orm == 'django':
            return '%s'
        param = ':pvalue%d' % pvalue_serial[0]
        pvalue_serial[0] += 1
        return param

    def _get_comparison_expression(elem):
        """return the SQL expression based on Filter query"""
        fname = None
        matchcase = elem.attrib.get('matchCase')
        wildcard = elem.attrib.get('wildCard')
        singlechar = elem.attrib.get('singleChar')
        expression = None

        if wildcard is None:
            wildcard = '%'

        if singlechar is None:
            singlechar = '_'

        if (elem.xpath('child::*')[0].tag ==
                util.nspath_eval('ogc:Function', nsmap)):
            LOGGER.debug('ogc:Function detected')
            if (elem.xpath('child::*')[0].attrib['name'] not in
                    MODEL['Functions']):
                raise RuntimeError('Invalid ogc:Function: %s' %
                                   (elem.xpath('child::*')[0].attrib['name']))
            fname = elem.xpath('child::*')[0].attrib['name']

            try:
                LOGGER.debug('Testing existence of ogc:PropertyName')
                pname = queryables[elem.find(util.nspath_eval('ogc:Function/ogc:PropertyName', nsmap)).text]['dbcol']
            except Exception as err:
                raise RuntimeError('Invalid PropertyName: %s.  %s' % (elem.find(util.nspath_eval('ogc:Function/ogc:PropertyName', nsmap)).text, str(err)))

        else:
            try:
                LOGGER.debug('Testing existence of ogc:PropertyName')
                pname = queryables[elem.find(
                    util.nspath_eval('ogc:PropertyName', nsmap)).text]['dbcol']
            except Exception as err:
                raise RuntimeError('Invalid PropertyName: %s.  %s' %
                                   (elem.find(util.nspath_eval('ogc:PropertyName',
                                   nsmap)).text, str(err)))

        if (elem.tag != util.nspath_eval('ogc:PropertyIsBetween', nsmap)):
            if elem.tag in [util.nspath_eval('ogc:%s' % n, nsmap) for n in
                MODEL['SpatialOperators']['values']]:
                boolean_true = '\'true\''
                boolean_false = '\'false\''
                if dbtype == 'mysql':
                    boolean_true = 'true'
                    boolean_false = 'false'

                return "%s = %s" % (_get_spatial_operator(queryables['pycsw:BoundingBox'], elem, dbtype, nsmap), boolean_true)
            else:
                pval = elem.find(util.nspath_eval('ogc:Literal', nsmap)).text

        com_op = _get_comparison_operator(elem)
        LOGGER.debug('Comparison operator: %s' % com_op)

        # if this is a case insensitive search
        # then set the DB-specific LIKE comparison operator

        LOGGER.debug('Setting csw:AnyText property')

        anytext = queryables['csw:AnyText']['dbcol']
        if ((matchcase is not None and matchcase == 'false') or
                pname == anytext):
            com_op = 'ilike' if is_pg else 'like'

        if (elem.tag == util.nspath_eval('ogc:PropertyIsBetween', nsmap)):
            com_op = 'between'
            lower_boundary = elem.find(
                util.nspath_eval('ogc:LowerBoundary/ogc:Literal',
                                 nsmap)).text
            upper_boundary = elem.find(
                util.nspath_eval('ogc:UpperBoundary/ogc:Literal',
                                 nsmap)).text
            expression = "%s %s %s and %s" % \
                           (pname, com_op, assign_param(), assign_param())
            values.append(lower_boundary)
            values.append(upper_boundary)
        else:
            if pname == anytext and is_pg and fts:
                LOGGER.debug('PostgreSQL FTS specific search')
                # do nothing, let FTS do conversion (#212)
                pvalue = pval
            else:
                LOGGER.debug('PostgreSQL non-FTS specific search')
                pvalue = pval.replace(wildcard, '%').replace(singlechar, '_')

                if pname == anytext:  # pad anytext with wildcards
                    LOGGER.debug('PostgreSQL non-FTS specific anytext search')
                    LOGGER.debug('old value: %s', pval)

                    pvalue = '%%%s%%' % pvalue.rstrip('%').lstrip('%')

                    LOGGER.debug('new value: %s', pvalue)

            values.append(pvalue)

            if boq == ' not ':
                if fname is not None:
                    expression = "%s is null or not %s(%s) %s %s" % \
                                   (pname, fname, pname, com_op, assign_param())
                elif pname == anytext and is_pg and fts:
                    LOGGER.debug('PostgreSQL FTS specific search')
                    expression = ("%s is null or not plainto_tsquery('%s', %s) @@ anytext_tsvector" %
                                  (anytext, language, assign_param()))
                else:
                    LOGGER.debug('PostgreSQL non-FTS specific search')
                    expression = "%s is null or not %s %s %s" % \
                                   (pname, pname, com_op, assign_param())
            else:
                if fname is not None:
                    expression = "%s(%s) %s %s" % \
                                   (fname, pname, com_op, assign_param())
                elif pname == anytext and is_pg and fts:
                    LOGGER.debug('PostgreSQL FTS specific search')
                    expression = ("plainto_tsquery('%s', %s) @@ anytext_tsvector" %
                                  (language, assign_param()))
                else:
                    LOGGER.debug('PostgreSQL non-FTS specific search')
                    expression = "%s %s %s" % (pname, com_op, assign_param())

        return expression

    queries = []
    queries_nested = []
    values = []

    LOGGER.debug('Scanning children elements')
    for child in tmp.xpath('child::*'):
        com_op = ''
        boolean_true = '\'true\''
        boolean_false = '\'false\''

        if dbtype == 'mysql':
            boolean_true = 'true'
            boolean_false = 'false'

        if child.tag == util.nspath_eval('ogc:Not', nsmap):
            LOGGER.debug('ogc:Not query detected')
            child_not = child.xpath('child::*')[0]
            if child_not.tag in \
                [util.nspath_eval('ogc:%s' % n, nsmap) for n in
                    MODEL['SpatialOperators']['values']]:
                LOGGER.debug('ogc:Not / spatial operator detected: %s' % child.tag)
                queries.append("%s = %s" %
                               (_get_spatial_operator(
                                   queryables['pycsw:BoundingBox'],
                                   child.xpath('child::*')[0], dbtype, nsmap),
                                   boolean_false))
            else:
                LOGGER.debug('ogc:Not / comparison operator detected: %s' % child.tag)
                queries.append('not %s' % _get_comparison_expression(child_not))

        elif child.tag in \
            [util.nspath_eval('ogc:%s' % n, nsmap) for n in
                MODEL['SpatialOperators']['values']]:
            LOGGER.debug('spatial operator detected: %s' % child.tag)
            if boq is not None and boq == ' not ':
                # for ogc:Not spatial queries in PostGIS we must explictly
                # test that pycsw:BoundingBox is null as well
                # TODO: Do we need the same for 'postgresql+postgis+native'???
                if dbtype == 'postgresql+postgis+wkt':
                    LOGGER.debug('Setting bbox is null test in PostgreSQL')
                    queries.append("%s = %s or %s is null" %
                                   (_get_spatial_operator(
                                       queryables['pycsw:BoundingBox'],
                                       child, dbtype, nsmap), boolean_false,
                                       queryables['pycsw:BoundingBox']))
                else:
                    queries.append("%s = %s" %
                                   (_get_spatial_operator(
                                       queryables['pycsw:BoundingBox'],
                                       child, dbtype, nsmap), boolean_false))
            else:
                queries.append("%s = %s" %
                               (_get_spatial_operator(
                                   queryables['pycsw:BoundingBox'],
                                   child, dbtype, nsmap), boolean_true))

        elif child.tag == util.nspath_eval('ogc:FeatureId', nsmap):
            LOGGER.debug('ogc:FeatureId filter detected')
            queries.append("%s = %s" % (queryables['pycsw:Identifier'], assign_param()))
            values.append(child.attrib.get('fid'))
        else:  # comparison operator
            LOGGER.debug('Comparison operator processing')
            tagname = ' %s ' % util.xmltag_split(child.tag).lower()
            if tagname in [' or ', ' and ']:  # this is a nested binary logic query
                LOGGER.debug('Nested binary logic detected; operator=%s' % tagname)
                for child2 in child.xpath('child::*'):
                    queries_nested.append(_get_comparison_expression(child2))
                queries.append('(%s)' % tagname.join(queries_nested))
            else:
                queries.append(_get_comparison_expression(child))

    where = boq.join(queries) if (boq is not None and boq != ' not ') \
        else queries[0]

    return where, values
Ejemplo n.º 14
0
def _get_comparison_operator(element):
    """return the SQL operator based on Filter query"""

    return MODEL['ComparisonOperators']['ogc:%s' % util.xmltag_split(element.tag)]['opvalue']
Ejemplo n.º 15
0
def _get_spatial_operator(geomattr, element, dbtype, nsmap, postgis_geometry_column='wkb_geometry'):
    """return the spatial predicate function"""
    property_name = element.find(util.nspath_eval('ogc:PropertyName', nsmap))
    distance = element.find(util.nspath_eval('ogc:Distance', nsmap))

    distance = 'false' if distance is None else distance.text

    LOGGER.debug('Scanning for spatial property name')

    if property_name is None:
        raise RuntimeError('Missing ogc:PropertyName in spatial filter')
    if (property_name.text.find('BoundingBox') == -1 and
            property_name.text.find('Envelope') == -1):
        raise RuntimeError('Invalid ogc:PropertyName in spatial filter: %s' %
                           property_name.text)

    geometry = gml3.Geometry(element, nsmap)

    #make decision to apply spatial ranking to results
    set_spatial_ranking(geometry)

    spatial_predicate = util.xmltag_split(element.tag).lower()

    LOGGER.debug('Spatial predicate: %s' % spatial_predicate)

    if dbtype == 'mysql':  # adjust spatial query for MySQL
        LOGGER.debug('Adjusting spatial query for MySQL')
        if spatial_predicate == 'bbox':
            spatial_predicate = 'intersects'

        if spatial_predicate == 'beyond':
            spatial_query = "ifnull(distance(geomfromtext(%s), \
            geomfromtext('%s')) > convert(%s, signed),false)" % \
                (geomattr, geometry.wkt, distance)
        elif spatial_predicate == 'dwithin':
            spatial_query = "ifnull(distance(geomfromtext(%s), \
            geomfromtext('%s')) <= convert(%s, signed),false)" % \
                (geomattr, geometry.wkt, distance)
        else:
            spatial_query = "ifnull(%s(geomfromtext(%s), \
            geomfromtext('%s')),false)" % \
                (spatial_predicate, geomattr, geometry.wkt)

    elif dbtype == 'postgresql+postgis+wkt':  # adjust spatial query for PostGIS with WKT geometry column
        LOGGER.debug('Adjusting spatial query for PostgreSQL+PostGIS+WKT')
        if spatial_predicate == 'bbox':
            spatial_predicate = 'intersects'

        if spatial_predicate == 'beyond':
            spatial_query = "not st_dwithin(st_geomfromtext(%s), \
            st_geomfromtext('%s'), %f)" % \
                (geomattr, geometry.wkt, float(distance))
        elif spatial_predicate == 'dwithin':
            spatial_query = "st_dwithin(st_geomfromtext(%s), \
            st_geomfromtext('%s'), %f)" % \
                (geomattr, geometry.wkt, float(distance))
        else:
            spatial_query = "st_%s(st_geomfromtext(%s), \
            st_geomfromtext('%s'))" % \
                (spatial_predicate, geomattr, geometry.wkt)

    elif dbtype == 'postgresql+postgis+native':  # adjust spatial query for PostGIS with native geometry
        LOGGER.debug('Adjusting spatial query for PostgreSQL+PostGIS+native')
        if spatial_predicate == 'bbox':
            spatial_predicate = 'intersects'

        if spatial_predicate == 'beyond':
            spatial_query = "not st_dwithin(%s, \
            st_geomfromtext('%s',4326), %f)" % \
                (postgis_geometry_column, geometry.wkt, float(distance))
        elif spatial_predicate == 'dwithin':
            spatial_query = "st_dwithin(%s, \
            st_geomfromtext('%s',4326), %f)" % \
                (postgis_geometry_column, geometry.wkt, float(distance))
        else:
            spatial_query = "st_%s(%s, \
            st_geomfromtext('%s',4326))" % \
                (spatial_predicate, postgis_geometry_column, geometry.wkt)

    else:
        LOGGER.debug('Adjusting spatial query')
        spatial_query = "query_spatial(%s,'%s','%s','%s')" % \
                        (geomattr, geometry.wkt, spatial_predicate, distance)

    return spatial_query
Ejemplo n.º 16
0
    def response_csw2sru(self, element, environ):
        """transform a CSW response into an SRU response"""

        if util.xmltag_split(element.tag) == '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 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 util.xmltag_split(element.tag) == '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 util.xmltag_split(element.tag) == 'ExceptionReport':
            node = self.exceptionreport2diagnostic(element)
        return node
Ejemplo n.º 17
0
    def response_csw2sru(self, element, environ):
        """transform a CSW response into an SRU response"""

        if util.xmltag_split(element.tag) == '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 self.mappings['csw:Record']['index'].iteritems():
                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 util.xmltag_split(element.tag) == '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 util.xmltag_split(element.tag) == 'ExceptionReport':
            node = self.exceptionreport2diagnostic(element)
        return node
Ejemplo n.º 18
0
    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
Ejemplo n.º 19
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
Ejemplo n.º 20
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.items():
            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.items():
                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.items():
                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
Ejemplo n.º 21
0
    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