gisserver.parsers.xml module

XML parsing for all incoming requests.

This logic uses the etree logic from the standard library, with some extra extensions to expose the original namespace aliases. Using defusedxml, incoming DOS attacks are prevented.

To handle more complex XML structures, consider building an Abstract Syntax Tree (AST) to translate the XML Element classes into Python objects. The gisserver.parsers.ast module provides the building blocks for that.

class gisserver.parsers.xml.NSElement(*args, **kwargs)

Bases: Element

Custom XML element, which also exposes its original namespace aliases. That information is needed to parse text content and attributes in WFS that hold a QName value. For example:

  • <ValueReference>ns0:elementName</ValueReference>

  • <Query typeNames="ns1:name">

__init__(*args, **kwargs)
get_int_attribute(name: str, default=None) int | None

Retrieve the integer value from an element attribute.

get_str_attribute(name: str) str

Resolve an attribute, raise an error when it’s missing.

parse_qname(qname: str) str

Resolve an aliased QName value to its fully qualified name.

property qname: str

Provde the tag name in its original short format

gisserver.parsers.xml.parse_qname(qname: str | None, ns_aliases: dict) str | None

Resolve the QName aliases.

For example, gml:Point will be resolved to {http://www.opengis.net/gml/3.2}Point. The XML namespace prefix is a custom alias, so if “ns0” is declared as “http://www.opengis.net/gml/3.2”, it means “ns0:Point” should resolve to the same fully qualified type name.

gisserver.parsers.xml.parse_xml_from_string(xml_string: str | bytes, extra_ns_aliases: dict[str, str] | None = None) NSElement

Provide a safe and consistent way for parsing XML.

This uses a custom parser, so namespace aliases can be tracked. All elements also have an ns_aliases attribute that exposes the original alias that was used for the namespace.

gisserver.parsers.xml.split_ns(xml_name: str) tuple[str | None, str]

Split the element tag or attribute/text value into the namespace and local name. The stdlib etree doesn’t have the properties for this (lxml does).

class gisserver.parsers.xml.xmlns(*values)

Bases: Enum

Common namespaces within WFS land. Note these short aliases are arbitrary in XML syntax; the XML code may use any alias (such as ns0). The full qualified name (e.g. <{http://www.opengis.net/gml/3.2}Point>) is the actual tag name.

classmethod as_namespaces() dict[str, str]

Map the namespaces as {uri: alias}. This will use the common aliases (without version numbers)

classmethod as_ns_aliases() dict[str, str]

Map the namespaces as {alias: uri}

fes = 'http://www.opengis.net/fes/2.0'
fes20 = 'http://www.opengis.net/fes/2.0'
gml = 'http://www.opengis.net/gml/3.2'
gml21 = 'http://www.opengis.net/gml'
gml32 = 'http://www.opengis.net/gml/3.2'
ogc = 'http://www.opengis.net/ogc'
ows = 'http://www.opengis.net/ows/1.1'
ows10 = 'http://www.opengis.net/ows'
ows11 = 'http://www.opengis.net/ows/1.1'
ows20 = 'http://www.opengis.net/ows/2.0'
qname(local_name) str

Convert the tag name into a fully qualified name.

wcs = 'http://www.opengis.net/wcs'
wcs20 = 'http://www.opengis.net/wcs/2.0'
wfs = 'http://www.opengis.net/wfs/2.0'
wfs1 = 'http://www.opengis.net/wfs'
wfs20 = 'http://www.opengis.net/wfs/2.0'
wms = 'http://www.opengis.net/wms'
wmts = 'http://www.opengis.net/wmts/1.0'
wps = 'http://www.opengis.net/wps/1.0.0'
xml = 'http://www.w3.org/XML/1998/namespace'
xs = 'http://www.w3.org/2001/XMLSchema'
xsd = 'http://www.w3.org/2001/XMLSchema'
xsi = 'http://www.w3.org/2001/XMLSchema-instance'