def _build_metadata(self, parse_remote_metadata=False): '''set up capabilities metadata objects: ''' # ServiceIdentification val = self._capabilities.find(nspath_eval('ows:ServiceIdentification', self.ows_version)) self.identification = ServiceIdentification(val,self.ows_namespace) # ServiceProvider val = self._capabilities.find(nspath_eval('ows:ServiceProvider', self.ows_version)) self.provider = ServiceProvider(val,self.ows_namespace) # ServiceOperations metadata op = self._capabilities.find(nspath_eval('ows:OperationsMetadata', self.ows_version)) self.operations = OperationsMetadata(op, self.ows_namespace).operations # FilterCapabilities val = self._capabilities.find(nspath_eval('ogc:Filter_Capabilities')) self.filters = FilterCapabilities(val) #serviceContents metadata: our assumption is that services use a top-level #layer as a metadata organizer, nothing more. self.contents={} features = self._capabilities.findall(nspath_eval('wfs:FeatureTypeList/wfs:FeatureType')) for feature in features: cm = ContentMetadata(feature, parse_remote_metadata) self.contents[cm.id] = cm #exceptions self.exceptions = [f.text for f \ in self._capabilities.findall('Capability/Exception/Format')]
def _build_metadata(self): """ Set up capabilities metadata objects """ # ows:ServiceIdentification metadata service_id_element = self._capabilities.find(nspath_eval('ows:ServiceIdentification', namespaces)) self.identification = ows.ServiceIdentification(service_id_element) # ows:ServiceProvider metadata service_provider_element = self._capabilities.find(nspath_eval('ows:ServiceProvider', namespaces)) self.provider = ows.ServiceProvider(service_provider_element) # ows:OperationsMetadata metadata self.operations=[] for elem in self._capabilities.findall(nspath_eval('ows:OperationsMetadata/ows:Operation', namespaces)): self.operations.append(ows.OperationsMetadata(elem)) # sos:FilterCapabilities filters = self._capabilities.find(nspath_eval('sos:Filter_Capabilities', namespaces)) if filters is not None: self.filters = FilterCapabilities(filters) else: self.filters = None # sos:Contents metadata self.contents = {} self.offerings = [] for offering in self._capabilities.findall(nspath_eval('sos:Contents/sos:ObservationOfferingList/sos:ObservationOffering', namespaces)): off = SosObservationOffering(offering) self.contents[off.id] = off self.offerings.append(off)
def __init__(self, md): val = md.find(util.nspath_eval('dif:File', namespaces)) self.file = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:URL', namespaces)) self.url = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Format', namespaces)) self.format = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Caption', namespaces)) self.caption = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Description', namespaces)) self.description = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Visualization_URL', namespaces)) self.vis_url = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Visualization_Type', namespaces)) self.vis_type = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Visualization_Subtype', namespaces)) self.vis_subtype = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Visualization_Duration', namespaces)) self.vis_duration = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Visualization_File_Size', namespaces)) self.file_size = util.testXMLValue(val)
def __init__(self, elem): # Spatial_Capabilities self.spatial_operands = [ f.text for f in elem.findall(util.nspath_eval("ogc:Spatial_Capabilities/ogc:GeometryOperands/ogc:GeometryOperand")) ] self.spatial_operators = [] for f in elem.findall(util.nspath_eval("ogc:Spatial_Capabilities/ogc:SpatialOperators/ogc:SpatialOperator")): self.spatial_operators.append(f.attrib["name"]) # Temporal_Capabilities self.temporal_operands = [ f.text for f in elem.findall( util.nspath_eval("ogc:Temporal_Capabilities/ogc:TemporalOperands/ogc:TemporalOperand") ) ] self.temporal_operators = [] for f in elem.findall(util.nspath_eval("ogc:Temporal_Capabilities/ogc:TemporalOperators/ogc:TemporalOperator")): self.temporal_operators.append(f.attrib["name"]) # Scalar_Capabilities self.scalar_comparison_operators = [ f.text for f in elem.findall( util.nspath_eval("ogc:Scalar_Capabilities/ogc:ComparisonOperators/ogc:ComparisonOperator") ) ]
def __init__(self, md): self.conformancetitle = [] for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:title/gco:CharacterString', namespaces)): val = util.testXMLValue(i) if val is not None: self.conformancetitle.append(val) self.conformancedate = [] for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:date/gmd:CI_Date/gmd:date/gco:Date', namespaces)): val = util.testXMLValue(i) if val is not None: self.conformancedate.append(val) self.conformancedatetype = [] for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:specification/gmd:CI_Citation/gmd:date/gmd:CI_Date/gmd:dateType/gmd:CI_DateTypeCode', namespaces)): val = util.testXMLValue(i) if val is not None: self.conformancedatetype.append(val) self.conformancedegree = [] for i in md.findall(util.nspath_eval('gmd:report/gmd:DQ_DomainConsistency/gmd:result/gmd:DQ_ConformanceResult/gmd:pass/gco:Boolean', namespaces)): val = util.testXMLValue(i) if val is not None: self.conformancedegree.append(val) val = md.find(util.nspath_eval('gmd:lineage/gmd:LI_Lineage/gmd:statement/gco:CharacterString', namespaces)) self.lineage = util.testXMLValue(val)
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 node0 = self._setrootelement("csw:GetRecordById") node0.set("outputSchema", outputschema) node0.set("outputFormat", format) node0.set("version", self.version) node0.set("service", self.service) node0.set(util.nspath_eval("xsi:schemaLocation", namespaces), schema_location) for i in id: etree.SubElement(node0, util.nspath_eval("csw:Id", namespaces)).text = i etree.SubElement(node0, util.nspath_eval("csw:ElementSetName", namespaces)).text = esn self.request = node0 self._invoke() if self.exceptionreport is None: self.results = {} self.records = {} self._parserecords(outputschema, esn)
def __init__(self, md): """constructor""" _GenericObject.__init__(self, md) self.name = util.testXMLValue(md.find(util.nspath_eval("gm03:name", namespaces))) self.version = util.testXMLValue(md.find(util.nspath_eval("gm03:version", versionspaces)))
def describerecord(self, typename="csw:Record", format=outputformat): """ Construct and process DescribeRecord request Parameters ---------- - typename: the typename to describe (default is 'csw:Record') - format: the outputFormat (default is 'application/xml') """ # construct request node0 = self._setrootelement("csw:DescribeRecord") node0.set("service", self.service) node0.set("version", self.version) node0.set("outputFormat", format) node0.set("schemaLanguage", namespaces["xs2"]) node0.set(util.nspath_eval("xsi:schemaLocation", namespaces), schema_location) etree.SubElement(node0, util.nspath_eval("csw:TypeName", namespaces)).text = typename self.request = node0 self._invoke()
def toXML(self): node0 = etree.Element(util.nspath_eval(self.propertyoperator, namespaces)) if not self.matchcase: node0.set('matchCase', 'false') etree.SubElement(node0, util.nspath_eval('ogc:PropertyName', namespaces)).text = self.propertyname etree.SubElement(node0, util.nspath_eval('ogc:Literal', namespaces)).text = self.literal return node0
def toXML(self): tmp = etree.Element(util.nspath_eval('ogc:BBOX', namespaces)) etree.SubElement(tmp, util.nspath_eval('ogc:PropertyName', namespaces)).text = 'ows:BoundingBox' tmp2 = etree.SubElement(tmp, util.nspath_eval('gml:Envelope', namespaces)) etree.SubElement(tmp2, util.nspath_eval('gml:lowerCorner', namespaces)).text = '%s %s' % (self.bbox[0], self.bbox[1]) etree.SubElement(tmp2, util.nspath_eval('gml:upperCorner', namespaces)).text = '%s %s' % (self.bbox[2], self.bbox[3]) return tmp
def __init__(self, url, lang='en-US', version='2.0.2', timeout=10, skip_caps=False, username=None, password=None): """ Construct and process a GetCapabilities request Parameters ---------- - url: the URL of the CSW - lang: the language (default is 'en-US') - version: version (default is '2.0.2') - timeout: timeout in seconds - skip_caps: whether to skip GetCapabilities processing on init (default is False) - username: username for HTTP basic authentication - password: password for HTTP basic authentication """ self.url = url self.lang = lang self.version = version self.timeout = timeout self.username = username self.password = password self.service = 'CSW' self.exceptionreport = None self.owscommon = ows.OwsCommon('1.0.0') if not skip_caps: # process GetCapabilities # construct request data = {'service': self.service, 'version': self.version, 'request': 'GetCapabilities'} self.request = urlencode(data) self._invoke() if self.exceptionreport is None: # ServiceIdentification val = self._exml.find(util.nspath_eval('ows:ServiceIdentification', namespaces)) if val is not None: self.identification = ows.ServiceIdentification(val,self.owscommon.namespace) else: self.identification = None # ServiceProvider val = self._exml.find(util.nspath_eval('ows:ServiceProvider', namespaces)) if val is not None: self.provider = ows.ServiceProvider(val,self.owscommon.namespace) else: self.provider = None # ServiceOperations metadata self.operations = [] for elem in self._exml.findall(util.nspath_eval('ows:OperationsMetadata/ows:Operation', namespaces)): self.operations.append(ows.OperationsMetadata(elem, self.owscommon.namespace)) # FilterCapabilities val = self._exml.find(util.nspath_eval('ogc:Filter_Capabilities', namespaces)) self.filters = fes.FilterCapabilities(val)
def toXML(self): node0 = etree.Element(util.nspath_eval('ogc:PropertyIsLike', namespaces)) node0.set('wildCard', self.wildCard) node0.set('singleChar', self.singleChar) node0.set('escapeChar', self.escapeChar) etree.SubElement(node0, util.nspath_eval('ogc:PropertyName', namespaces)).text = self.propertyname etree.SubElement(node0, util.nspath_eval('ogc:Literal', namespaces)).text = self.literal return node0
def __init__(self, md): """constructor""" self.language = util.testXMLValue(md.find(util.nspath_eval("gm03:language", namespaces))) self.country = util.testXMLValue(md.find(util.nspath_eval("gm03:country", namespaces))) self.character_set_code = util.testXMLValue(md.find(util.nspath_eval("gm03:characterSetCode", namespaces))) self.plain_text = util.testXMLValue(md.find(util.nspath_eval("gm03:plainText", namespaces))) self.plain_url = util.testXMLValue(md.find(util.nspath_eval("gm03:plainURL", namespaces)))
def __init__(self, md): """constructor""" val = md.find(util.nspath_eval("gm03:MD_Distribution", namespaces)) self.distribution = _GenericObjectProperty(val) val = md.find(util.nspath_eval("gm03:distributionFormat", namespaces)) self.distribution_format = _GenericObjectProperty(val)
def __init__(self, md): """constructor""" val = md.find(util.nspath_eval("gm03:referenceSystemInfo", namespaces)) self.reference_system_info = _GenericObjectProperty(val) val = md.find(util.nspath_eval("gm03:MD_Metadata", namespaces)) self.metadata = _GenericObjectProperty(val)
def __init__(self, md): val = md.find(util.nspath_eval('gmd:extentTypeCode')) self.is_extent = util.testXMLValue(val) md_polygons = md.findall(util.nspath_eval('gmd:polygon')) self.polygons = [] for val in md_polygons: self.polygons.append(EX_Polygon(val))
def __init__(self, md): val = md.find(util.nspath_eval('dif:Discipline_Name', namespaces)) self.name = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Subdiscipline', namespaces)) self.subdiscipline = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Detailed_Subdiscipline', namespaces)) self.detailed_subdiscipline = util.testXMLValue(val)
def __init__(self, md): """constructor""" _GenericObject.__init__(self, md) self.extent_type_code = util.testXMLValue(md.find(util.nspath_eval("gm03:extentTypeCode", namespaces))) val = md.find(util.nspath_eval("gm03:geographicIdentifier", namespaces)) self.geographic_identifier = _GenericObjectProperty(val)
def __init__(self, md): val = md.find(util.nspath_eval('gmd:EX_GeographicBoundingBox/gmd:westBoundLongitude/gco:Decimal', namespaces)) self.minx = util.testXMLValue(val) val = md.find(util.nspath_eval('gmd:EX_GeographicBoundingBox/gmd:eastBoundLongitude/gco:Decimal', namespaces)) self.maxx = util.testXMLValue(val) val = md.find(util.nspath_eval('gmd:EX_GeographicBoundingBox/gmd:southBoundLatitude/gco:Decimal', namespaces)) self.miny = util.testXMLValue(val) val = md.find(util.nspath_eval('gmd:EX_GeographicBoundingBox/gmd:northBoundLatitude/gco:Decimal', namespaces)) self.maxy = util.testXMLValue(val)
def __init__(self, md): """constructor""" _GenericObject.__init__(self, md) self.level = util.testXMLValue(md.find(util.nspath_eval("gm03:level", namespaces))) val = md.find(util.nspath_eval("gm03:DQ_DataQuality", namespaces)) self.data_quality = _GenericObjectProperty(val)
def __init__(self, md): val = md.find(util.nspath_eval('gmd:westBoundLongitude/gco:Decimal')) self.minx = util.testXMLValue(val) val = md.find(util.nspath_eval('gmd:eastBoundLongitude/gco:Decimal')) self.maxx = util.testXMLValue(val) val = md.find(util.nspath_eval('gmd:southBoundLatitude/gco:Decimal')) self.miny = util.testXMLValue(val) val = md.find(util.nspath_eval('gmd:northBoundLatitude/gco:Decimal')) self.maxy = util.testXMLValue(val)
def __init__(self, md=None): if md is None: self.id = None self.languagecode = None self.charset = None else: self.id = md.attrib.get('id') self.languagecode = md.find(util.nspath_eval('gmd:languageCode/gmd:LanguageCode', namespaces)).attrib.get('codeListValue') self.charset = md.find(util.nspath_eval('gmd:characterEncoding/gmd:MD_CharacterSetCode', namespaces)).attrib.get('codeListValue')
def __init__(self, md): linear_ring = md.find(util.nspath_eval('gml32:Polygon/gml32:exterior/gml32:LinearRing')) if linear_ring is not None: self.exterior_ring = self._coordinates_for_ring(linear_ring) interior_ring_elements = md.findall(util.nspath_eval('gml32:Polygon/gml32:interior')) self.interior_rings = [] for iring_element in interior_ring_elements: linear_ring = iring_element.find(util.nspath_eval('gml32:LinearRing')) self.interior_rings.append(self._coordinates_for_ring(linear_ring))
def __init__(self, md): """constructor""" _GenericObject.__init__(self, md) val = md.find(util.nspath_eval("gm03:parentResponsibleParty", namespaces)) self.parent_responsible_party = _GenericObjectProperty(val) val = md.find(util.nspath_eval("gm03:CI_ResponsibleParty", namespaces)) self.responsible_party = _GenericObjectProperty(val)
def __init__(self, md): """constructor""" _GenericObject.__init__(self, md) val = md.find(util.nspath_eval("gm03:spatialExtent", namespaces)) self.spatial_extent = _GenericObjectProperty(val) val = md.find(util.nspath_eval("gm03:EX_SpatialTemporalExtent", namespaces)) self.spatial_temporal_extent = _GenericObjectProperty(val)
def __init__(self, md): """constructor""" _GenericObject.__init__(self, md) self.hours_of_service = util.testXMLValue(md.find(util.nspath_eval("gm03:hoursOfService", namespaces))) val = md.find(util.nspath_eval("gm03:contactInstructions", namespaces)) if val is not None: self.contact_instructions = PT_FreeText(val)
def __init__(self, md): """constructor""" _GenericObject.__init__(self, md) self.date = util.testXMLValue(md.find(util.nspath_eval("gm03:date", namespaces))) self.date_type = util.testXMLValue(md.find(util.nspath_eval("gm03:dateType", namespaces))) val = md.find(util.nspath_eval("gm03:CI_Citation", namespaces)) self.citation = _GenericObjectProperty(val)
def __init__(self, md): """constructor""" _GenericObject.__init__(self, md) self.extent_type_code = util.testXMLValue(md.find(util.nspath_eval("gm03:extentTypeCode", namespaces))) self.north_bound_latitude = util.testXMLValue(md.find(util.nspath_eval("gm03:northBoundLatitude", namespaces))) self.south_bound_latitude = util.testXMLValue(md.find(util.nspath_eval("gm03:southBoundLatitude", namespaces))) self.east_bound_longitude = util.testXMLValue(md.find(util.nspath_eval("gm03:eastBoundLongitude", namespaces))) self.west_bound_longitude = util.testXMLValue(md.find(util.nspath_eval("gm03:westBoundLongitude", namespaces)))
def __init__(self, md): """constructor""" _GenericObject.__init__(self, md) self.number = util.testXMLValue(md.find(util.nspath_eval("gm03:number", namespaces))) self.number_type = util.testXMLValue(md.find(util.nspath_eval("gm03:numberType", namespaces))) val = md.find(util.nspath_eval("gm03:CI_ResponsibleParty", namespaces)) self.responsible_party = _GenericObjectProperty(val)
def __init__(self, md): """constructor""" _GenericObject.__init__(self, md) val = md.find(util.nspath_eval("gm03:descriptiveKeywords", namespaces)) self.descriptive_keywords = _GenericObjectProperty(val) val = md.find(util.nspath_eval("gm03:MD_Identification", namespaces)) self.identification = _GenericObjectProperty(val)
def get_feature_of_interest(self, featuresOfInterest=None, observedProperties=None, procedures=None, responseFormat=None, method=None, **kwargs): """Performs "GetFeatureOfInterest" request Parameters ---------- featuresOfInterest : non-empty list of str, optional request only specific features of interest observedProperties: non-empty list of str, optional request only specific observed properties procedures: non-empty list of str, optional request only specific procedures responseFormat : str, optional response format method: str, optional http method (default is "Get") Returns ------- response of the request as <class 'bytes'> """ method = method or 'Get' methods = self.get_operation_by_name('GetFeatureOfInterest').methods base_url = [m['url'] for m in methods if m['type'] == method][0] request = { 'service': 'SOS', 'version': self.version, 'request': 'GetFeatureOfInterest' } # Optional Fields if featuresOfInterest is not None: check_list_param(featuresOfInterest) featureOfInterest = ','.join(featuresOfInterest) request['featureOfInterest'] = featureOfInterest if observedProperties is not None: check_list_param(observedProperties) observedProperty = ','.join(observedProperties) request['observedProperty'] = observedProperty if procedures is not None: check_list_param(procedures) procedure = ','.join(procedures) request['procedure'] = procedure if responseFormat is not None: request['responseFormat'] = responseFormat url_kwargs = {} if 'timeout' in kwargs: url_kwargs['timeout'] = kwargs.pop( 'timeout') # Client specified timeout value if kwargs: for kw in kwargs: request[kw] = kwargs[kw] response = openURL(base_url, request, method, username=self.username, password=self.password, **url_kwargs).read() try: tr = etree.fromstring(response) if tr.tag == nspath_eval("ows:ExceptionReport", namespaces): raise ows.ExceptionReport(tr) else: return response except ows.ExceptionReport: raise except BaseException: return response
def get_data_availability(self, procedures=None, observedProperties=None, featuresOfInterest=None, offerings=None, method=None, **kwargs): """Performs "GetDataAvailability" request Parameters ---------- procedures: non-empty list of str, optional request only specific procedures observedProperties: non-empty list of str, optional request only specific observed properties featuresOfInterest : non-empty list of str, optional request only specific features of interest offerings : non-empty list of str, optional request only specific offerings method: str, optional http method (default is "Get") Returns ------- list of GetDataAvailability members """ method = method or 'Get' try: base_url = next(( m.get('url') for m in self.getOperationByName('GetDataAvailability').methods if m.get('type').lower() == method.lower())) except StopIteration: base_url = self.url #Mandatory request parameters request = { 'service': 'SOS', 'version': "2.0.0", 'request': 'GetDataAvailability' } # Optional Fields if procedures is not None: check_list_param(procedures) procedure = ','.join(procedures) request['procedure'] = procedure if observedProperties is not None: check_list_param(observedProperties) observedProperty = ','.join(observedProperties) request['observedProperty'] = observedProperty if featuresOfInterest is not None: check_list_param(featuresOfInterest) featureOfInterest = ','.join(featuresOfInterest) request['featureOfInterest'] = featureOfInterest if offerings is not None: check_list_param(offerings) offering = ','.join(offerings) request['offering'] = offering url_kwargs = {} if 'timeout' in kwargs: url_kwargs['timeout'] = kwargs.pop( 'timeout') # Client specified timeout value if kwargs: for kw in kwargs: request[kw] = kwargs[kw] request_gda = openURL(base_url, request, method, username=self.username, password=self.password, **url_kwargs).read() gda = etree.fromstring(request_gda) if gda.tag == nspath_eval("ows:ExceptionReport", namespaces): raise ows.ExceptionReport(gda) gdaMembers = gda.findall( nspath_eval("gda:dataAvailabilityMember", namespaces)) final = list(map(gda_member, gdaMembers)) return (final)
def harvest(self, source, resourcetype, resourceformat=None, harvestinterval=None, responsehandler=None): """ Construct and process a Harvest request Parameters ---------- - source: a URI to harvest - resourcetype: namespace identifying the type of resource - resourceformat: MIME type of the resource - harvestinterval: frequency of harvesting, in ISO8601 - responsehandler: endpoint that CSW should responsd to with response """ # construct request node0 = self._setrootelement('csw:Harvest') node0.set('version', self.version) node0.set('service', self.service) node0.set(util.nspath_eval('xsi:schemaLocation', namespaces), schema_location) etree.SubElement(node0, util.nspath_eval('csw:Source', namespaces)).text = source etree.SubElement(node0, util.nspath_eval('csw:ResourceType', namespaces)).text = resourcetype if resourceformat is not None: etree.SubElement( node0, util.nspath_eval('csw:ResourceFormat', namespaces)).text = resourceformat if harvestinterval is not None: etree.SubElement( node0, util.nspath_eval('csw:HarvestInterval', namespaces)).text = harvestinterval if responsehandler is not None: etree.SubElement( node0, util.nspath_eval('csw:ResponseHandler', namespaces)).text = responsehandler self.request = node0 self._invoke() self.results = {} if self.exceptionreport is None: val = self._exml.find( util.nspath_eval('csw:Acknowledgement', namespaces)) if util.testXMLValue(val) is not None: ts = val.attrib.get('timeStamp') self.timestamp = util.testXMLValue(ts, True) id = val.find(util.nspath_eval('csw:RequestId', namespaces)) self.id = util.testXMLValue(id) else: self._parsetransactionsummary() self._parseinsertresult()
def toXML(self): node0 = etree.Element(util.nspath_eval(self.urary_operator, namespaces)) for op in self.operations: node0.append(op.toXML()) return node0
def _parseinsertresult(self): self.results['insertresults'] = [] for i in self._exml.findall('.//'+util.nspath_eval('csw:InsertResult', namespaces)): for j in i.findall(util.nspath_eval('csw:BriefRecord/dc:identifier', namespaces)): self.results['insertresults'].append(util.testXMLValue(j))
def __init__(self, el): val = el.find(util.nspath_eval('dif:Dataset_Creator', namespaces)) self.creator = util.testXMLValue(val) val = el.find(util.nspath_eval('dif:Dataset_Title', namespaces)) self.title = util.testXMLValue(val) val = el.find(util.nspath_eval('dif:Dataset_Series_Name', namespaces)) self.series_name = util.testXMLValue(val) val = el.find(util.nspath_eval('dif:Dataset_Release_Date', namespaces)) self.release_date = util.testXMLValue(val) val = el.find(util.nspath_eval('dif:Dataset_Release_Place', namespaces)) self.release_place = util.testXMLValue(val) val = el.find(util.nspath_eval('dif:Dataset_Publisher', namespaces)) self.publisher = util.testXMLValue(val) val = el.find(util.nspath_eval('dif:Version', namespaces)) self.version = util.testXMLValue(val) val = el.find(util.nspath_eval('dif:Issue_Identification', namespaces)) self.issue_identification = util.testXMLValue(val) val = el.find( util.nspath_eval('dif:Data_Presentation_Form', namespaces)) self.presentation_form = util.testXMLValue(val) val = el.find( util.nspath_eval('dif:Other_Citation_Details', namespaces)) self.details = util.testXMLValue(val) val = el.find(util.nspath_eval('dif:Online_Resource', namespaces)) self.onlineresource = util.testXMLValue(val)
def _setrootelement(self, el): if etree.__name__ == 'lxml.etree': # apply nsmap return etree.Element(util.nspath_eval(el, namespaces), nsmap=namespaces) else: return etree.Element(util.nspath_eval(el, namespaces))
def transaction(self, ttype=None, typename='csw30:Record', record=None, propertyname=None, propertyvalue=None, bbox=None, keywords=[], cql=None, identifier=None): """ Construct and process a Transaction request Parameters ---------- - ttype: the type of transaction 'insert, 'update', 'delete' - typename: the typename to describe (default is 'csw30:Record') - record: the XML record to insert - propertyname: the RecordProperty/PropertyName to Filter against - propertyvalue: the RecordProperty Value to Filter against (for updates) - bbox: the bounding box of the spatial query in the form [minx,miny,maxx,maxy] - keywords: list of keywords - cql: common query language text. Note this overrides bbox, qtype, keywords - identifier: record identifier. Note this overrides bbox, qtype, keywords, cql """ # construct request node0 = self._setrootelement('csw30:Transaction') node0.set('version', self.version) node0.set('service', self.service) node0.set(util.nspath_eval('xsi:schemaLocation', namespaces), schema_location) validtransactions = ['insert', 'update', 'delete'] if ttype not in validtransactions: # invalid transaction raise RuntimeError('Invalid transaction \'%s\'.' % ttype) node1 = etree.SubElement(node0, util.nspath_eval('csw30:%s' % ttype.capitalize(), namespaces)) if ttype != 'update': node1.set('typeName', typename) if ttype == 'insert': if record is None: raise RuntimeError('Nothing to insert.') node1.append(etree.fromstring(record)) if ttype == 'update': if record is not None: node1.append(etree.fromstring(record)) else: if propertyname is not None and propertyvalue is not None: node2 = etree.SubElement(node1, util.nspath_eval('csw30:RecordProperty', namespaces)) etree.SubElement(node2, util.nspath_eval('csw30:Name', namespaces)).text = propertyname etree.SubElement(node2, util.nspath_eval('csw30:Value', namespaces)).text = propertyvalue self._setconstraint(node1, None, propertyname, keywords, bbox, cql, identifier) if ttype == 'delete': self._setconstraint(node1, None, propertyname, keywords, bbox, cql, identifier) self.request = node0 self._invoke() self.results = {} if self.exceptionreport is None: self._parsetransactionsummary() self._parseinsertresult()
def getrecords(self, constraints=[], sortby=None, typenames='csw30:Record', esn='summary', outputschema=namespaces['csw30'], format=outputformat, startposition=0, maxrecords=10, cql=None, xml=None, distributedsearch=False, hopcount=2, federatedcatalogues=[]): """ Construct and process a GetRecords request Parameters ---------- - constraints: the list of constraints (OgcExpression from owslib.fes2 module) - sortby: an OGC SortBy object (SortBy from owslib.fes2 module) - typenames: the typeNames to query against (default is csw30:Record) - esn: the ElementSetName 'full', 'brief' or 'summary' (default is 'summary') - outputschema: the outputSchema (default is 'http://www.opengis.net/cat/csw/3.0.0') - 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 - distributedsearch: `bool` of whether to trigger distributed search - hopcount: number of message hops before search is terminated (default is 1) - federatedcatalogues: list of CSW 3 URLs """ if xml is not None: if str(xml).startswith('<'): self.request = etree.fromstring(xml) val = self.request.find(util.nspath_eval('csw30:Query/csw30: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: self.request = xml else: # construct request node0 = self._setrootelement('csw30:GetRecords') if etree.__name__ != 'lxml.etree': # apply nsmap manually node0.set('xmlns:ows110', namespaces['ows110']) 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) if startposition > 0: node0.set('startPosition', str(startposition)) node0.set('maxRecords', str(maxrecords)) node0.set(util.nspath_eval('xsi:schemaLocation', namespaces), schema_location) if distributedsearch: node00 = etree.SubElement(node0, util.nspath_eval('csw30:DistributedSearch', namespaces), hopCount=str(hopcount), clientId='owslib', distributedSearchId='owslib-request') if federatedcatalogues: for fc in federatedcatalogues: etree.SubElement(node00, util.nspath_eval('csw30:federatedCatalogues', namespaces), catalogueURL=fc) node1 = etree.SubElement(node0, util.nspath_eval('csw30:Query', namespaces)) node1.set('typeNames', typenames) etree.SubElement(node1, util.nspath_eval('csw30:ElementSetName', namespaces)).text = esn if any([len(constraints) > 0, cql is not None]): node2 = etree.SubElement(node1, util.nspath_eval('csw30:Constraint', namespaces)) node2.set('version', '1.1.0') flt = fes2.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('csw30:CqlText', namespaces)).text = cql if sortby is not None and isinstance(sortby, fes2.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('csw30:SearchResults', namespaces)).attrib.get('numberOfRecordsMatched') self.results['matches'] = int(util.testXMLValue(val, True)) val = self._exml.find( util.nspath_eval('csw30:SearchResults', namespaces)).attrib.get('numberOfRecordsReturned') self.results['returned'] = int(util.testXMLValue(val, True)) val = self._exml.find(util.nspath_eval('csw30: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 nspv(path): return nspath_eval(path, namespaces)
def __init__(self, element): self._root = element self.id = testXMLValue( self._root.attrib.get(nspath_eval('gml:id', namespaces)), True) self.description = testXMLValue( self._root.find(nspath_eval('gml:description', namespaces))) self.name = testXMLValue( self._root.find(nspath_eval('gml:name', namespaces))) val = testXMLValue( self._root.find(nspath_eval('gml:srsName', namespaces))) if val is not None: self.srs = Crs(val) # LOOK: Check on GML boundedBy to make sure we handle all of the cases # gml:boundedBy try: envelope = self._root.find( nspath_eval('gml:boundedBy/gml:Envelope', namespaces)) lower_left_corner = testXMLValue( envelope.find(nspath_eval('gml:lowerCorner', namespaces))).split() upper_right_corner = testXMLValue( envelope.find(nspath_eval('gml:upperCorner', namespaces))).split() # (left, bottom, right, top) in self.bbox_srs units self.bbox = (float(lower_left_corner[1]), float(lower_left_corner[0]), float(upper_right_corner[1]), float(upper_right_corner[0])) self.bbox_srs = Crs( testXMLValue(envelope.attrib.get('srsName'), True)) except Exception: self.bbox = None self.bbox_srs = None # LOOK: Support all gml:TimeGeometricPrimitivePropertyType # Right now we are just supporting gml:TimePeriod # sos:Time begin_position_element = self._root.find( nspath_eval('sos:time/gml:TimePeriod/gml:beginPosition', namespaces)) self.begin_position = extract_time(begin_position_element) end_position_element = self._root.find( nspath_eval('sos:time/gml:TimePeriod/gml:endPosition', namespaces)) self.end_position = extract_time(end_position_element) self.result_model = testXMLValue( self._root.find(nspath_eval('sos:resultModel', namespaces))) self.procedures = [] for proc in self._root.findall(nspath_eval('sos:procedure', namespaces)): self.procedures.append( testXMLValue( proc.attrib.get(nspath_eval('xlink:href', namespaces)), True)) # LOOK: Support swe:Phenomenon here # this includes compound properties self.observed_properties = [] for op in self._root.findall( nspath_eval('sos:observedProperty', namespaces)): self.observed_properties.append( testXMLValue( op.attrib.get(nspath_eval('xlink:href', namespaces)), True)) self.features_of_interest = [] for fot in self._root.findall( nspath_eval('sos:featureOfInterest', namespaces)): self.features_of_interest.append( testXMLValue( fot.attrib.get(nspath_eval('xlink:href', namespaces)), True)) self.response_formats = [] for rf in self._root.findall( nspath_eval('sos:responseFormat', namespaces)): self.response_formats.append(testXMLValue(rf)) self.response_modes = [] for rm in self._root.findall( nspath_eval('sos:responseMode', namespaces)): self.response_modes.append(testXMLValue(rm))
def __init__(self, url, lang='en-US', version='2.0.2', timeout=10, skip_caps=False, username=None, password=None): """ Construct and process a GetCapabilities request Parameters ---------- - url: the URL of the CSW - lang: the language (default is 'en-US') - version: version (default is '2.0.2') - timeout: timeout in seconds - skip_caps: whether to skip GetCapabilities processing on init (default is False) - username: username for HTTP basic authentication - password: password for HTTP basic authentication """ self.url = url self.lang = lang self.version = version self.timeout = timeout self.username = username self.password = password self.service = 'CSW' self.exceptionreport = None self.owscommon = ows.OwsCommon('1.0.0') if not skip_caps: # process GetCapabilities # construct request data = {'service': self.service, 'version': self.version, 'request': 'GetCapabilities'} self.request = urlencode(data) self._invoke() if self.exceptionreport is None: self.updateSequence = self._exml.getroot().attrib.get('updateSequence') # ServiceIdentification val = self._exml.find(util.nspath_eval('ows:ServiceIdentification', namespaces)) if val is not None: self.identification = ows.ServiceIdentification(val,self.owscommon.namespace) else: self.identification = None # ServiceProvider val = self._exml.find(util.nspath_eval('ows:ServiceProvider', namespaces)) if val is not None: self.provider = ows.ServiceProvider(val,self.owscommon.namespace) else: self.provider = None # ServiceOperations metadata self.operations = [] for elem in self._exml.findall(util.nspath_eval('ows:OperationsMetadata/ows:Operation', namespaces)): self.operations.append(ows.OperationsMetadata(elem, self.owscommon.namespace)) self.constraints = {} for elem in self._exml.findall(util.nspath_eval('ows:OperationsMetadata/ows:Constraint', namespaces)): self.constraints[elem.attrib['name']] = ows.Constraint(elem, self.owscommon.namespace) self.parameters = {} for elem in self._exml.findall(util.nspath_eval('ows:OperationsMetadata/ows:Parameter', namespaces)): self.parameters[elem.attrib['name']] = ows.Parameter(elem, self.owscommon.namespace) # FilterCapabilities val = self._exml.find(util.nspath_eval('ogc:Filter_Capabilities', namespaces)) self.filters = fes.FilterCapabilities(val)
def toXML(self): node0 = etree.Element(util.nspath_eval("ogc:SortBy", namespaces)) for prop in self.properties: node0.append(prop.toXML()) return node0
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 get_observation(self, responseFormat=None, offerings=None, observedProperties=None, eventTime=None, procedure=None, method='Get', **kwargs): """ Parameters ---------- format : string Output format. Provide one that is available for all offerings method : string Optional. HTTP DCP method name: Get or Post. Must **kwargs : extra arguments anything else e.g. vendor specific parameters """ try: base_url = next( (m.get('url') for m in self.getOperationByName('GetObservation').methods if m.get('type').lower() == method.lower())) except StopIteration: base_url = self.url request = { 'service': 'SOS', 'version': self.version, 'request': 'GetObservation' } # Required Fields assert isinstance(offerings, list) and len(offerings) > 0 request['offering'] = ','.join(offerings) assert isinstance(observedProperties, list) and len(observedProperties) > 0 request['observedProperty'] = ','.join(observedProperties) assert isinstance(responseFormat, str) request['responseFormat'] = responseFormat # Optional Fields if eventTime is not None: request['eventTime'] = eventTime url_kwargs = {} if 'timeout' in kwargs: url_kwargs['timeout'] = kwargs.pop( 'timeout') # Client specified timeout value if procedure is not None: request['procedure'] = procedure if kwargs: for kw in kwargs: request[kw] = kwargs[kw] data = urlencode(request) response = openURL(base_url, data, method, username=self.username, password=self.password, **url_kwargs).read() try: tr = etree.fromstring(response) if tr.tag == nspath_eval("ows:ExceptionReport", namespaces): raise ows.ExceptionReport(tr) else: return response except ows.ExceptionReport: raise except BaseException: return response
def __init__(self, md): val = md.find(util.nspath_eval('dif:Start_Date', namespaces)) self.start_date = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:End_Date', namespaces)) self.end_date = util.testXMLValue(val)
def __init__(self, md): val = md.find(util.nspath_eval('dif:Type', namespaces)) self.type = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:SubType', namespaces)) self.subtype = util.testXMLValue(val)
def nsp(self, path): """ """ return nspath_eval(path, self.namespaces)
def __init__(self, md): val = md.find(util.nspath_eval('dif:Entry_ID', namespaces)) self.identifier = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Entry_Title', namespaces)) self.title = util.testXMLValue(val) self.citation = [] for el in md.findall( util.nspath_eval('dif:Data_Set_Citation', namespaces)): self.citation.append(Citation(el)) self.personnel = [] for el in md.findall(util.nspath_eval('dif:Personnel', namespaces)): self.personnel.append(util.testXMLValue(el)) self.discipline = [] for el in md.findall(util.nspath_eval('dif:Discipline', namespaces)): self.discipline.append(util.testXMLValue(el)) self.parameters = [] for el in md.findall(util.nspath_eval('dif:Parameters', namespaces)): self.parameters.append(util.testXMLValue(el)) self.iso_topic_category = [] for el in md.findall( util.nspath_eval('dif:ISO_Topic_Category', namespaces)): self.iso_topic_category.append(util.testXMLValue(el)) self.keyword = [] for el in md.findall(util.nspath_eval('dif:Keyword', namespaces)): self.keyword.append(util.testXMLValue(el)) self.sensor_name = [] for el in md.findall(util.nspath_eval('dif:Sensor_Name', namespaces)): self.sensor_name.append(Name(el)) self.source_name = [] for el in md.findall(util.nspath_eval('dif:Source_Name', namespaces)): self.source_name.append(Name(el)) self.temporal_coverage = [] for el in md.findall( util.nspath_eval('dif:Temporal_Coverage', namespaces)): self.temporal_coverage.append(Temporal_Coverage(el)) self.paleo_temporal_coverage = [] for el in md.findall( util.nspath_eval('dif:Paleo_Temporal_Coverage', namespaces)): self.paleo_temporal_coverage.append(Paleo_Temporal_Coverage(el)) self.data_set_progress = [] for el in md.findall( util.nspath_eval('dif:Data_Set_Progress', namespaces)): self.data_set_progress.append(util.testXMLValue(el)) self.spatial_coverage = [] for el in md.findall( util.nspath_eval('dif:Spatial_Coverage', namespaces)): self.spatial_coverage.append(Spatial_Coverage(el)) self.location = [] for el in md.findall(util.nspath_eval('dif:location', namespaces)): self.location.append(util.testXMLValue(el)) self.data_resolution = [] for el in md.findall( util.nspath_eval('dif:Data_Resolution', namespaces)): self.data_resolution.append(Data_Resolution(el)) self.project = [] for el in md.findall(util.nspath_eval('dif:Project', namespaces)): self.project.append(Name(el)) val = md.find(util.nspath_eval('dif:Quality', namespaces)) self.quality = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Access_Constraints', namespaces)) self.access_constraints = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Use_Constraints', namespaces)) self.use_constraints = util.testXMLValue(val) self.language = [] for el in md.findall( util.nspath_eval('dif:Data_Set_Language', namespaces)): self.language.append(util.testXMLValue(el)) self.originating_center = [] for el in md.findall( util.nspath_eval('dif:Originating_Center', namespaces)): self.originating_center.append(util.testXMLValue(el)) self.data_center = [] for el in md.findall(util.nspath_eval('dif:Data_Center', namespaces)): self.data_center.append(Data_Center(el)) self.distribution = [] for el in md.findall(util.nspath_eval('dif:Distribution', namespaces)): self.distribution.append(Distribution(el)) self.multimedia_sample = [] for el in md.findall( util.nspath_eval('dif:Multimedia_Sample', namespaces)): self.multimedia_sample.append(Multimedia_Sample(el)) val = md.find(util.nspath_eval('dif:Reference', namespaces)) self.reference = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Summary', namespaces)) self.summary = util.testXMLValue(val) self.related_url = [] for el in md.findall(util.nspath_eval('dif:Related_URL', namespaces)): self.related_url.append(Related_URL(el)) self.parent_dif = [] for el in md.findall(util.nspath_eval('dif:Parent_DIF', namespaces)): self.parent_dif.append(util.testXMLValue(el)) self.idn_node = [] for el in md.findall(util.nspath_eval('dif:IDN_Node', namespaces)): self.idn_node.append(Name(el)) val = md.find( util.nspath_eval('dif:Originating_Metadata_Node', namespaces)) self.originating_metadata_node = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Metadata_Name', namespaces)) self.metadata_name = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Metadata_Version', namespaces)) self.metadata_version = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:DIF_Creation_Date', namespaces)) self.dif_creation_date = util.testXMLValue(val) val = md.find( util.nspath_eval('dif:Last_DIF_Revision_Date', namespaces)) self.last_dif_revision_date = util.testXMLValue(val) val = md.find( util.nspath_eval('dif:Future_DIF_Review_Date', namespaces)) self.future_dif_review_date = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Private', namespaces)) self.private = util.testXMLValue(val)
def get_observation(self, responseFormat=None, offerings=None, observedProperties=None, featuresOfInterest=None, procedures=None, eventTime=None, method=None, **kwargs): """Overrides parent function get_observation() Performs "GetObservation" request Parameters ---------- responseFormat : str response format, e.g. 'http://www.opengis.net/om/2.0' offerings : non-empty list of str, optional request only specific offerings observedProperties: non-empty list of str, optional request only specific observed properties featuresOfInterest : non-empty list of str, optional request only specific features of interest procedures: non-empty list of str, optional request only specific procedures eventTime: str, optional event time as om:resultTime, e.g. 'om:resultTime,2019-01-01T12:00:00Z/2019-01-02T12:00:00Z' method: str, optional http method (default is "Get") **kwargs : extra arguments anything else e.g. vendor specific parameters It is recommended to provide at least one of featuresOfInterest, observedProperties, offerings or procedures. Otherwise the request may take very long. Returns ------- response of the request as <class 'bytes'> """ method = method or 'Get' # Pluck out the get observation URL for HTTP method - methods is an # array of dicts methods = self.get_operation_by_name('GetObservation').methods base_url = [m['url'] for m in methods if m['type'] == method][0] request = { 'service': 'SOS', 'version': self.version, 'request': 'GetObservation' } if responseFormat is not None: request['responseFormat'] = responseFormat if offerings is not None: check_list_param(offerings) offering = ','.join(offerings) request['offering'] = offering if observedProperties is not None: check_list_param(observedProperties) observedProperty = ','.join(observedProperties) request['observedProperty'] = observedProperty if featuresOfInterest is not None: check_list_param(featuresOfInterest) featureOfInterest = ','.join(featuresOfInterest) request['featureOfInterest'] = featureOfInterest if procedures is not None: check_list_param(procedures) procedure = ','.join(procedures) request['procedure'] = procedure if eventTime is not None: request['temporalFilter'] = eventTime url_kwargs = {} if 'timeout' in kwargs: url_kwargs['timeout'] = kwargs.pop( 'timeout') # Client specified timeout value if kwargs: for kw in kwargs: request[kw] = kwargs[kw] response = openURL(base_url, request, method, username=self.username, password=self.password, **url_kwargs).read() try: tr = etree.fromstring(response) if tr.tag == nspath_eval("ows:ExceptionReport", namespaces): raise ows.ExceptionReport(tr) else: return response except ows.ExceptionReport: raise except BaseException: return response
def getfeature(self, typename=None, filter=None, bbox=None, featureid=None, featureversion=None, propertyname=['*'], maxfeatures=None, srsname=None, method='Get'): """Request and return feature data as a file-like object. Parameters ---------- typename : list List of typenames (string) filter : string XML-encoded OGC filter expression. bbox : tuple (left, bottom, right, top) in the feature type's coordinates. featureid : list List of unique feature ids (string) featureversion : string Default is most recent feature version. propertyname : list List of feature property names. '*' matches all. maxfeatures : int Maximum number of features to be returned. method : string Qualified name of the HTTP DCP method to use. srsname: string EPSG code to request the data in There are 3 different modes of use 1) typename and bbox (simple spatial query). It is assumed, that bbox coordinates are given *always* in the east,north order 2) typename and filter (more expressive) 3) featureid (direct access to known features) """ base_url = self.getOperationByName('GetFeature').methods[method]['url'] request = {'service': 'WFS', 'version': self.version, 'request': 'GetFeature'} srs_func = None if type(typename) == type(""): typename=[typename] if srsname: # check, if desired SRS is supported by the service if typename: # convert srsname string to Crs object srsnameobj = self.getSRS(srsname,typename[0]) if srsname: # set the srsname string with propper function # (getcode or getcodeurn) request['srsname'] = srsnameobj.encoding == "urn" and\ srsnameobj.getcodeurn() or srsnameobj.getcode() else: raise util.ServiceException, "SRSNAME %s not supported" % srsname else: request['srsname'] = str(srsname) # check featureid if featureid: request['featureid'] = ','.join(featureid) # bbox elif bbox and typename: # srs of the bbox is specified in the bbox as fifth paramter srs = None if len(bbox) == 5: srs = self.getSRS(bbox[4],typename[0]) # take default srs else: srs = self.contents[typename[0]].crsOptions[0] # format bbox parameter if srs.encoding == "urn" : if srs.axisorder == "yx": request["bbox"] = "%s,%s,%s,%s,%s" % \ (bbox[1],bbox[0],bbox[3],bbox[2],srs.getcodeurn()) else: request["bbox"] = "%s,%s,%s,%s,%s" % \ (bbox[0],bbox[1],bbox[2],bbox[3],srs.getcodeurn()) else: request["bbox"] = "%s,%s,%s,%s,%s" % \ (bbox[0],bbox[1],bbox[2],bbox[3],srs.getcode()) # or filter elif filter and typename: request['filter'] = str(filter) assert len(typename) > 0 request['typename'] = ','.join(typename) if propertyname: request['propertyname'] = ','.join(propertyname) if featureversion: request['featureversion'] = str(featureversion) if maxfeatures: request['maxfeatures'] = str(maxfeatures) data = urlencode(request) u = openURL(base_url, data, method) # check for service exceptions, rewrap, and return # We're going to assume that anything with a content-length > 32k # is data. We'll check anything smaller. try: length = int(u.info()['Content-Length']) have_read = False except (KeyError, AttributeError): data = u.read() have_read = True length = len(data) if length < 32000: if not have_read: data = u.read() tree = etree.fromstring(data) if tree.tag == "{%s}ServiceExceptionReport" % namespaces["ogc"]: se = tree.find(nspath_eval('ServiceException', namespaces["ogc"])) raise util.ServiceException, str(se.text).strip() return StringIO(data) else: if have_read: return StringIO(data) return u
def __init__(self, record): if hasattr(record, 'getroot'): # standalone document self.xml = etree.tostring(record.getroot()) else: # part of a larger document self.xml = etree.tostring(record) # check to see if Dublin Core record comes from # rdf:RDF/rdf:Description container # (child content model is identical) self.rdf = False rdf = record.find(util.nspath_eval('rdf:Description', namespaces)) if rdf is not None: self.rdf = True record = rdf # some CSWs return records with multiple identifiers based on # different schemes. Use the first dc:identifier value to set # self.identifier, and set self.identifiers as a list of dicts val = record.find(util.nspath_eval('dc:identifier', namespaces)) self.identifier = util.testXMLValue(val) self.identifiers = [] for i in record.findall(util.nspath_eval('dc:identifier', namespaces)): d = {} d['scheme'] = i.attrib.get('scheme') d['identifier'] = i.text self.identifiers.append(d) val = record.find(util.nspath_eval('dc:type', namespaces)) self.type = util.testXMLValue(val) val = record.find(util.nspath_eval('dc:title', namespaces)) self.title = util.testXMLValue(val) val = record.find(util.nspath_eval('dct:alternative', namespaces)) self.alternative = util.testXMLValue(val) val = record.find(util.nspath_eval('dct:isPartOf', namespaces)) self.ispartof = util.testXMLValue(val) val = record.find(util.nspath_eval('dct:abstract', namespaces)) self.abstract = util.testXMLValue(val) val = record.find(util.nspath_eval('dc:date', namespaces)) self.date = util.testXMLValue(val) val = record.find(util.nspath_eval('dct:created', namespaces)) self.created = util.testXMLValue(val) val = record.find(util.nspath_eval('dct:issued', namespaces)) self.issued = util.testXMLValue(val) val = record.find(util.nspath_eval('dc:relation', namespaces)) self.relation = util.testXMLValue(val) val = record.find(util.nspath_eval('dct:temporal', namespaces)) self.temporal = util.testXMLValue(val) self.uris = [] # list of dicts for i in record.findall(util.nspath_eval('dc:URI', namespaces)): uri = {} uri['protocol'] = util.testXMLValue(i.attrib.get('protocol'), True) uri['name'] = util.testXMLValue(i.attrib.get('name'), True) uri['description'] = util.testXMLValue(i.attrib.get('description'), True) uri['url'] = util.testXMLValue(i) self.uris.append(uri) self.references = [] # list of dicts for i in record.findall(util.nspath_eval('dct:references', namespaces)): ref = {} ref['scheme'] = util.testXMLValue(i.attrib.get('scheme'), True) ref['url'] = util.testXMLValue(i) self.references.append(ref) val = record.find(util.nspath_eval('dct:modified', namespaces)) self.modified = util.testXMLValue(val) val = record.find(util.nspath_eval('dc:creator', namespaces)) self.creator = util.testXMLValue(val) val = record.find(util.nspath_eval('dc:publisher', namespaces)) self.publisher = util.testXMLValue(val) val = record.find(util.nspath_eval('dc:coverage', namespaces)) self.coverage = util.testXMLValue(val) val = record.find(util.nspath_eval('dc:contributor', namespaces)) self.contributor = util.testXMLValue(val) val = record.find(util.nspath_eval('dc:language', namespaces)) self.language = util.testXMLValue(val) val = record.find(util.nspath_eval('dc:source', namespaces)) self.source = util.testXMLValue(val) val = record.find(util.nspath_eval('dct:rightsHolder', namespaces)) self.rightsholder = util.testXMLValue(val) val = record.find(util.nspath_eval('dct:accessRights', namespaces)) self.accessrights = util.testXMLValue(val) val = record.find(util.nspath_eval('dct:license', namespaces)) self.license = util.testXMLValue(val) val = record.find(util.nspath_eval('dc:format', namespaces)) self.format = util.testXMLValue(val) self.subjects = [] for i in record.findall(util.nspath_eval('dc:subject', namespaces)): self.subjects.append(util.testXMLValue(i)) self.rights = [] for i in record.findall(util.nspath_eval('dc:rights', namespaces)): self.rights.append(util.testXMLValue(i)) val = record.find(util.nspath_eval('dct:spatial', namespaces)) self.spatial = util.testXMLValue(val) val = record.find(util.nspath_eval('ows:BoundingBox', namespaces)) if val is not None: self.bbox = ows.BoundingBox(val, namespaces['ows']) else: self.bbox = None val = record.find(util.nspath_eval('ows:WGS84BoundingBox', namespaces)) if val is not None: self.bbox_wgs84 = ows.WGS84BoundingBox(val, namespaces['ows']) else: self.bbox_wgs84 = None
class SosObservationOffering(object): def __init__(self, element): self._root = element self.id = testXMLValue( self._root.find(nspath_eval('swes:identifier', namespaces))) if self.id is None: self.id = testXMLValue( self._root.attrib.get(nspath_eval('swes:id', namespaces)), True) self.description = testXMLValue( self._root.find(nspath_eval('swes:description', namespaces))) self.name = testXMLValue( self._root.find(nspath_eval('swes:name', namespaces))) # sos:observedArea try: envelope = self._root.find( nspath_eval('sos:observedArea/gml32:Envelope', namespaces)) lower_left_corner = testXMLValue( envelope.find(nspath_eval('gml32:lowerCorner', namespaces))).split() upper_right_corner = testXMLValue( envelope.find(nspath_eval('gml32:upperCorner', namespaces))).split() # (left, bottom, right, top) in self.bbox_srs units self.bbox = (float(lower_left_corner[1]), float(lower_left_corner[0]), float(upper_right_corner[1]), float(upper_right_corner[0])) self.bbox_srs = Crs( testXMLValue(envelope.attrib.get('srsName'), True)) except Exception, err: self.bbox = None self.bbox_srs = None # LOOK: Support all gml:TimeGeometricPrimitivePropertyType # Right now we are just supporting gml:TimePeriod # sos:Time begin_position_element = self._root.find( nspath_eval( 'sos:phenomenonTime/gml32:TimePeriod/gml32:beginPosition', namespaces)) self.begin_position = extract_time(begin_position_element) end_position_element = self._root.find( nspath_eval( 'sos:phenomenonTime/gml32:TimePeriod/gml32:endPosition', namespaces)) self.end_position = extract_time(end_position_element) self.procedures = [] for proc in self._root.findall( nspath_eval('swes:procedure', namespaces)): self.procedures.append(testXMLValue(proc)) self.procedure_description_formats = [] for proc in self._root.findall( nspath_eval('swes:procedureDescriptionFormat', namespaces)): self.procedure_description_formats.append(testXMLValue(proc)) # LOOK: Support swe:Phenomenon here # this includes compound properties self.observed_properties = [] for op in self._root.findall( nspath_eval('swes:observableProperty', namespaces)): self.observed_properties.append(testXMLValue(op)) self.features_of_interest = [] for fot in self._root.findall( nspath_eval('sos:featureOfInterest', namespaces)): self.features_of_interest.append( testXMLValue( fot.attrib.get(nspath_eval('xlink:href', namespaces)), True)) self.response_formats = [] for rf in self._root.findall( nspath_eval('sos:responseFormat', namespaces)): self.response_formats.append(testXMLValue(rf)) self.observation_models = [] for om in self._root.findall( nspath_eval('sos:observationType', namespaces)): self.observation_models.append(testXMLValue(om))
def get_remote_featurecatalogue(csw_url, fc_uuid): """Request and parse the remote feature catalogue described by the CSW base url and feature catalogue UUID. Parameters ---------- csw_url : str Base URL of the CSW service to query, should end with 'csw'. fc_uuid : str Universally unique identifier of the feature catalogue. Returns ------- dict Dictionary with fields described in the feature catalogue, using the following schema: >>> {'definition' : 'feature type definition', >>> 'attributes' : {'name': >>> {'definition' : 'attribute definition', >>> 'values' : ['list of', 'values'], >>> 'multiplicity': (lower, upper)} >>> } >>> } Where the lower multiplicity is always and integer and the upper multiplicity is either an integer or the str 'Inf' indicating an infinate value. Raises ------ pydov.util.errors.FeatureCatalogueNotFoundError If there is no feature catalogue with given UUID available in the given CSW service. """ fc_url = csw_url + '?Service=CSW&Request=GetRecordById&Version=2.0.2' \ '&outputSchema=http://www.isotc211.org/2005/gfc' \ '&elementSetName=full&id=' + fc_uuid content = __get_remote_fc(fc_url) tree = etree.fromstring(content) fc = tree.find(nspath_eval('gfc:FC_FeatureCatalogue', __namespaces)) if fc is None: raise FeatureCatalogueNotFoundError r = {} r['definition'] = fc.findtext( nspath_eval( 'gfc:featureType/gfc:FC_FeatureType/gfc:definition/' 'gco:CharacterString', __namespaces)) attributes = {} for a in fc.findall( nspath_eval( 'gfc:featureType/gfc:FC_FeatureType/gfc:carrierOfCharacteristics/' 'gfc:FC_FeatureAttribute', __namespaces)): attr = {} name = a.findtext( nspath_eval('gfc:memberName/gco:LocalName', __namespaces)) attr['definition'] = a.findtext( nspath_eval('gfc:definition/gco:CharacterString', __namespaces)) try: multiplicity_lower = int( a.findtext( nspath_eval( 'gfc:cardinality/gco:Multiplicity/gco:range/gco' ':MultiplicityRange/gco:lower/gco:Integer', __namespaces))) except (TypeError, ValueError): multiplicity_lower = 0 upper = a.find( nspath_eval( 'gfc:cardinality/gco:Multiplicity/gco:range/gco' ':MultiplicityRange/gco:upper/gco:UnlimitedInteger', __namespaces)) try: multiplicity_upper = int(upper.text) except (TypeError, ValueError): multiplicity_upper = None if upper.get('isInfinite', 'false').lower() == 'true': multiplicity_upper = 'Inf' values = {} for lv in a.findall( nspath_eval('gfc:listedValue/gfc:FC_ListedValue', __namespaces)): label = lv.findtext( nspath_eval('gfc:label/gco:CharacterString', __namespaces)) definition = lv.findtext( nspath_eval('gfc:definition/gco:CharacterString', __namespaces)) if label is not None: label = label.strip() if label != '': if definition is not None: values[label] = definition.strip() if \ definition.strip() != '' else None else: values[label] = None attr['values'] = values if len(values) > 0 else None attr['multiplicity'] = (multiplicity_lower, multiplicity_upper) attributes[name] = attr r['attributes'] = attributes return r
def __init__(self, md): val = md.find(util.nspath_eval('dif:Short_Name', namespaces)) self.short_name = util.testXMLValue(val) val = md.find(util.nspath_eval('dif:Long_Name', namespaces)) self.long_name = util.testXMLValue(val)
def get_observation(self, responseFormat=None, offerings=None, observedProperties=None, eventTime=None, method='Get', **kwargs): """ Parameters ---------- format : string Output format. Provide one that is available for all offerings method : string Optional. HTTP DCP method name: Get or Post. Must **kwargs : extra arguments anything else e.g. vendor specific parameters """ base_url = self.get_operation_by_name( 'GetObservation').methods[method]['url'] request = { 'service': 'SOS', 'version': self.version, 'request': 'GetObservation' } # Required Fields assert isinstance(offerings, list) and len(offerings) > 0 request['offering'] = ','.join(offerings) assert isinstance(observedProperties, list) and len(observedProperties) > 0 request['observedProperty'] = ','.join(observedProperties) if responseFormat is not None: request['responseFormat'] = responseFormat # Optional Fields if eventTime is not None: request['temporalFilter'] = eventTime if kwargs: for kw in kwargs: request[kw] = kwargs[kw] data = urlencode(request) response = openURL(base_url, data, method, username=self.username, password=self.password).read() try: tr = etree.fromstring(response) if tr.tag == nspath_eval("ows:ExceptionReport", namespaces): raise ows.ExceptionReport(tr) else: return response except ows.ExceptionReport: raise except BaseException: return response
def _invoke(self): # do HTTP request if isinstance(self.request, basestring): # GET KVP req = Request(self.request) if self.username is not None and self.password is not None: base64string = base64.encodestring('%s:%s' % (self.username, self.password))[:-1] req.add_header('Authorization', 'Basic %s' % base64string) self.response = urlopen(req, timeout=self.timeout).read() else: xml_post_url = self.url # Get correct POST URL based on Operation list. # If skip_caps=True, then self.operations has not been set, so use # default URL. if hasattr(self, 'operations'): caller = inspect.stack()[1][3] if caller == 'getrecords2': caller = 'getrecords' try: op = self.get_operation_by_name(caller) post_verbs = filter(lambda x: x.get('type').lower() == 'post', op.methods) if len(post_verbs) > 1: # Filter by constraints. We must match a PostEncoding of "XML" try: xml_post_url = next(x for x in filter(list, ([pv.get('url') for const in pv.get('constraints') if const.name.lower() == "postencoding" and 'xml' in map(lambda x: x.lower(), const.values)] for pv in post_verbs)))[0] except StopIteration: # Well, just use the first one. xml_post_url = post_verbs[0].get('url') elif len(post_verbs) == 1: xml_post_url = post_verbs[0].get('url') except: # no such luck, just go with xml_post_url pass self.request = cleanup_namespaces(self.request) # Add any namespaces used in the "typeNames" attribute of the # csw:Query element to the query's xml namespaces. for query in self.request.findall(util.nspath_eval('csw:Query', namespaces)): ns = query.get("typeNames", None) if ns is not None: # Pull out "gmd" from something like "gmd:MD_Metadata" from the list # of typenames ns_keys = [x.split(':')[0] for x in ns.split(' ')] self.request = add_namespaces(self.request, ns_keys) self.request = util.element_to_string(self.request, encoding='utf-8') self.response = util.http_post(xml_post_url, self.request, self.lang, self.timeout, self.username, self.password) # parse result see if it's XML self._exml = etree.parse(StringIO.StringIO(self.response)) # it's XML. Attempt to decipher whether the XML response is CSW-ish """ valid_xpaths = [ util.nspath_eval('ows:ExceptionReport', namespaces), util.nspath_eval('csw:Capabilities', namespaces), util.nspath_eval('csw:DescribeRecordResponse', namespaces), util.nspath_eval('csw:GetDomainResponse', namespaces), util.nspath_eval('csw:GetRecordsResponse', namespaces), util.nspath_eval('csw:GetRecordByIdResponse', namespaces), util.nspath_eval('csw:HarvestResponse', namespaces), util.nspath_eval('csw:TransactionResponse', namespaces) ] if self._exml.getroot().tag not in valid_xpaths: raise RuntimeError, 'Document is XML, but not CSW-ish' # check if it's an OGC Exception val = self._exml.find(util.nspath_eval('ows:Exception', namespaces)) if val is not None: raise ows.ExceptionReport(self._exml, self.owscommon.namespace) else: self.exceptionreport = None
def _invoke(self): # do HTTP request request_url = self.url # Get correct URL based on Operation list. # If skip_caps=True, then self.operations has not been set, so use # default URL. if hasattr(self, 'operations'): caller = inspect.stack()[1][3] if caller == 'getrecords2': caller = 'getrecords' try: op = self.get_operation_by_name(caller) if isinstance(self.request, six.string_types): # GET KVP get_verbs = [x for x in op.methods if x.get('type').lower() == 'get'] request_url = get_verbs[0].get('url') else: post_verbs = [x for x in op.methods if x.get('type').lower() == 'post'] if len(post_verbs) > 1: # Filter by constraints. We must match a PostEncoding of "XML" for pv in post_verbs: for const in pv.get('constraints'): if const.name.lower() == 'postencoding': values = [v.lower() for v in const.values] if 'xml' in values: request_url = pv.get('url') break else: # Well, just use the first one. request_url = post_verbs[0].get('url') elif len(post_verbs) == 1: request_post_url = post_verbs[0].get('url') except: # no such luck, just go with request_url pass if isinstance(self.request, six.string_types): # GET KVP self.request = '%s%s' % (bind_url(request_url), self.request) self.response = openURL(self.request, None, 'Get', username=self.username, password=self.password, timeout=self.timeout).read() else: self.request = cleanup_namespaces(self.request) # Add any namespaces used in the "typeNames" attribute of the # csw:Query element to the query's xml namespaces. for query in self.request.findall(util.nspath_eval('csw:Query', namespaces)): ns = query.get("typeNames", None) if ns is not None: # Pull out "gmd" from something like "gmd:MD_Metadata" from the list # of typenames ns_keys = [x.split(':')[0] for x in ns.split(' ')] self.request = add_namespaces(self.request, ns_keys) self.request = util.element_to_string(self.request, encoding='utf-8') self.response = util.http_post(request_url, self.request, self.lang, self.timeout, self.username, self.password) # parse result see if it's XML self._exml = etree.parse(BytesIO(self.response)) # it's XML. Attempt to decipher whether the XML response is CSW-ish """ valid_xpaths = [ util.nspath_eval('ows:ExceptionReport', namespaces), util.nspath_eval('csw:Capabilities', namespaces), util.nspath_eval('csw:DescribeRecordResponse', namespaces), util.nspath_eval('csw:GetDomainResponse', namespaces), util.nspath_eval('csw:GetRecordsResponse', namespaces), util.nspath_eval('csw:GetRecordByIdResponse', namespaces), util.nspath_eval('csw:HarvestResponse', namespaces), util.nspath_eval('csw:TransactionResponse', namespaces) ] if self._exml.getroot().tag not in valid_xpaths: raise RuntimeError('Document is XML, but not CSW-ish') # check if it's an OGC Exception val = self._exml.find(util.nspath_eval('ows:Exception', namespaces)) if val is not None: raise ows.ExceptionReport(self._exml, self.owscommon.namespace) else: self.exceptionreport = None
def __init__(self, elem, parse_remote_metadata=False, timeout=30): """.""" self.id = testXMLValue(elem.find(nspath_eval('wfs:Name', namespaces))) self.title = testXMLValue( elem.find(nspath_eval('wfs:Title', namespaces))) self.abstract = testXMLValue( elem.find(nspath_eval('wfs:Abstract', namespaces))) self.keywords = [ f.text for f in elem.findall( nspath_eval('ows:Keywords/ows:Keyword', namespaces)) ] # bbox self.boundingBoxWGS84 = None b = BoundingBox( elem.find(nspath_eval('ows:WGS84BoundingBox', namespaces)), namespaces['ows']) if b is not None: try: self.boundingBoxWGS84 = ( float(b.minx), float(b.miny), float(b.maxx), float(b.maxy), ) except TypeError: self.boundingBoxWGS84 = None # crs options self.crsOptions = [ Crs(srs.text) for srs in elem.findall(nspath_eval('wfs:OtherSRS', namespaces)) ] dsrs = testXMLValue( elem.find(nspath_eval('wfs:DefaultSRS', namespaces))) if dsrs is not None: # first element is default srs self.crsOptions.insert(0, Crs(dsrs)) # verbs self.verbOptions = [ op.text for op in elem.findall( nspath_eval('wfs:Operations/wfs:Operation', namespaces)) ] # output formats self.outputFormats = [ op.text for op in elem.findall( nspath_eval('wfs:OutputFormats/wfs:Format', namespaces)) ] # MetadataURLs self.metadataUrls = [] for m in elem.findall(nspath_eval('wfs:MetadataURL', namespaces)): metadataUrl = { 'type': testXMLValue(m.attrib['type'], attrib=True), 'format': testXMLValue(m.find('Format')), 'url': testXMLValue(m) } if metadataUrl[ 'url'] is not None and parse_remote_metadata: # download URL try: content = openURL(metadataUrl['url'], timeout=timeout) doc = etree.parse(content) if metadataUrl['type'] is not None: if metadataUrl['type'] == 'FGDC': metadataUrl['metadata'] = Metadata(doc) if metadataUrl['type'] in ['TC211', '19115', '19139']: metadataUrl['metadata'] = MD_Metadata(doc) except Exception: metadataUrl['metadata'] = None self.metadataUrls.append(metadataUrl) #others not used but needed for iContentMetadata harmonisation self.styles = None self.timepositions = None self.defaulttimeposition = None
def __init__(self, url, lang='en-US', version='2.0.2', timeout=10, skip_caps=False): """ Construct and process a GetCapabilities request Parameters ---------- - url: the URL of the CSW - lang: the language (default is 'en-US') - version: version (default is '2.0.2') - timeout: timeout in seconds - skip_caps: whether to skip GetCapabilities processing on init (default is False) """ self.url = url self.lang = lang self.version = version self.timeout = timeout self.service = 'CSW' self.exceptionreport = None self.owscommon = ows.OwsCommon('1.0.0') if not skip_caps: # process GetCapabilities # construct request data = { 'service': self.service, 'version': self.version, 'request': 'GetCapabilities' } self.request = '%s%s' % (bind_url(self.url), urlencode(data)) self._invoke() if self.exceptionreport is None: # ServiceIdentification val = self._exml.find( util.nspath_eval('ows:ServiceIdentification', namespaces)) self.identification = ows.ServiceIdentification( val, self.owscommon.namespace) # ServiceProvider val = self._exml.find( util.nspath_eval('ows:ServiceProvider', namespaces)) self.provider = ows.ServiceProvider(val, self.owscommon.namespace) # ServiceOperations metadata self.operations = [] for elem in self._exml.findall( util.nspath_eval( 'ows:OperationsMetadata/ows:Operation', namespaces)): self.operations.append( ows.OperationsMetadata(elem, self.owscommon.namespace)) # FilterCapabilities val = self._exml.find( util.nspath_eval('ogc:Filter_Capabilities', namespaces)) self.filters = fes.FilterCapabilities(val)