gisserver.parsers.ast module¶
Utilities for building an Abstract Syntax Tree (AST) from an XML fragment.
By transforming the XML Element nodes into Python objects, most logic naturally follows. For example, the FES filter syntax can be processed into objects that build an ORM query.
Python classes can inherit AstNode and register themselves as the parser/handler
for a given tag. Both normal Python classes and dataclass work,
as long as it has an AstNode.from_xml() class method.
The custom from_xml() method should copy the XML data into local attributes.
Next, when TagRegistry.node_from_xml() is called,
it will detect which class the XML Element refers to and initialize it using the from_xml() call.
As convenience, calling a AstNode.child_from_xml()
on a subclass will also initialize the right subclass and initialize it.
Since clients may not follow the desired XML schema, and make mistakes, we should guard against
creating an invalid Abstract Syntax Tree. When using TagRegistry.node_from_xml(),
the allowed child types can also be provided, preventing invalid child elements.
Furthermore, to support the creation of from_xml() methods, the expect_tag(),
expect_children() and expect_no_children() decorators validate
whether the given tag has the expected elements. This combination should make it easy
to validate whether a provided XML structure confirms to the supported schema.
- class gisserver.parsers.ast.AstNode¶
Bases:
objectThe base node for all classes that represent an XML tag.
All subclasses of this class build an Abstract Syntax Tree (AST) that describes the XML content in Python objects. Each object can handle implement additional logic to
Each subclass should implement the
from_xml()to translate an XML tag into a Python (data) class.- classmethod child_from_xml(element: NSElement) AstNode¶
Parse the element, returning the correct subclass of this tag.
When
Expression.child_from_xml(some_node)is given, it may return aLiteral,ValueReference,FunctionorBinaryOperatornode.
- classmethod from_xml(element: NSElement)¶
Initialize this Python class from the data of the corresponding XML tag. Each subclass overrides this to implement the XML parsing of that particular XML tag.
- xml_name¶
Tell the default tag by which this class is registered
- class gisserver.parsers.ast.TagNameEnum(new_class_name, /, names, *, module=None, qualname=None, type=None, start=1, boundary=None)¶
Bases:
EnumAn base clas for enumerations of XML tag names.
All enumerations that represent tag names inherit from this. Each member name should be exactly the XML tag that it refers to.
- class gisserver.parsers.ast.TagRegistry¶
Bases:
objectRegistration of all classes that can parse XML nodes.
The same class can be registered multiple times for different tag names.
- __init__()¶
- node_from_xml(element: NSElement, allowed_types: tuple[type[A]] | None = None) A¶
Find the
AstNodesubclass that corresponds to the given XML element, and initialize it with the element. This is a convenience shortcut.
- register(tag: str | type[TagNameEnum] | None = None, namespace: xmlns | str | None = None, hidden: bool = False)¶
Decorator to register a class as XML element parser.
Usage:
@dataclass @tag_registry.register() class SomeXmlTag(AstNode): xml_ns = FES @classmethod def from_xml(cls, element: NSElement): return cls( ... )
Whenever an element of the registered XML name is found, the given “SomeXmlTag” will be initialized.
It’s also possible to register tag names using an enum; each member name is assumed to be an XML tag name.
- gisserver.parsers.ast.expect_children(min_child_nodes, *expect_types: str | type[AstNode], silent_allowed: tuple[str] = ())¶
Decorator for
from_xml()methods to validate whether an element has the expected children.For example:
@classmethod @expect_children(2, Expression) def from_xml(cls, element): ...
- gisserver.parsers.ast.expect_no_children(from_xml_func)¶
Decorator for
from_xml()methods that validate that the XML tag has no child nodes.For example:
@classmethod @expect_tag(xmlns.fes20, "ResourceId") @expect_no_children def from_xml(cls, element): ...
- gisserver.parsers.ast.expect_tag(namespace: xmlns | str, *tag_names: str)¶
Decorator for
from_xml()methods that validate whether a given tag is provided.For example:
@classmethod @expect_tag(xmlns.fes20, "Literal") def from_xml(cls, element): ...
This guard is needed when nodes are passed directly to a
from_xml()method.
- gisserver.parsers.ast.tag_registry = <gisserver.parsers.ast.TagRegistry object>¶
The tag registry to register new parsing classes at.