コード例 #1
0
    def get_exception_report(self):
        """ Creates an OWSExceptionReport from a given Exception object

        Returns:
             report (str): The exception report as string
        """
        root = Element(
            "{}ExceptionReport".format(self.ows_ns),
            nsmap=self.namespace_map,
            attrib={
                "{}schemaLocation".format(self.xsi_ns):
                "http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd",
                "version": "1.2.0",
            })
        exception_elem = xml_helper.create_subelement(
            root,
            "{}Exception".format(self.ows_ns),
            attrib={
                "exceptionCode": self.exception.__class__.__name__,
                "locator": self.locator,
            })
        text_elem = xml_helper.create_subelement(
            exception_elem, "{}ExceptionText".format(self.ows_ns))
        text_elem.text = self.text

        return xml_helper.xml_to_string(root, pretty_print=True)
コード例 #2
0
ファイル: request_resolver.py プロジェクト: terrestris/mrmap
    def _create_parameter_elem(self, parameters: dict, upper_elem: Element):
        """ Creates <ows:Parameter> element and adds it to an upper element

        Returns:

        """
        for param_key, param_val in parameters.items():
            param_elem = xml_helper.create_subelement(upper_elem, "{}Parameter".format(self.ows_ns), attrib={
                "name": param_key
            })
            for val in param_val:
                xml_helper.create_subelement(param_elem, "{}Value".format(self.ows_ns)).text = val
コード例 #3
0
ファイル: request_resolver.py プロジェクト: terrestris/mrmap
    def _create_constraint_elem(self, constraints: dict, upper_elem: Element):
        """ Creates <ows:Constraint> element and adds it to an upper element

        Returns:

        """
        for cons_key, cons_val in constraints.items():
            cons_elem = xml_helper.create_subelement(upper_elem, "{}Constraint".format(self.ows_ns), attrib={
                "name": cons_key
            })
            for val in cons_val:
                xml_helper.create_subelement(cons_elem, "{}Value".format(self.ows_ns)).text = val
コード例 #4
0
    def _generate_request_POST_body(self,
                                    start_position: int,
                                    result_type: str = "results"):
        """ Creates a CSW POST body xml document for GetRecords

        Args:
            start_position (int): The start position for the request
        Returns:
             xml (str): The GetRecords xml document
        """
        namespaces = {
            "csw":
            "http://www.opengis.net/cat/csw/2.0.2",
            "apiso":
            "http://www.opengis.net/cat/csw/apiso/1.0",
            "ogc":
            "http://www.opengis.net/ogc",
            "gmd":
            "http://www.isotc211.org/2005/gmd",
            "ows":
            "http://www.opengis.net/ows",
            "xsd":
            "http://www.w3.org/2001/XMLSchema",
            "xsi":
            "http://www.w3.org/2001/XMLSchema",
            "dc":
            "http://purl.org/dc/elements/1.1/",
            "dct":
            "http://purl.org/dc/terms/",
            "schemaLocation":
            "http://www.opengis.net/cat/csw/{}".format(self.version),
            None:
            "http://www.opengis.net/cat/csw/{}".format(self.version),
        }
        csw_ns = "{" + namespaces["csw"] + "}"

        root_elem = Element(
            "{}{}".format(csw_ns, OGCOperationEnum.GET_RECORDS.value),
            attrib={
                "version": self.version,
                "service": "CSW",
                "resultType": result_type,
                "outputFormat": self.output_format,
                "startPosition": str(start_position),
                "maxRecords": str(self.max_records_per_request),
                "outputSchema": HARVEST_GET_REQUEST_OUTPUT_SCHEMA,
                #"{}schemaLocation".format(xsi_ns): "http://www.opengis.net/cat/csw/2.0.2",
            },
            nsmap=namespaces)
        xml_helper.create_subelement(root_elem, "{}Query".format(csw_ns), None,
                                     {"typeNames": "gmd:MD_Metadata"})
        post_content = xml_helper.xml_to_string(root_elem)
        return post_content
コード例 #5
0
def _overwrite_capabilities_data(xml_obj: _Element, metadata: Metadata):
    """ Overwrites capabilities document data with changed data from editor based changes.

    Only capable of changing <Title>, <Abstract> and <AccessConstraints>

    Args:
        xml_obj (_Element): The document xml object
        metadata (Metadata): The metadata holding the data
    Returns:

    """
    # Create licence appendix for AccessConstraints and Fees
    licence = metadata.licence
    licence_appendix = ""
    if licence is not None:
        licence_appendix = "\n {} ({}), \n {}, \n {}".format(
            licence.name, licence.identifier, licence.description,
            licence.description_url)
    elements = {
        "Title":
        metadata.title,
        "Abstract":
        metadata.abstract,
        "AccessConstraints":
        "{}{}".format(metadata.access_constraints, licence_appendix),
        "Fees":
        "{}{}".format(metadata.fees, licence_appendix),
    }

    for key, val in elements.items():
        try:
            # Check if element exists to change it
            key_xml_obj = xml_helper.try_get_single_element_from_xml(
                "./" + GENERIC_NAMESPACE_TEMPLATE.format(key), xml_obj)
            if key_xml_obj is not None:
                # Element exists, we can change it easily
                xml_helper.write_text_to_element(
                    xml_obj, "./" + GENERIC_NAMESPACE_TEMPLATE.format(key),
                    val)
            else:
                # The element does not exist (happens in case of abstract sometimes)
                # First create, than change it
                xml_helper.create_subelement(
                    xml_obj,
                    key,
                )
                xml_helper.write_text_to_element(
                    xml_obj, "./" + GENERIC_NAMESPACE_TEMPLATE.format(key),
                    val)
        except AttributeError as e:
            # for not is_root this will fail in AccessConstraints querying
            pass
コード例 #6
0
ファイル: request_resolver.py プロジェクト: terrestris/mrmap
    def _create_csw_filter_capabilities(self, root: Element):
        """ Creates the <ogc:Filter_Capabilities> element

        Returns:

        """
        elem = xml_helper.create_subelement(
            root,
            "{}Filter_Capabilities".format(self.ogc_ns)
        )
        filter_capabilities = CSW_CAPABILITIES_CONF.get("filter_capabilities", {})

        for cap_key, cap_val in filter_capabilities.items():
            cap_elem = xml_helper.create_subelement(elem, "{}{}".format(self.ogc_ns, cap_key))
            for operator_key, operator_val in cap_val.items():
                op_elem = xml_helper.create_subelement(cap_elem, "{}{}".format(self.ogc_ns, operator_key))
                singular_operator_key = operator_key[:-1] if operator_key[-1] == "s" else operator_key
                for val in operator_val:
                    xml_helper.create_subelement(op_elem, "{}{}".format(self.ogc_ns, singular_operator_key)).text = val
コード例 #7
0
ファイル: converter.py プロジェクト: terrestris/mrmap
    def _create_dublin_core_brief_elem(self, md: Metadata):
        """ Creates the BriefRecord in Dublin core syntax

        Args:
            md (Metadata): The metadata object providing the data
        Returns:
             elem (_Element): The lxml element
        """
        record_elem = Element(
            "{}BriefRecord".format(self.csw_ns),
            nsmap=self.dc_ns_map,
        )

        # Perform xml creation for simple elements
        attribute_element_map = OrderedDict()
        attribute_element_map[IDENTIFIER_TEMPLATE.format(
            self.dc_ns)] = md.identifier
        attribute_element_map[TITLE_TEMPLATE.format(self.dc_ns)] = md.title
        attribute_element_map[TYPE_TEMPLATE.format(
            self.dc_ns
        )] = md.metadata_type if md.metadata_type == MetadataEnum.DATASET.value else MetadataEnum.SERVICE.value

        # Create xml elements from mapped information
        self._create_xml_from_map(record_elem, attribute_element_map)

        # Perform xml creation for complex elements
        geometry = md.bounding_geometry if md.bounding_geometry is not None and md.bounding_geometry.area > 0 else md.find_max_bounding_box(
        )
        bbox_elem = xml_helper.create_subelement(
            record_elem,
            "{}BoundingBox".format(self.ows_ns),
            attrib={"crs": "EPSG:{}".format(geometry.srid)})

        bbox = geometry.extent
        lower_corner_elem = xml_helper.create_subelement(
            bbox_elem, "{}LowerCorner".format(self.ows_ns))
        lower_corner_elem.text = "{} {}".format(bbox[0], bbox[1])
        upper_corner_elem = xml_helper.create_subelement(
            bbox_elem, "{}UpperCorner".format(self.ows_ns))
        upper_corner_elem.text = "{} {}".format(bbox[2], bbox[3])

        return record_elem
コード例 #8
0
ファイル: converter.py プロジェクト: terrestris/mrmap
    def _create_xml_from_map(self, parent_element: Element, map: OrderedDict):
        """ Creates xml elements from a given tag-attribute map.

        Only for simple elements, which only hold a tag and text data.

        Args:
            parent_element (Element): The upper xml element
            map (OrderedDict): The tag-attribute map
        Returns:

        """
        for key, val in map.items():
            if isinstance(val, list):
                for item in val:
                    elem = xml_helper.create_subelement(parent_element, key)
                    elem.text = item

            else:
                elem = xml_helper.create_subelement(parent_element, key)
                elem.text = val
コード例 #9
0
ファイル: converter.py プロジェクト: terrestris/mrmap
    def _create_dublin_core_full_elem(self, md: Metadata):
        """ Creates the default (full) record in Dublin core syntax

        Args:
            md (Metadata): The metadata object providing the data
        Returns:
             elem (_Element): The lxml element
        """
        record_elem = Element(
            "{}Record".format(self.csw_ns),
            nsmap=self.dc_ns_map,
        )

        # Perform xml creation for simple elements
        attribute_element_map = OrderedDict()
        attribute_element_map[IDENTIFIER_TEMPLATE.format(
            self.dc_ns)] = md.identifier
        attribute_element_map["{}date".format(
            self.dc_ns)] = md.created.strftime(DATE_STRF)
        attribute_element_map[TITLE_TEMPLATE.format(self.dc_ns)] = md.title
        attribute_element_map["{}abstract".format(self.dct_ns)] = md.abstract
        attribute_element_map["{}description".format(self.dc_ns)] = md.abstract
        attribute_element_map[TYPE_TEMPLATE.format(
            self.dc_ns
        )] = md.metadata_type if md.metadata_type == MetadataEnum.DATASET.value else MetadataEnum.SERVICE.value
        kws = md.keywords.all()
        formats = md.get_formats()
        attribute_element_map["{}subject".format(
            self.dc_ns)] = [kw.keyword for kw in kws]
        attribute_element_map["{}format".format(
            self.dc_ns)] = [format.mime_type for format in formats]
        attribute_element_map["{}modified".format(
            self.dct_ns)] = md.last_modified.strftime(DATE_STRF)
        attribute_element_map["{}rights".format(self.dc_ns)] = "ToDo"  # ToDo

        # Create xml elements from mapped information
        self._create_xml_from_map(record_elem, attribute_element_map)

        # Perform xml creation for more complex elements
        # URI
        elem = xml_helper.create_subelement(record_elem,
                                            "{}URI".format(self.dc_ns),
                                            attrib={
                                                "protocol": "",
                                                "name": md.identifier or "",
                                                "description": md.abstract
                                                or "",
                                            })
        elem.text = md.capabilities_uri

        return record_elem
コード例 #10
0
ファイル: request_resolver.py プロジェクト: terrestris/mrmap
    def _create_csw_operations_metadata(self, root: Element):
        """ Creates the <ows:OperationsMetadata> element

        Returns:

        """
        elem = xml_helper.create_subelement(
            root,
            "{}OperationsMetadata".format(self.ows_ns)
        )
        operations_metadata = CSW_CAPABILITIES_CONF.get("operations_metadata", {})
        operations = operations_metadata.get("operations", {})

        for operation_name, operation_val in operations.items():
            operation_elem = xml_helper.create_subelement(elem, "{}Operation".format(self.ows_ns), attrib={
                "name": operation_name
            })
            # DCP | HTTP
            dcp_elem = xml_helper.create_subelement(operation_elem, "{}DCP".format(self.ows_ns))
            http_elem = xml_helper.create_subelement(dcp_elem, "{}HTTP".format(self.ows_ns))

            ## Get
            get_uri = operation_val.get("get_uri", None)
            if get_uri is not None:
                xml_helper.create_subelement(http_elem, "{}Get".format(self.ows_ns), attrib={
                    "{}href".format(self.xlink_ns): get_uri
                })

            ## Post
            post_uri = operation_val.get("post_uri", None)
            if post_uri is not None:
                xml_helper.create_subelement(http_elem, "{}Post".format(self.ows_ns), attrib={
                    "{}href".format(self.xlink_ns): post_uri
                })

            # Parameter
            parameters = operation_val.get("parameter", {})
            self._create_parameter_elem(parameters, operation_elem)

            # Constraint
            constraints = operation_val.get("constraint", {})
            self._create_constraint_elem(constraints, operation_elem)

        # General parameters and constraints
        parameters = operations_metadata.get("parameters", {})
        self._create_parameter_elem(parameters, elem)
        constraints = operations_metadata.get("constraints", {})
        self._create_constraint_elem(constraints, elem)
コード例 #11
0
ファイル: request_builder.py プロジェクト: majo72/mrmap
    def _build_lock_feature_xml(self, service_param: str, version_param: str,
                                request_param: str):
        """ Returns the POST request XML for a Lock request

        Args:
            service_param (str): The service param
            version_param (str): The version param
            request_param (str): The request param
        Returns:
             xml (str): The xml document
        """
        xml = ""

        lock_action_param = self._get_POST_val("lockAction") or ""
        type_name_param = self._get_POST_val("typename")
        filter_param = self._get_POST_val("filter")

        reduced_ns_map = self._get_version_specific_namespaces(
            version_param, service_param)

        root_attributes = {
            "service": service_param,
            "version": version_param,
            "lockAction": lock_action_param
        }
        root = etree.Element(_tag=request_param,
                             nsmap=reduced_ns_map,
                             attrib=root_attributes)

        # create the xml filter object from the filter string parameter
        filter_xml = xml_helper.parse_xml(filter_param)
        filter_xml_root = filter_xml.getroot()

        for t_n_param in type_name_param.split(","):
            query_attributes = {"typeName": t_n_param}
            query_elem = xml_helper.create_subelement(root,
                                                      "Query",
                                                      attrib=query_attributes)

            # add the filter xml object as subobject to the query to use e.g. the spatial restriction
            xml_helper.add_subelement(query_elem, filter_xml_root)

        xml = xml_helper.xml_to_string(root)

        return xml
コード例 #12
0
ファイル: request_resolver.py プロジェクト: terrestris/mrmap
    def _create_csw_service_identification(self, root: Element):
        """ Creates the <ows:ServiceIdentification> element

        Returns:

        """
        elem = xml_helper.create_subelement(
            root,
            "{}ServiceIdentification".format(self.ows_ns)
        )

        service_identification = CSW_CAPABILITIES_CONF.get("service_identification")

        # Title
        xml_helper.create_subelement(elem, "{}Title".format(self.ows_ns)).text = service_identification.get("title", "")

        # Abstract
        xml_helper.create_subelement(elem, "{}Abstract".format(self.ows_ns)).text = service_identification.get("abstract", "")

        # Keywords
        kw_elem = xml_helper.create_subelement(elem, "{}Keywords".format(self.ows_ns))
        keywords = service_identification.get("keywords", "").split(",")
        for kw in keywords:
            xml_helper.create_subelement(kw_elem, "{}Keyword".format(self.ows_ns)).text = kw

        # ServiceType
        xml_helper.create_subelement(elem, "{}ServiceType".format(self.ows_ns)).text = service_identification.get("service_type", "")

        # ServiceTypeVersion
        xml_helper.create_subelement(elem, "{}ServiceTypeVersion".format(self.ows_ns)).text = service_identification.get("service_type_version", "")

        # Fees
        xml_helper.create_subelement(elem, "{}Fees".format(self.ows_ns)).text = service_identification.get("fees", "")

        # AccessConstraints
        xml_helper.create_subelement(elem, "{}AccessConstraints".format(self.ows_ns)).text = service_identification.get("access_constraints", "")
コード例 #13
0
def _overwrite_capabilities_keywords(xml_obj: _Element, metadata: Metadata,
                                     _type: str):
    """ Overwrites existing capabilities keywords with metadata editor input

    Args:
        xml_obj (_Element): The parent xml object which holds the KeywordList element
        metadata (Metadata): The metadata object which holds the edited keyword data
        _type (str): Defines if this is a wms or wfs
    Returns:
         nothing
    """
    ns_prefix = ""
    keyword_container_tag = "KeywordList"
    keyword_prefix = ""
    keyword_ns_map = {}

    if _type == 'wfs':
        ns_keyword_prefix_s = "ows"
        ns_prefix = "wfs:"
        if metadata.is_root():
            # for the <ows:ServiceIdentification> element we need the prefix "ows:"
            ns_prefix = "ows:"
        keyword_container_tag = "Keywords"
        keyword_prefix = "{" + XML_NAMESPACES[ns_keyword_prefix_s] + "}"
        keyword_ns_map[ns_keyword_prefix_s] = XML_NAMESPACES[
            ns_keyword_prefix_s]

    xml_keywords_list_obj = xml_helper.try_get_single_element_from_xml(
        "./" + GENERIC_NAMESPACE_TEMPLATE.format(keyword_container_tag),
        xml_obj)

    if xml_keywords_list_obj is None:
        # there are no keywords in this capabilities for this element yet
        # we need to add an element first!
        try:
            xml_keywords_list_obj = xml_helper.create_subelement(
                xml_obj,
                "{}{}".format(keyword_prefix, keyword_container_tag),
                after="{}Abstract".format(ns_prefix),
                nsmap=keyword_ns_map)
        except (TypeError, ValueError) as e:
            # there seems to be no <Abstract> element. We add simply after <Title> and also create a new Abstract element
            xml_keywords_list_obj = xml_helper.create_subelement(
                xml_obj,
                "{}{}".format(keyword_prefix, keyword_container_tag),
                after="{}Title".format(ns_prefix))
            xml_helper.create_subelement(xml_obj,
                                         "{}".format("Abstract"),
                                         after="{}Title".format(ns_prefix))

    xml_keywords_objs = xml_helper.try_get_element_from_xml(
        "./" + GENERIC_NAMESPACE_TEMPLATE.format("Keyword"),
        xml_keywords_list_obj) or []

    # first remove all persisted keywords
    for kw in xml_keywords_objs:
        xml_keywords_list_obj.remove(kw)

    # then add all edited
    for kw in metadata.keywords.all():
        xml_keyword = xml_helper.create_subelement(
            xml_keywords_list_obj,
            "{}Keyword".format(keyword_prefix),
            nsmap=keyword_ns_map)
        xml_helper.write_text_to_element(xml_keyword, txt=kw.keyword)
コード例 #14
0
ファイル: request_builder.py プロジェクト: majo72/mrmap
    def _build_get_feature_xml(self, service_param: str, version_param: str,
                               request_param: str):
        """ Returns the POST request XML for a GetFeature request

        Args:
            service_param (str): The service param
            version_param (str): The version param
            request_param (str): The request param
        Returns:
             xml (str): The xml document
        """
        xml = ""

        format_param = self._get_POST_val("format")
        type_name_param = self._get_POST_val("typename") or self._get_POST_val(
            "typenames")
        filter_param = self._get_POST_val("filter")
        count_param = self._get_POST_val("count") or self._get_POST_val(
            "maxFeatures")
        resulttype_param = self._get_POST_val("count") or self._get_POST_val(
            "resultType")

        # check if the newer 'typeNames' instead of 'typeName' should be used
        type_name_identifier = "typeName"
        if version_param == OGCServiceVersionEnum.V_2_0_0.value or version_param == OGCServiceVersionEnum.V_2_0_2.value:
            type_name_identifier = "typeNames"

        reduced_ns_map = self._get_version_specific_namespaces(
            version_param, service_param)
        wfs_ns = reduced_ns_map["wfs"]

        root_attributes = {
            "service": service_param,
            "version": version_param,
        }

        if resulttype_param is not None:
            root_attributes["resultType"] = resulttype_param
        if format_param is not None:
            root_attributes["outputFormat"] = format_param
        if count_param is not None:
            param_tag = "maxFeatures"
            if version_param == OGCServiceVersionEnum.V_2_0_0.value or version_param == OGCServiceVersionEnum.V_2_0_2.value:
                param_tag = "count"
            root_attributes[param_tag] = count_param

        root = etree.Element(_tag="{" + wfs_ns + "}" + request_param,
                             nsmap=reduced_ns_map,
                             attrib=root_attributes)

        # create the xml filter object from the filter string parameter
        filter_xml = xml_helper.parse_xml(filter_param)
        if filter_xml is not None:
            filter_xml_root = filter_xml.getroot()

            for t_n_param in type_name_param.split(","):
                query_attributes = {type_name_identifier: t_n_param}
                query_elem = xml_helper.create_subelement(
                    root,
                    "{" + wfs_ns + "}" + "Query",
                    attrib=query_attributes)

                # add the filter xml object as subobject to the query to use e.g. the spatial restriction
                xml_helper.add_subelement(query_elem, filter_xml_root)

            xml = xml_helper.xml_to_string(root)

        return xml
コード例 #15
0
ファイル: request_resolver.py プロジェクト: terrestris/mrmap
    def _create_csw_service_provider(self, root: Element):
        """ Creates the <ows:ServiceProvider> element

        Returns:

        """
        elem = xml_helper.create_subelement(
            root,
            "{}ServiceProvider".format(self.ows_ns)
        )

        service_provider = CSW_CAPABILITIES_CONF.get("service_provider")

        # ProviderName
        xml_helper.create_subelement(elem, "{}ProviderName".format(self.ows_ns)).text = service_provider.get("name", "")

        # ProviderSite
        xml_helper.create_subelement(elem, "{}ProviderSite".format(self.ows_ns), attrib={"{}href".format(self.xlink_ns): service_provider.get("provider_site")})

        # ServiceContact
        contact_elem = xml_helper.create_subelement(elem, "{}ServiceContact".format(self.ows_ns))

        ## IndividualName
        xml_helper.create_subelement(contact_elem, "{}IndividualName".format(self.ows_ns)).text = service_provider.get("individual_name", "")

        ## PositionName
        xml_helper.create_subelement(contact_elem, "{}PositionName".format(self.ows_ns)).text = service_provider.get("position_name", "")

        ## ContactInfo
        contact_info_elem = xml_helper.create_subelement(contact_elem, "{}ContactInfo".format(self.ows_ns))

        ### Phone
        phone_elem = xml_helper.create_subelement(contact_info_elem, "{}Phone".format(self.ows_ns))

        #### Voice
        xml_helper.create_subelement(phone_elem, "{}Voice".format(self.ows_ns)).text = service_provider.get("contact_phone", "")

        #### Facsimile
        xml_helper.create_subelement(phone_elem, "{}Facsimile".format(self.ows_ns)).text = service_provider.get("contact_facsimile", "")

        ### Address
        address_elem = xml_helper.create_subelement(contact_info_elem, "{}Address".format(self.ows_ns))

        #### DeliveryPoint
        xml_helper.create_subelement(address_elem, "{}DeliveryPoint".format(self.ows_ns)).text = service_provider.get("contact_address_delivery_point", "")

        #### City
        xml_helper.create_subelement(address_elem, "{}City".format(self.ows_ns)).text = service_provider.get("contact_address_city", "")

        #### AdministrativeArea
        xml_helper.create_subelement(address_elem, "{}AdministrativeArea".format(self.ows_ns)).text = service_provider.get("contact_address_administrative_area", "")

        #### PostalCode
        xml_helper.create_subelement(address_elem, "{}PostalCode".format(self.ows_ns)).text = service_provider.get("contact_address_postal_code", "")

        #### Country
        xml_helper.create_subelement(address_elem, "{}Country".format(self.ows_ns)).text = service_provider.get("contact_address_country", "")

        #### ElectronicMailAddress
        xml_helper.create_subelement(address_elem, "{}ElectronicMailAddress".format(self.ows_ns)).text = service_provider.get("contact_address_email", "")