def setConstraintList(self, constraints, tostring=False): """ Construct and process a GetRecords request Parameters ---------- - constraints: A list of OgcExpression objects The list is interpretted like so: [a,b,c] a || b || c [[a,b,c]] a && b && c [[a,b],[c],[d],[e]] or [[a,b],c,d,e] (a && b) || c || d || e - tostring (optional): return as string """ ors = [] if len(constraints) == 1: if isinstance(constraints[0], OgcExpression): flt = self.setConstraint(constraints[0]) else: self._root.append(And(operations=constraints[0]).toXML()) flt = self._root if tostring: return util.element_to_string(flt, xml_declaration=False) else: return flt for c in constraints: if isinstance(c, OgcExpression): ors.append(c) elif isinstance(c, list) or isinstance(c, tuple): if len(c) == 1: ors.append(c[0]) elif len(c) >= 2: ands = [] for sub in c: if isinstance(sub, OgcExpression): ands.append(sub) ors.append(And(operations=ands)) self._root.append(Or(operations=ors).toXML()) if tostring: return util.element_to_string(self._root, xml_declaration=False) return self._root
def encode_atomxml(obj_d): """ encode instance of OwcContext dict into atom xml encoding, because we can't do circular imports :param obj_d: the dict from owscontext to dict :return: b'atomxml' """ # try: # xml_tree = axml_context(obj_d) # tree = etree.ElementTree(xml_tree) # return tree # except TypeError as te: # log.warning('problem encoding context to xml', te) # raise te # except AttributeError as ae: # log.warning('problem encoding context to xml', ae) # raise ae # except ValueError as ve: # log.warning('problem encoding context to xml', ve) # raise ve # except ParseError as pe: # log.warning('problem encoding context to xml', pe) # raise pe xml_tree = axml_context(obj_d) tree = etree.ElementTree(xml_tree) return element_to_string(tree, encoding='utf-8', xml_declaration=False)
def encode_atomxml(obj_d): """ encode instance of OwcContext dict into atom xml encoding, because we can't do circular imports :param obj_d: the dict from owscontext to dict :return: b'atomxml' """ # try: # xml_tree = axml_context(obj_d) # tree = etree.ElementTree(xml_tree) # return tree # except TypeError as te: # log.warn('problem encoding context to xml', te) # raise te # except AttributeError as ae: # log.warn('problem encoding context to xml', ae) # raise ae # except ValueError as ve: # log.warn('problem encoding context to xml', ve) # raise ve # except ParseError as pe: # log.warn('problem encoding context to xml', pe) # raise pe xml_tree = axml_context(obj_d) tree = etree.ElementTree(xml_tree) return element_to_string(tree, encoding='utf-8', xml_declaration=False)
def parse_owc_content(content_node): mimetype = util.testXMLAttribute(content_node, 'type') url = util.testXMLAttribute(content_node, 'href') title = util.testXMLAttribute(content_node, 'title') child_elem = None if len(list(content_node)) > 0: child_elem = element_to_string(list(content_node)[0], False) content_dict = { "type": mimetype, "url": url, "content": str(child_elem), "title": title } return content_dict
def parse_owc_content(content_node): mimetype = util.testXMLAttribute(content_node, 'type') url = util.testXMLAttribute(content_node, 'href') title = util.testXMLAttribute(content_node, 'title') child_elem = None if len(list(content_node)) > 0: child_elem = element_to_string( list(content_node)[0],False) content_dict = { "type": mimetype, "url": url, "content": str(child_elem), "title": title } return content_dict
def setConstraint(self, constraint, tostring=False): """ Construct and process a GetRecords request Parameters ---------- - constraint: An OgcExpression object - tostring (optional): return as string """ self._root.append(constraint.toXML()) if tostring: return util.element_to_string(self._root, xml_declaration=False) return self._root
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 parse_entry(entry_node): """ parse an aotm entry into a feature/resource dict to build OwcResource from :param entry_node: xml element root node of the atom:entry :return: dictionary for OwcResource.from_dict() """ resource_base_dict = { "type": "Feature", "id": None, "geometry": None, "properties": { 'title': None, 'abstract': None, 'updated': None, 'date': None, 'authors': [], 'publisher': None, 'rights': None, 'categories': [], "links": { "alternates": [], "previews": [], "data": [], "via": [], }, 'offerings': [], 'active': None, 'minscaledenominator': None, 'maxscaledenominator': None, 'folder': None } } # <id>ftp://ftp.remotesensing.org/pub/geotiff/samples/gdal_eg/cea.txt</id> val = entry_node.find(util.nspath_eval('atom:id', ns)) id = util.testXMLValue(val) # log.debug("entry :id %s :: %s", id, val) resource_base_dict.update({"id": id}) # <title>GeoTIFF Example</title> val = entry_node.find(util.nspath_eval('atom:title', ns)) title = util.testXMLValue(val) # log.debug("entry: title %s :: %s", id, val) resource_base_dict['properties'].update({"title": title}) # <updated>2011-11-01T00:00:00Z</updated> val = entry_node.find(util.nspath_eval('atom:updated', ns)) update_date = util.testXMLValue(val) # log.debug("entry: updated %s :: %s", update_date, val) resource_base_dict['properties'].update({"updated": update_date}) # <dc:publisher> val = entry_node.find(util.nspath_eval('dc:publisher', ns)) publisher = util.testXMLValue(val) # log.debug("entry: dc:publisher %s :: %s", publisher, val) resource_base_dict['properties'].update({"publisher": publisher}) # <dc:rights> val = entry_node.find(util.nspath_eval('dc:rights', ns)) rights = util.testXMLValue(val) # log.debug("entry: rights %s :: %s", rights, val) resource_base_dict['properties'].update({"rights": rights}) # <georss:where> val = entry_node.find(util.nspath_eval('georss:where', ns)) if val is not None: if len(list(val)) > 0: # xmltxt = etree.tostring( # list(val)[0], encoding='utf8', method='xml') xmltxt = element_to_string(list(val)[0], False) # TODO here parse geometry?? # log.debug("entry: geometry %s :: %s", xmltxt, val) resource_base_dict.update({"geometry": xmltxt.decode('utf-8')}) # <content type = "text" > aka subtitle, aka abstract val = entry_node.find(util.nspath_eval('atom:content', ns)) subtitle = util.testXMLValue(val) # log.debug("entry: subtitle %s :: %s", subtitle, val) resource_base_dict['properties'].update({"abstract": subtitle}) # <author> .. # <name> # <email> vals = entry_node.findall(util.nspath_eval('atom:author', ns)) authors = [] for val in vals: val_name = val.find(util.nspath_eval('atom:name', ns)) val_email = val.find(util.nspath_eval('atom:email', ns)) val_uri = val.find(util.nspath_eval('atom:uri', ns)) name = util.testXMLValue(val_name) email = util.testXMLValue(val_email) uri = util.testXMLValue(val_uri) author = {"name": name, "email": email, "uri": uri} # log.debug("entry: author %s :: %s", author, vals) if not is_empty(author): authors.append(author) resource_base_dict['properties'].update({"authors": authors}) # <link rel="enclosure" type="image/png" # length="12345" title="..." href="http://o..."/> # <link rel="icon" type="image/png" title="Preview f..." # href="http://..."/> # <link rel="via" type="application/vnd.ogc.wms_xml" # title="Original .." href="...."/> vals = entry_node.findall(util.nspath_eval('atom:link', ns)) links_alternates = [] links_previews = [] links_data = [] links_via = [] for val in vals: rel = util.testXMLAttribute(val, 'rel') href = util.testXMLAttribute(val, 'href') mimetype = util.testXMLAttribute(val, 'type') lang = util.testXMLAttribute(val, 'lang') title = util.testXMLAttribute(val, 'title') length = util.testXMLAttribute(val, 'length') link = { "href": href, "type": mimetype, "length": length, "lang": lang, "title": title, "rel": rel } # log.debug("entry: link %s :: %s", link, vals) if link.get("rel") == "alternate" and not is_empty(link): links_alternates.append(link) elif link.get("rel") == "icon" and not is_empty(link): links_previews.append(link) elif link.get("rel") == "enclosure" and not is_empty(link): links_data.append(link) elif link.get("rel") == "via" and not is_empty(link): links_via.append(link) else: log.warning("unknown link type in Ows Resource entry section: %r", link) resource_base_dict['properties']['links'].update( {"alternates": links_alternates}) resource_base_dict['properties']['links'].update( {"previews": links_previews}) resource_base_dict['properties']['links'].update({"data": links_data}) resource_base_dict['properties']['links'].update({"via": links_via}) # <owc:offering code="http://www.opengis.net/spec/owc-at..."> # <owc:content type="image/tiff" href=".." # <owc:offering code="http://www.opengis.net/spec....l"> # <owc:content type="application/gml+xml"> # <owc:operation code="GetCapabilities" method="GET" # type="applica..." href="..." # <owc:request type="application/xml"> .. # <owc:styleSet> # <owc:name>raster</owc:name> # <owc:title>Default Raster</owc:title> # <owc:abstract>A sample style that draws a </owc:abstract> # <owc:legendURL href="h...." type="image/png"/> # </owc:styleSet> offering_nodes = entry_node.findall(util.nspath_eval('owc:offering', ns)) offerings = [] for offering_node in offering_nodes: offering_code = util.testXMLAttribute(offering_node, 'code') operations = [] contents = [] styles = [] operation_nodes = offering_node.findall( util.nspath_eval('owc:operation', ns)) for op_val in operation_nodes: operations_code = util.testXMLAttribute(op_val, 'code') http_method = util.testXMLAttribute(op_val, 'method') mimetype = util.testXMLAttribute(op_val, 'type') request_url = util.testXMLAttribute(op_val, 'href') req_content_val = val.find(util.nspath_eval('owc:request', ns)) req_content = None if req_content_val is not None: req_content = parse_owc_content(req_content_val) # TODO no example for result/response op_dict = { "code": operations_code, "method": http_method, "type": mimetype, "href": request_url, "request": None if is_empty(req_content) else req_content, "result": None } # log.debug("entry: operation %s :: %s", op_dict, vals) if not is_empty(op_dict): operations.append(op_dict) content_nodes = offering_node.findall( util.nspath_eval('owc:content', ns)) for cont_val in content_nodes: content_dict = parse_owc_content(cont_val) # log.debug("entry: content_dict %s :: %s", content_dict, vals) if not is_empty(content_dict): contents.append(content_dict) style_nodes = offering_node.findall( util.nspath_eval('owc:styleSet', ns)) for style_val in style_nodes: val_name = style_val.find(util.nspath_eval('owc:name', ns)) val_title = style_val.find(util.nspath_eval('owc:title', ns)) val_abstr = style_val.find(util.nspath_eval('owc:abstract', ns)) val_uri = style_val.find(util.nspath_eval('owc:legendURL', ns)) name = util.testXMLValue(val_name) title = util.testXMLValue(val_title) abstr = util.testXMLValue(val_abstr) legend_url = util.testXMLAttribute(val_uri, 'href') style_set = { "name": name, "title": title, "abstract": abstr, "default": None, "legendURL": legend_url, "content": None } # log.debug("entry: style_set %s :: %s", style_set, vals) if not is_empty(style_set): styles.append(style_set) offering_dict = { "code": offering_code, "operations": operations, "contents": contents, "styles": styles } if offering_code is not None: offerings.append(offering_dict) resource_base_dict['properties'].update({"offerings": offerings}) # TODO no examples for active attribute # <owc:minScaleDenominator>2500</owc:minScaleDenominator> val = entry_node.find(util.nspath_eval('owc:minScaleDenominator', ns)) min_scale_denominator = util.testXMLValue(val) # log.debug("entry: min-scale-... %s :: %s", min_scale_denominator, val) resource_base_dict['properties'].update( {"minscaledenominator": min_scale_denominator}) # <owc:maxScaleDenominator>25000</owc:maxScaleDenominator> val = entry_node.find(util.nspath_eval('owc:maxScaleDenominator', ns)) max_scale_denominator = util.testXMLValue(val) # log.debug("entry: max_scale_... %s :: %s", max_scale_denominator, val) resource_base_dict['properties'].update( {"maxscaledenominator": max_scale_denominator}) # TODO no examples for folder attribute return resource_base_dict
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') #Modified by Ross Thompson for use with FGP #self.response = util.http_post(xml_post_url, self.request, self.lang, self.timeout, self.username, self.password) self.response = util.http_post(self.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_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 parse_entry(entry_node): """ parse an aotm entry into a feature/resource dict to build OwcResource from :param entry_node: xml element root node of the atom:entry :return: dictionary for OwcResource.from_dict() """ resource_base_dict = { "type": "Feature", "id": None, "geometry": None, "properties": { 'title': None, 'abstract': None, 'updated': None, 'date': None, 'authors': [], 'publisher': None, 'rights': None, 'categories': [], "links": { "alternates": [], "previews": [], "data": [], "via": [], }, 'offerings': [], 'active': None, 'minscaledenominator': None, 'maxscaledenominator': None, 'folder': None } } # <id>ftp://ftp.remotesensing.org/pub/geotiff/samples/gdal_eg/cea.txt</id> val = entry_node.find(util.nspath_eval('atom:id', ns)) id = util.testXMLValue(val) # log.debug("entry :id %s :: %s", id, val) resource_base_dict.update({"id": id}) # <title>GeoTIFF Example</title> val = entry_node.find(util.nspath_eval('atom:title', ns)) title = util.testXMLValue(val) # log.debug("entry: title %s :: %s", id, val) resource_base_dict['properties'].update({"title": title}) # <updated>2011-11-01T00:00:00Z</updated> val = entry_node.find(util.nspath_eval('atom:updated', ns)) update_date = util.testXMLValue(val) # log.debug("entry: updated %s :: %s", update_date, val) resource_base_dict['properties'].update({"updated": update_date}) # <dc:publisher> val = entry_node.find(util.nspath_eval('dc:publisher', ns)) publisher = util.testXMLValue(val) # log.debug("entry: dc:publisher %s :: %s", publisher, val) resource_base_dict['properties'].update({"publisher": publisher}) # <dc:rights> val = entry_node.find(util.nspath_eval('dc:rights', ns)) rights = util.testXMLValue(val) # log.debug("entry: rights %s :: %s", rights, val) resource_base_dict['properties'].update({"rights": rights}) # <georss:where> val = entry_node.find(util.nspath_eval('georss:where', ns)) if val is not None: if len(list(val)) > 0: # xmltxt = etree.tostring( # list(val)[0], encoding='utf8', method='xml') xmltxt = element_to_string( list(val)[0], False) # TODO here parse geometry?? # log.debug("entry: geometry %s :: %s", xmltxt, val) resource_base_dict.update({"geometry": xmltxt.decode('utf-8')}) # <content type = "text" > aka subtitle, aka abstract val = entry_node.find(util.nspath_eval('atom:content', ns)) subtitle = util.testXMLValue(val) # log.debug("entry: subtitle %s :: %s", subtitle, val) resource_base_dict['properties'].update({"abstract": subtitle}) # <author> .. # <name> # <email> vals = entry_node.findall(util.nspath_eval('atom:author', ns)) authors = [] for val in vals: val_name = val.find(util.nspath_eval('atom:name', ns)) val_email = val.find(util.nspath_eval('atom:email', ns)) val_uri = val.find(util.nspath_eval('atom:uri', ns)) name = util.testXMLValue(val_name) email = util.testXMLValue(val_email) uri = util.testXMLValue(val_uri) author = { "name": name, "email": email, "uri": uri } # log.debug("entry: author %s :: %s", author, vals) if not is_empty(author): authors.append(author) resource_base_dict['properties'].update({"authors": authors}) # <link rel="enclosure" type="image/png" # length="12345" title="..." href="http://o..."/> # <link rel="icon" type="image/png" title="Preview f..." # href="http://..."/> # <link rel="via" type="application/vnd.ogc.wms_xml" # title="Original .." href="...."/> vals = entry_node.findall(util.nspath_eval('atom:link', ns)) links_alternates = [] links_previews = [] links_data = [] links_via = [] for val in vals: rel = util.testXMLAttribute(val, 'rel') href = util.testXMLAttribute(val, 'href') mimetype = util.testXMLAttribute(val, 'type') lang = util.testXMLAttribute(val, 'lang') title = util.testXMLAttribute(val, 'title') length = util.testXMLAttribute(val, 'length') link = { "href": href, "type": mimetype, "length": length, "lang": lang, "title": title, "rel": rel } # log.debug("entry: link %s :: %s", link, vals) if link.get("rel") == "alternate" and not is_empty(link): links_alternates.append(link) elif link.get("rel") == "icon" and not is_empty(link): links_previews.append(link) elif link.get("rel") == "enclosure" and not is_empty(link): links_data.append(link) elif link.get("rel") == "via" and not is_empty(link): links_via.append(link) else: log.warn( "unknown link type in Ows Resource entry section: %r", link) resource_base_dict['properties']['links'].update( {"alternates": links_alternates}) resource_base_dict['properties']['links'].update( {"previews": links_previews}) resource_base_dict['properties']['links'].update({"data": links_data}) resource_base_dict['properties']['links'].update({"via": links_via}) # <owc:offering code="http://www.opengis.net/spec/owc-at..."> # <owc:content type="image/tiff" href=".." # <owc:offering code="http://www.opengis.net/spec....l"> # <owc:content type="application/gml+xml"> # <owc:operation code="GetCapabilities" method="GET" # type="applica..." href="..." # <owc:request type="application/xml"> .. # <owc:styleSet> # <owc:name>raster</owc:name> # <owc:title>Default Raster</owc:title> # <owc:abstract>A sample style that draws a </owc:abstract> # <owc:legendURL href="h...." type="image/png"/> # </owc:styleSet> offering_nodes = entry_node.findall(util.nspath_eval('owc:offering', ns)) offerings = [] for offering_node in offering_nodes: offering_code = util.testXMLAttribute(offering_node, 'code') operations = [] contents = [] styles = [] operation_nodes = offering_node.findall( util.nspath_eval('owc:operation', ns)) for op_val in operation_nodes: operations_code = util.testXMLAttribute(op_val, 'code') http_method = util.testXMLAttribute(op_val, 'method') mimetype = util.testXMLAttribute(op_val, 'type') request_url = util.testXMLAttribute(op_val, 'href') req_content_val = val.find(util.nspath_eval('owc:request', ns)) req_content = None if req_content_val is not None: request_content = parse_owc_content(req_content_val) # TODO no example for result/response op_dict = { "code": operations_code, "method": http_method, "type": mimetype, "href": request_url, "request": None if is_empty(req_content) else req_content, "result": None } # log.debug("entry: operation %s :: %s", op_dict, vals) if not is_empty(op_dict): operations.append(op_dict) content_nodes = offering_node.findall( util.nspath_eval('owc:content', ns)) for cont_val in content_nodes: content_dict = parse_owc_content(cont_val) # log.debug("entry: content_dict %s :: %s", content_dict, vals) if not is_empty(content_dict): contents.append(content_dict) style_nodes = offering_node.findall( util.nspath_eval('owc:styleSet', ns)) for style_val in style_nodes: val_name = style_val.find(util.nspath_eval('owc:name', ns)) val_title = style_val.find(util.nspath_eval('owc:title', ns)) val_abstr = style_val.find(util.nspath_eval('owc:abstract', ns)) val_uri = style_val.find(util.nspath_eval('owc:legendURL', ns)) name = util.testXMLValue(val_name) title = util.testXMLValue(val_title) abstr = util.testXMLValue(val_abstr) legend_url = util.testXMLAttribute(val_uri, 'href') style_set = { "name": name, "title": title, "abstract": abstr, "default": None, "legendURL": legend_url, "content": None } # log.debug("entry: style_set %s :: %s", style_set, vals) if not is_empty(style_set): styles.append(style_set) offering_dict = { "code": offering_code, "operations": operations, "contents": contents, "styles": styles } if offering_code is not None: offerings.append(offering_dict) resource_base_dict['properties'].update( {"offerings": offerings}) # TODO no examples for active attribute # <owc:minScaleDenominator>2500</owc:minScaleDenominator> val = entry_node.find(util.nspath_eval('owc:minScaleDenominator', ns)) min_scale_denominator = util.testXMLValue(val) # log.debug("entry: min-scale-... %s :: %s", min_scale_denominator, val) resource_base_dict['properties'].update( {"minscaledenominator": min_scale_denominator}) # <owc:maxScaleDenominator>25000</owc:maxScaleDenominator> val = entry_node.find(util.nspath_eval('owc:maxScaleDenominator', ns)) max_scale_denominator = util.testXMLValue(val) # log.debug("entry: max_scale_... %s :: %s", max_scale_denominator, val) resource_base_dict['properties'].update( {"maxscaledenominator": max_scale_denominator}) # TODO no examples for folder attribute return resource_base_dict
def decode_atomxml(xml_string): """ here parse atom xml to a dict for instanciating of OWC:Context :param xmlstring: :return: OwcContext-ready dict """ context_base_dict = { "type": "FeatureCollection", "id": None, "bbox": None, "properties": { "lang": None, "links": { "profiles": [], "via": [], }, 'title': None, 'abstract': None, 'updated': None, 'authors': [], 'publisher': None, 'generator': None, 'display': None, 'rights': None, 'date': None, 'categories': [], }, 'features': [] } feed_root = etree.fromstring(xml_string) # feed_root = etree.parse(xml_bytes) # feed_root xml lang use? # # log.debug(feed_root) # feed xml:lang=en # lang = feed_root.get('{http://www.w3.org/XML/1998/namespace}lang') lang = util.testXMLAttribute( feed_root, '{http://www.w3.org/XML/1998/namespace}lang') # log.debug("lang %s ", lang) context_base_dict['properties'].update({"lang": lang}) # <id> val = feed_root.find(util.nspath_eval('atom:id', ns)) id = util.testXMLValue(val) # log.debug("id %s :: %s", id, val) context_base_dict.update({"id": id}) # <link rel="profile" # href="http://www.opengis.net/spec/owc-atom/1.0/req/core" # title="compliant bla bla" # < link rel = "via" type = "application/xml" href = "..." title = "..." vals = feed_root.findall(util.nspath_eval('atom:link', ns)) links_profile = [] links_via = [] for val in vals: rel = util.testXMLAttribute(val, 'rel') href = util.testXMLAttribute(val, 'href') mimetype = util.testXMLAttribute(val, 'type') lang = util.testXMLAttribute(val, 'lang') title = util.testXMLAttribute(val, 'title') length = util.testXMLAttribute(val, 'length') link = { "href": href, "type": mimetype, "length": length, "lang": lang, "title": title, "rel": rel } # log.debug("link %s :: %s", link, vals) if link.get("rel") == "profile" and not is_empty(link): links_profile.append(link) elif link.get("rel") == "via" and not is_empty(link): links_via.append(link) else: log.warn("unknown link type in Ows Context section: %r", link) context_base_dict['properties']['links'].update( {"profiles": links_profile}) context_base_dict['properties']['links'].update({"via": links_via}) # <title> val = feed_root.find(util.nspath_eval('atom:title', ns)) title = util.testXMLValue(val) # log.debug("title %s :: %s", title, val) context_base_dict['properties'].update({"title": title}) # <subtitle type = "html" val = feed_root.find(util.nspath_eval('atom:subtitle', ns)) subtitle = util.testXMLValue(val) # log.debug("subtitle %s :: %s", subtitle, val) context_base_dict['properties'].update({"abstract": subtitle}) # <author> .. # <name> # <email> vals = feed_root.findall(util.nspath_eval('atom:author', ns)) authors = [] for val in vals: val_name = val.find(util.nspath_eval('atom:name', ns)) val_email = val.find(util.nspath_eval('atom:email', ns)) val_uri = val.find(util.nspath_eval('atom:uri', ns)) name = util.testXMLValue(val_name) email = util.testXMLValue(val_email) uri = util.testXMLValue(val_uri) author = { "name": name, "email": email, "uri": uri } # log.debug("author %s :: %s", author, vals) if not is_empty(author): authors.append(author) context_base_dict['properties'].update({"authors": authors}) # <georss:where> val = feed_root.find(util.nspath_eval('georss:where', ns)) if val is not None: if len(list(val)) > 0: xmltxt = element_to_string( list(val)[0], False) # log.debug("geometry %s :: %s", xmltxt, val) context_base_dict['properties'].update({"bbox": xmltxt.decode('utf-8')}) # <updated>2012-11-04T17:26:23Z</updated> val = feed_root.find(util.nspath_eval('atom:updated', ns)) update_date = util.testXMLValue(val) # log.debug("updated %s :: %s", update_date, val) context_base_dict['properties'].update({"updated": update_date}) # <dc:date>2009-01-23T09:08:56.000Z/2009-01-23T09:14:08.000Z</dc:date> val = feed_root.find(util.nspath_eval('dc:date', ns)) time_interval_of_interest = util.testXMLValue(val) # log.debug("dc:date %s :: %s", time_interval_of_interest, val) context_base_dict['properties'].update( {"date": time_interval_of_interest}) # <rights> val = feed_root.find(util.nspath_eval('atom:rights', ns)) rights = util.testXMLValue(val) # log.debug("rights %s :: %s", rights, val) context_base_dict['properties'].update({"rights": rights}) # <dc:publisher> val = feed_root.find(util.nspath_eval('dc:publisher', ns)) publisher = util.testXMLValue(val) # log.debug("dc:publisher %s :: %s", publisher, val) context_base_dict['properties'].update({"publisher": publisher}) # <owc:display> # <owc:pixelWidth> val_display = feed_root.find(util.nspath_eval('owc:display', ns)) val_pixel_width = None if val_display is None \ else val_display.find(util.nspath_eval('owc:pixelWidth', ns)) val_pixel_height = None if val_display is None \ else val_display.find(util.nspath_eval('owc:pixelHeight', ns)) val_mm_per_pixel = None if val_display is None \ else val_display.find(util.nspath_eval('owc:mmPerPixel', ns)) pixel_width = util.testXMLValue(val_pixel_width) pixel_height = util.testXMLValue(val_pixel_height) mm_per_pixel = util.testXMLValue(val_mm_per_pixel) owc_display = { "pixelWidth": pixel_width, "pixelHeight": pixel_height, "mmPerPixel": mm_per_pixel } # log.debug("display %s :: %s", owc_display, val_display) if not is_empty(owc_display): context_base_dict['properties'].update({"display": owc_display}) # <generator uri="http://w.." version="1.0">MiraMon</generator> val = feed_root.find(util.nspath_eval('atom:generator', ns)) name = util.testXMLValue(val) version = util.testXMLAttribute(val, 'version') uri = util.testXMLAttribute(val, 'uri') owc_generator = { "name": name, "version": version, "uri": uri } # log.debug("generator %s :: %s", owc_generator, val) if not is_empty(owc_generator): context_base_dict['properties'].update({"generator": owc_generator}) # <category term="maps" label="This file contains maps"/> vals = feed_root.findall(util.nspath_eval('atom:category', ns)) categories = [] for val in vals: term = util.testXMLAttribute(val, 'term') scheme = util.testXMLAttribute(val, 'scheme') label = util.testXMLAttribute(val, 'label') category = { "term": term, "scheme": scheme, "label": label } # log.debug("category %s :: %s", category, vals) if not is_empty(category): categories.append(category) context_base_dict['properties'].update({"categories": categories}) # <entry> ... entries = feed_root.findall(util.nspath_eval('atom:entry', ns)) resources = [] for entry in entries: entry_dict = parse_entry(entry) if entry_dict.get("id") is not None: resources.append(entry_dict) else: log.warn("feature entry has no id, not allowed: skipping!") context_base_dict.update({"features": resources}) return context_base_dict
def _invoke(self): # do HTTP request if isinstance(self.request, basestring): # GET KVP self.response = urlopen(self.request, 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'): for op in self.operations: 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') 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) # 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 decode_atomxml(xml_string): """ here parse atom xml to a dict for instanciating of OWC:Context :param xmlstring: :return: OwcContext-ready dict """ context_base_dict = { "type": "FeatureCollection", "id": None, "bbox": None, "properties": { "lang": None, "links": { "profiles": [], "via": [], }, 'title': None, 'abstract': None, 'updated': None, 'authors': [], 'publisher': None, 'generator': None, 'display': None, 'rights': None, 'date': None, 'categories': [], }, 'features': [] } feed_root = etree.fromstring(xml_string) # feed_root = etree.parse(xml_bytes) # feed_root xml lang use? # # log.debug(feed_root) # feed xml:lang=en # lang = feed_root.get('{http://www.w3.org/XML/1998/namespace}lang') lang = util.testXMLAttribute(feed_root, '{http://www.w3.org/XML/1998/namespace}lang') # log.debug("lang %s ", lang) context_base_dict['properties'].update({"lang": lang}) # <id> val = feed_root.find(util.nspath_eval('atom:id', ns)) id = util.testXMLValue(val) # log.debug("id %s :: %s", id, val) context_base_dict.update({"id": id}) # <link rel="profile" # href="http://www.opengis.net/spec/owc-atom/1.0/req/core" # title="compliant bla bla" # < link rel = "via" type = "application/xml" href = "..." title = "..." vals = feed_root.findall(util.nspath_eval('atom:link', ns)) links_profile = [] links_via = [] for val in vals: rel = util.testXMLAttribute(val, 'rel') href = util.testXMLAttribute(val, 'href') mimetype = util.testXMLAttribute(val, 'type') lang = util.testXMLAttribute(val, 'lang') title = util.testXMLAttribute(val, 'title') length = util.testXMLAttribute(val, 'length') link = { "href": href, "type": mimetype, "length": length, "lang": lang, "title": title, "rel": rel } # log.debug("link %s :: %s", link, vals) if link.get("rel") == "profile" and not is_empty(link): links_profile.append(link) elif link.get("rel") == "via" and not is_empty(link): links_via.append(link) else: log.warning("unknown link type in Ows Context section: %r", link) context_base_dict['properties']['links'].update( {"profiles": links_profile}) context_base_dict['properties']['links'].update({"via": links_via}) # <title> val = feed_root.find(util.nspath_eval('atom:title', ns)) title = util.testXMLValue(val) # log.debug("title %s :: %s", title, val) context_base_dict['properties'].update({"title": title}) # <subtitle type = "html" val = feed_root.find(util.nspath_eval('atom:subtitle', ns)) subtitle = util.testXMLValue(val) # log.debug("subtitle %s :: %s", subtitle, val) context_base_dict['properties'].update({"abstract": subtitle}) # <author> .. # <name> # <email> vals = feed_root.findall(util.nspath_eval('atom:author', ns)) authors = [] for val in vals: val_name = val.find(util.nspath_eval('atom:name', ns)) val_email = val.find(util.nspath_eval('atom:email', ns)) val_uri = val.find(util.nspath_eval('atom:uri', ns)) name = util.testXMLValue(val_name) email = util.testXMLValue(val_email) uri = util.testXMLValue(val_uri) author = {"name": name, "email": email, "uri": uri} # log.debug("author %s :: %s", author, vals) if not is_empty(author): authors.append(author) context_base_dict['properties'].update({"authors": authors}) # <georss:where> val = feed_root.find(util.nspath_eval('georss:where', ns)) if val is not None: if len(list(val)) > 0: xmltxt = element_to_string(list(val)[0], False) # log.debug("geometry %s :: %s", xmltxt, val) context_base_dict['properties'].update( {"bbox": xmltxt.decode('utf-8')}) # <updated>2012-11-04T17:26:23Z</updated> val = feed_root.find(util.nspath_eval('atom:updated', ns)) update_date = util.testXMLValue(val) # log.debug("updated %s :: %s", update_date, val) context_base_dict['properties'].update({"updated": update_date}) # <dc:date>2009-01-23T09:08:56.000Z/2009-01-23T09:14:08.000Z</dc:date> val = feed_root.find(util.nspath_eval('dc:date', ns)) time_interval_of_interest = util.testXMLValue(val) # log.debug("dc:date %s :: %s", time_interval_of_interest, val) context_base_dict['properties'].update({"date": time_interval_of_interest}) # <rights> val = feed_root.find(util.nspath_eval('atom:rights', ns)) rights = util.testXMLValue(val) # log.debug("rights %s :: %s", rights, val) context_base_dict['properties'].update({"rights": rights}) # <dc:publisher> val = feed_root.find(util.nspath_eval('dc:publisher', ns)) publisher = util.testXMLValue(val) # log.debug("dc:publisher %s :: %s", publisher, val) context_base_dict['properties'].update({"publisher": publisher}) # <owc:display> # <owc:pixelWidth> val_display = feed_root.find(util.nspath_eval('owc:display', ns)) val_pixel_width = None if val_display is None \ else val_display.find(util.nspath_eval('owc:pixelWidth', ns)) val_pixel_height = None if val_display is None \ else val_display.find(util.nspath_eval('owc:pixelHeight', ns)) val_mm_per_pixel = None if val_display is None \ else val_display.find(util.nspath_eval('owc:mmPerPixel', ns)) pixel_width = util.testXMLValue(val_pixel_width) pixel_height = util.testXMLValue(val_pixel_height) mm_per_pixel = util.testXMLValue(val_mm_per_pixel) owc_display = { "pixelWidth": pixel_width, "pixelHeight": pixel_height, "mmPerPixel": mm_per_pixel } # log.debug("display %s :: %s", owc_display, val_display) if not is_empty(owc_display): context_base_dict['properties'].update({"display": owc_display}) # <generator uri="http://w.." version="1.0">MiraMon</generator> val = feed_root.find(util.nspath_eval('atom:generator', ns)) name = util.testXMLValue(val) version = util.testXMLAttribute(val, 'version') uri = util.testXMLAttribute(val, 'uri') owc_generator = {"name": name, "version": version, "uri": uri} # log.debug("generator %s :: %s", owc_generator, val) if not is_empty(owc_generator): context_base_dict['properties'].update({"generator": owc_generator}) # <category term="maps" label="This file contains maps"/> vals = feed_root.findall(util.nspath_eval('atom:category', ns)) categories = [] for val in vals: term = util.testXMLAttribute(val, 'term') scheme = util.testXMLAttribute(val, 'scheme') label = util.testXMLAttribute(val, 'label') category = {"term": term, "scheme": scheme, "label": label} # log.debug("category %s :: %s", category, vals) if not is_empty(category): categories.append(category) context_base_dict['properties'].update({"categories": categories}) # <entry> ... entries = feed_root.findall(util.nspath_eval('atom:entry', ns)) resources = [] for entry in entries: entry_dict = parse_entry(entry) if entry_dict.get("id") is not None: resources.append(entry_dict) else: log.warning("feature entry has no id, not allowed: skipping!") context_base_dict.update({"features": resources}) return context_base_dict
def _invoke(self, mock_requests_post, mock_requests_request): try: if self.auth.token is not None: self.auth.username = "******" self.auth.password = self.auth.token except AttributeError: pass # 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" # noinspection PyBroadException try: op = self.get_operation_by_name(caller) if isinstance(self.request, str): # 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_url = post_verbs[0].get("url") except Exception: # nosec # no such luck, just go with request_url pass # print("Echo") if isinstance(self.request, str): # GET KVP # print("Foxtrot") self.request = "%s%s" % (bind_url(request_url), self.request) self.response = openURL(self.request, None, "Get", timeout=self.timeout, auth=self.auth).read() # debug # print("invoke") # print(self.response[0:100]) else: # print("Golf") 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. # noinspection PyUnresolvedReferences for query in self.request.findall( util.nspath_eval("csw:Query", csw_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 = add_namespaces(self.request, "ows") self.request = util.element_to_string(self.request, encoding="utf-8") # print("Hotel") self.response = http_post(request_url, self.request, self.lang, self.timeout, auth=self.auth) # debug # print("invoke 2") # print(self.response[0:100]) # debug # print("parse") # print(self.response[0:100]) # print(self.response) # 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", csw_namespaces), util.nspath_eval("csw:Capabilities", csw_namespaces), util.nspath_eval("csw:DescribeRecordResponse", csw_namespaces), util.nspath_eval("csw:GetDomainResponse", csw_namespaces), util.nspath_eval("csw:GetRecordsResponse", csw_namespaces), util.nspath_eval("csw:GetRecordByIdResponse", csw_namespaces), util.nspath_eval("csw:HarvestResponse", csw_namespaces), util.nspath_eval("csw:TransactionResponse", csw_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", csw_namespaces)) if val is not None: raise ows.ExceptionReport(self._exml, self.owscommon.namespace) else: self.exceptionreport = None