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)
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
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
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)
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)
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)