Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
0
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)
Beispiel #4
0
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)
Beispiel #5
0
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
Beispiel #6
0
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
Beispiel #7
0
    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
Beispiel #8
0
    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
Beispiel #9
0
    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
Beispiel #10
0
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
Beispiel #11
0
    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
Beispiel #12
0
    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
Beispiel #13
0
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
Beispiel #14
0
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
Beispiel #15
0
    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
Beispiel #16
0
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
Beispiel #17
0
    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