示例#1
0
文件: csw.py 项目: meteogrid/OWSLib
    def getrecordbyid(self, id=[], esn='full', outputschema=namespaces['csw'], format=outputformat):
        """

        Construct and process a GetRecordById request

        Parameters
        ----------

        - id: the list of Ids
        - esn: the ElementSetName 'full', 'brief' or 'summary' (default is 'full')
        - outputschema: the outputSchema (default is 'http://www.opengis.net/cat/csw/2.0.2')
        - format: the outputFormat (default is 'application/xml')

        """

        # construct request
        data = {
            'service': self.service,
            'version': self.version,
            'request': 'GetRecordById',
            'outputFormat': format,
            'outputSchema': outputschema,
            'elementsetname': esn,
            'id': ','.join(id),
        }

        self.request = urlencode(data)

        self._invoke()

        if self.exceptionreport is None:
            self.results = {}
            self.records = OrderedDict()
            self._parserecords(outputschema, esn)
示例#2
0
    def _buildMetadata(self, parse_remote_metadata=False):
        '''set up capabilities metadata objects:'''

        self.updateSequence = self._capabilities.attrib.get('updateSequence')

        # serviceIdentification metadata
        serviceelem = self._capabilities.find(
            nspath('Service', ns=WMS_NAMESPACE))
        self.identification = ServiceIdentification(serviceelem, self.version)

        # serviceProvider metadata
        self.provider = ServiceProvider(serviceelem)

        # serviceOperations metadata
        self.operations = []
        for elem in self._capabilities.find(
                nspath('Capability/Request', ns=WMS_NAMESPACE))[:]:
            self.operations.append(OperationMetadata(elem))

        # serviceContents metadata: our assumption is that services use a top-level
        # layer as a metadata organizer, nothing more.
        self.contents = OrderedDict()
        caps = self._capabilities.find(nspath('Capability', WMS_NAMESPACE))

        # recursively gather content metadata for all layer elements.
        # To the WebMapService.contents store only metadata of named layers.
        def gather_layers(parent_elem, parent_metadata):
            layers = []
            for index, elem in enumerate(
                    parent_elem.findall(nspath('Layer', WMS_NAMESPACE))):
                cm = ContentMetadata(
                    elem,
                    parent=parent_metadata,
                    index=index + 1,
                    parse_remote_metadata=parse_remote_metadata)
                if cm.id:
                    if cm.id in self.contents:
                        warnings.warn(
                            'Content metadata for layer "%s" already exists. Using child layer'
                            % cm.id)
                    layers.append(cm)
                    self.contents[cm.id] = cm
                cm.children = gather_layers(elem, cm)
            return layers

        gather_layers(caps, None)

        # exceptions
        self.exceptions = [
            f.text for f in self._capabilities.findall(
                nspath('Capability/Exception/Format', WMS_NAMESPACE))
        ]
    def get_records(self, maxrecords=50, **kwargs):
        """
        Send a GetRecords request. The results are stored in self.records property.

        :param kwargs: see OWSLib's getrecords2 (https://github.com/geopython/OWSLib/blob/master/owslib/csw.py).
        A hint: if "xml" argument is passed (raw WML request), other arguments are ignored. Also, if maxrecords exceeds
        50, getrecords2 is called multiple times to get maxrecords records (or less if less are found)
        """
        # has xml argument been passed?
        try:
            payload = kwargs['xml'].strip()
        except KeyError:
            payload = None

        # all 'csw:Record' dict from 'GetRecords' request pages
        all_records = OrderedDict()

        while True:
            # set kwargs' maxrecords according to how many records we want (doesn't matter if it exceeds 50)
            kwargs['maxrecords'] = min(maxrecords,
                                       maxrecords - len(all_records))

            # get next page by using OWSLib's getrecords2
            if payload is None:
                self.getrecords2(**kwargs)
            else:
                self.getrecords2(xml=payload)

            # store found records in all_records
            all_records.update(self.records)

            # stop if records reached limit
            if len(all_records) >= maxrecords:
                break

            next_record = self.results['nextrecord']
            # if next_record is "0", we got all records
            if next_record == 0:
                break

            # else, update start position
            if payload is None:
                kwargs['startposition'] = next_record
            else:
                payload_xml = etree.fromstring(payload)
                payload_xml.set('startPosition', str(next_record))
                payload = etree.tostring(payload_xml,
                                         pretty_print=True,
                                         encoding='unicode')

        self.records = all_records
示例#4
0
    def mundigetrecords2(self, xml):
        # removing unrelevant information from given payload
        payload = xml.strip()

        # all 'csw:Record' dictionnary from 'GetRecords' request pages
        all_records = OrderedDict()

        # getting first page (i.e. 'page0')
        self.getrecords2(xml=payload)
        all_records.update(self.records)
        page0 = lxml.etree.fromstring(self.response)

        sr_node = page0.find('csw:SearchResults', namespaces=mundi_nsmap)
        nb_total = int(sr_node.get("numberOfRecordsMatched"))
        nb_set = int(sr_node.get("numberOfRecordsReturned"))
        next_record = int(sr_node.get("nextRecord"))

        # calculation of page number
        if (nb_total == 0):
            nbPages = 1
        else:
            nbPages = ceil(nb_total / nb_set)

        # getting other/next pages (i.e. 'pageN')
        i = 1
        while (i < nbPages):
            # modifying payload with new start position
            node_p = lxml.etree.fromstring(payload)
            node_p.set('startPosition', str(next_record))
            payload = lxml.etree.tostring(node_p, pretty_print=True)
            self.getrecords2(xml=payload)
            pageN = lxml.etree.fromstring(self.response)
            sr_node = pageN.find('csw:SearchResults', namespaces=mundi_nsmap)
            next_record = int(sr_node.get("nextRecord"))
            all_records.update(self.records)
            # go next page
            i += 1
        self.records = all_records
示例#5
0
    def getrecords2(self,
                    constraints=[],
                    sortby=None,
                    typenames='csw:Record',
                    esn='summary',
                    outputschema=namespaces['csw'],
                    format=outputformat,
                    startposition=0,
                    maxrecords=10,
                    cql=None,
                    xml=None,
                    resulttype='results'):
        """

        Construct and process a  GetRecords request

        Parameters
        ----------

        - constraints: the list of constraints (OgcExpression from owslib.fes module)
        - sortby: an OGC SortBy object (SortBy from owslib.fes module)
        - typenames: the typeNames to query against (default is csw:Record)
        - esn: the ElementSetName 'full', 'brief' or 'summary' (default is 'summary')        
        - outputschema: the outputSchema (default is 'http://www.opengis.net/cat/csw/2.0.2')
        - format: the outputFormat (default is 'application/xml')
        - startposition: requests a slice of the result set, starting at this position (default is 0)
        - maxrecords: the maximum number of records to return. No records are returned if 0 (default is 10)
        - cql: common query language text.  Note this overrides bbox, qtype, keywords
        - xml: raw XML request.  Note this overrides all other options
        - resulttype: the resultType 'hits', 'results', 'validate' (default is 'results')

        """

        if xml is not None:
            self.request = etree.fromstring(xml)
            val = self.request.find(
                util.nspath_eval('csw:Query/csw:ElementSetName', namespaces))
            if val is not None:
                esn = util.testXMLValue(val)
            val = self.request.attrib.get('outputSchema')
            if val is not None:
                outputschema = util.testXMLValue(val, True)
        else:
            # construct request
            node0 = self._setrootelement('csw:GetRecords')
            if etree.__name__ != 'lxml.etree':  # apply nsmap manually
                node0.set('xmlns:ows', namespaces['ows'])
                node0.set('xmlns:gmd', namespaces['gmd'])
                node0.set('xmlns:dif', namespaces['dif'])
                node0.set('xmlns:fgdc', namespaces['fgdc'])
            node0.set('outputSchema', outputschema)
            node0.set('outputFormat', format)
            node0.set('version', self.version)
            node0.set('service', self.service)
            node0.set('resultType', resulttype)
            if startposition > 0:
                node0.set('startPosition', str(startposition))
            node0.set('maxRecords', str(maxrecords))
            node0.set(util.nspath_eval('xsi:schemaLocation', namespaces),
                      schema_location)

            node1 = etree.SubElement(node0,
                                     util.nspath_eval('csw:Query', namespaces))
            node1.set('typeNames', typenames)

            etree.SubElement(
                node1, util.nspath_eval('csw:ElementSetName',
                                        namespaces)).text = esn

            if any([len(constraints) > 0, cql is not None]):
                node2 = etree.SubElement(
                    node1, util.nspath_eval('csw:Constraint', namespaces))
                node2.set('version', '1.1.0')
                flt = fes.FilterRequest()
                if len(constraints) > 0:
                    node2.append(flt.setConstraintList(constraints))
                # Now add a CQL filter if passed in
                elif cql is not None:
                    etree.SubElement(
                        node2, util.nspath_eval('csw:CqlText',
                                                namespaces)).text = cql

            if sortby is not None and isinstance(sortby, fes.SortBy):
                node1.append(sortby.toXML())

            self.request = node0

        self._invoke()

        if self.exceptionreport is None:
            self.results = {}

            # process search results attributes
            val = self._exml.find(
                util.nspath_eval(
                    'csw:SearchResults',
                    namespaces)).attrib.get('numberOfRecordsMatched')
            self.results['matches'] = int(util.testXMLValue(val, True))
            val = self._exml.find(
                util.nspath_eval(
                    'csw:SearchResults',
                    namespaces)).attrib.get('numberOfRecordsReturned')
            self.results['returned'] = int(util.testXMLValue(val, True))
            val = self._exml.find(
                util.nspath_eval('csw:SearchResults',
                                 namespaces)).attrib.get('nextRecord')
            if val is not None:
                self.results['nextrecord'] = int(util.testXMLValue(val, True))
            else:
                warnings.warn(
                    """CSW Server did not supply a nextRecord value (it is optional), so the client
                should page through the results in another way.""")
                # For more info, see:
                # https://github.com/geopython/OWSLib/issues/100
                self.results['nextrecord'] = None

            # process list of matching records
            self.records = OrderedDict()

            self._parserecords(outputschema, esn)
示例#6
0
    def getrecords(self,
                   qtype=None,
                   keywords=[],
                   typenames='csw:Record',
                   propertyname='csw:AnyText',
                   bbox=None,
                   esn='summary',
                   sortby=None,
                   outputschema=namespaces['csw'],
                   format=outputformat,
                   startposition=0,
                   maxrecords=10,
                   cql=None,
                   xml=None,
                   resulttype='results'):
        """

        Construct and process a  GetRecords request

        Parameters
        ----------

        - qtype: type of resource to query (i.e. service, dataset)
        - keywords: list of keywords
        - typenames: the typeNames to query against (default is csw:Record)
        - propertyname: the PropertyName to Filter against 
        - bbox: the bounding box of the spatial query in the form [minx,miny,maxx,maxy]
        - esn: the ElementSetName 'full', 'brief' or 'summary' (default is 'summary')
        - sortby: property to sort results on
        - outputschema: the outputSchema (default is 'http://www.opengis.net/cat/csw/2.0.2')
        - format: the outputFormat (default is 'application/xml')
        - startposition: requests a slice of the result set, starting at this position (default is 0)
        - maxrecords: the maximum number of records to return. No records are returned if 0 (default is 10)
        - cql: common query language text.  Note this overrides bbox, qtype, keywords
        - xml: raw XML request.  Note this overrides all other options
        - resulttype: the resultType 'hits', 'results', 'validate' (default is 'results')

        """

        warnings.warn(
            """Please use the updated 'getrecords2' method instead of 'getrecords'.  
        The 'getrecords' method will be upgraded to use the 'getrecords2' parameters
        in a future version of OWSLib.""")

        if xml is not None:
            self.request = etree.fromstring(xml)
            val = self.request.find(
                util.nspath_eval('csw:Query/csw:ElementSetName', namespaces))
            if val is not None:
                esn = util.testXMLValue(val)
        else:
            # construct request
            node0 = self._setrootelement('csw:GetRecords')
            if etree.__name__ != 'lxml.etree':  # apply nsmap manually
                node0.set('xmlns:ows', namespaces['ows'])
                node0.set('xmlns:gmd', namespaces['gmd'])
                node0.set('xmlns:dif', namespaces['dif'])
                node0.set('xmlns:fgdc', namespaces['fgdc'])
            node0.set('outputSchema', outputschema)
            node0.set('outputFormat', format)
            node0.set('version', self.version)
            node0.set('resultType', resulttype)
            node0.set('service', self.service)
            if startposition > 0:
                node0.set('startPosition', str(startposition))
            node0.set('maxRecords', str(maxrecords))
            node0.set(util.nspath_eval('xsi:schemaLocation', namespaces),
                      schema_location)

            node1 = etree.SubElement(node0,
                                     util.nspath_eval('csw:Query', namespaces))
            node1.set('typeNames', typenames)

            etree.SubElement(
                node1, util.nspath_eval('csw:ElementSetName',
                                        namespaces)).text = esn

            self._setconstraint(node1, qtype, propertyname, keywords, bbox,
                                cql, None)

            if sortby is not None:
                fes.setsortby(node1, sortby)

            self.request = node0

        self._invoke()

        if self.exceptionreport is None:
            self.results = {}

            # process search results attributes
            val = self._exml.find(
                util.nspath_eval(
                    'csw:SearchResults',
                    namespaces)).attrib.get('numberOfRecordsMatched')
            self.results['matches'] = int(util.testXMLValue(val, True))
            val = self._exml.find(
                util.nspath_eval(
                    'csw:SearchResults',
                    namespaces)).attrib.get('numberOfRecordsReturned')
            self.results['returned'] = int(util.testXMLValue(val, True))
            val = self._exml.find(
                util.nspath_eval('csw:SearchResults',
                                 namespaces)).attrib.get('nextRecord')
            self.results['nextrecord'] = int(util.testXMLValue(val, True))

            # process list of matching records
            self.records = OrderedDict()

            self._parserecords(outputschema, esn)
示例#7
0
    def getrecords2(
        self,
        constraints=[],
        sortby=None,
        typenames="csw:Record",
        esn="summary",
        outputschema=csw_namespaces["csw"],
        format=csw_outputformat,
        startposition=0,
        maxrecords=10,
        cql=None,
        xml=None,
        resulttype="results",
    ):
        if xml is not None:
            self.request = etree.fromstring(xml)
            val = self.request.find(
                util.nspath_eval("csw:Query/csw:ElementSetName",
                                 csw_namespaces))
            if val is not None:
                esn = util.testXMLValue(val)
            val = self.request.attrib.get("outputSchema")
            if val is not None:
                outputschema = util.testXMLValue(val, True)
        else:
            # construct request
            node0 = self._setrootelement("csw:GetRecords")
            if etree.__name__ != "lxml.etree":  # apply nsmap manually
                node0.set("xmlns:ows", csw_namespaces["ows"])
                node0.set("xmlns:gmd", csw_namespaces["gmd"])
                node0.set("xmlns:dif", csw_namespaces["dif"])
                node0.set("xmlns:fgdc", csw_namespaces["fgdc"])
            node0.set("outputSchema", outputschema)
            node0.set("outputFormat", format)
            node0.set("version", self.version)
            node0.set("service", self.service)
            node0.set("resultType", resulttype)
            if startposition > 0:
                node0.set("startPosition", str(startposition))
            node0.set("maxRecords", str(maxrecords))
            node0.set(
                util.nspath_eval("xsi:schemaLocation", csw_namespaces),
                csw_schema_location,
            )

            node1 = etree.SubElement(
                node0, util.nspath_eval("csw:Query", csw_namespaces))
            node1.set("typeNames", typenames)

            etree.SubElement(
                node1, util.nspath_eval("csw:ElementSetName",
                                        csw_namespaces)).text = esn

            if any([len(constraints) > 0, cql is not None]):
                node2 = etree.SubElement(
                    node1, util.nspath_eval("csw:Constraint", csw_namespaces))
                node2.set("version", "1.1.0")
                flt = fes.FilterRequest()
                if len(constraints) > 0:
                    node2.append(flt.setConstraintList(constraints))
                # Now add a CQL filter if passed in
                elif cql is not None:
                    etree.SubElement(
                        node2, util.nspath_eval("csw:CqlText",
                                                csw_namespaces)).text = cql

            if sortby is not None and isinstance(sortby, fes.SortBy):
                node1.append(sortby.toXML())

            self.request = node0

        # print("Delta")
        self._invoke()

        if self.exceptionreport is None:
            self.results = {}

            # process search results attributes
            val = self._exml.find(
                util.nspath_eval(
                    "csw:SearchResults",
                    csw_namespaces)).attrib.get("numberOfRecordsMatched")
            self.results["matches"] = int(util.testXMLValue(val, True))
            val = self._exml.find(
                util.nspath_eval(
                    "csw:SearchResults",
                    csw_namespaces)).attrib.get("numberOfRecordsReturned")
            self.results["returned"] = int(util.testXMLValue(val, True))
            val = self._exml.find(
                util.nspath_eval("csw:SearchResults",
                                 csw_namespaces)).attrib.get("nextRecord")
            if val is not None:
                self.results["nextrecord"] = int(util.testXMLValue(val, True))
            else:
                warnings.warn(
                    """CSW Server did not supply a nextRecord value (it is optional), so the client
                should page through the results in another way.""")
                # For more info, see:
                # https://github.com/geopython/OWSLib/issues/100
                self.results["nextrecord"] = None

            # process list of matching records
            self.records = OrderedDict()

            self._parserecords(outputschema, esn)