gisserver.parsers.fes20 package

Parsing and processing of the OGC Filter Encoding Standard 2.0 (FES).

This parses the XML syntax, and translates that into a Django ORM query.

It’s also possible to register custom functions, which will include Django ORM function as part of the filter language.

The full spec can be found at: https://www.ogc.org/publications/standard/filter/. Secondly, using https://www.mediamaps.ch/ogc/schemas-xsdoc/sld/1.2/filter_xsd.html can be very helpful to see which options each object type should support.

Filters

class gisserver.parsers.fes20.filters.Filter(predicate: Function | Operator, source: AnyStr | None = None)

Bases: AstNode

The <fes:Filter> element.

This parses and handles the syntax:

<fes:Filter>
    <fes:SomeOperator>
        ...
    </fes:SomeOperator>
</fes:Filter>

The build_query() will convert the parsed tree into a format that can build a Django ORM QuerySet.

__init__(predicate: Function | Operator, source: AnyStr | None = None) None
build_query(compiler: CompiledQuery) Q | None

Collect the data to perform a Django ORM query.

classmethod from_kvp_request(kvp: KVPRequest) Filter | None

Parse the filter from the GET request.

classmethod from_string(text: AnyStr, ns_aliases: dict[str, str] | None = None) Filter

Parse an XML <fes:Filter> string.

This uses defusedxml by default, to avoid various XML injection attacks.

Raises:
classmethod from_xml(element: NSElement, source: AnyStr | None = None) Filter

Parse the <fes20:Filter> element.

get_resource_id_types() list[str] | None

When the filter predicate consists of <fes:ResourceId> elements, return those. This can return an empty list in case a <fes:ResourceId> object doesn’t define a type.

predicate: Function | Operator

The filter predicate (body)

query_language: ClassVar[str] = 'urn:ogc:def:queryLanguage:OGC-FES:Filter'
source: AnyStr | None = None
classmethod validate_kvp_exclusions(filter: Filter | None, bbox: GEOSGMLGeometry | None, resource_ids: list)

Validate mutually exclusive parameters

gisserver.parsers.fes20.filters.FilterPredicates

The FES element group that can be used as body for the Filter element.

alias of Function | Operator

Expressions

These classes map to the FES 2.0 specification for expressions. The class names are identical to those in the FES spec.

Inheritance structure:

The BinaryOperator is included as expression to handle FES 1.0 BinaryOperatorType arithmetic tags: <fes:Add>, <fes:Sub>, <fes:Mul>, <fes:Div>.

class gisserver.parsers.fes20.expressions.BinaryOperator(_operatorType: BinaryOperatorType, expression: tuple[Expression, Expression])

Bases: Expression

Support for FES 1.0 arithmetic operators.

This parses a syntax like:

<fes:Add>
    <fes:ValueReference>field-name</fes:ValueReference>
    <fes:Literal>2</fes:Literal>
</fes:Add>

The operator can be a <fes:Add>, <fes:Sub>, <fes:Mul>, <fes:Div>.

These are no longer part of the FES 2.0 spec, but clients (like QGis) still assume the server use these. Hence, these need to be included.

__init__(_operatorType: BinaryOperatorType, expression: tuple[Expression, Expression]) None
build_rhs(compiler) Combinable | Func | Q | GEOSGeometry | bool | int | Decimal | str | date | datetime | tuple

Get the expression as the right-hand-side of the equation.

Typically, this can return the exact value.

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.

validate_arithmetic(compiler, lhs: Expression, rhs: Expression)

Check whether values support arithmetic operators.

class gisserver.parsers.fes20.expressions.BinaryOperatorType(*values)

Bases: TagNameEnum

FES 1.0 Arithmetic operators.

These are no longer part of the FES 2.0 spec, but clients (like QGis) still assume the server supports these. Hence, these need to be included.

class gisserver.parsers.fes20.expressions.Expression

Bases: AstNode

Abstract base class, as defined by FES spec.

The FES spec defines the following subclasses:

When code uses Expression.child_from_xml(element), the AST logic will initialize the correct subclass for those elements.

build_lhs(compiler) str

Get the expression as the left-hand-side of the equation.

This typically returns the expression as a ‘field name’ which can be used in the Django QuerySet.filter(name=…) syntax. When the expression is actually a Function/Literal, this should generate the name using a queryset annotation.

build_rhs(compiler) Combinable | Func | Q | GEOSGeometry | bool | int | Decimal | str | date | datetime | tuple

Get the expression as the right-hand-side of the equation.

Typically, this can return the exact value.

xml_ns: xmlns | str | None = 'http://www.opengis.net/fes/2.0'

Default namespace of the element and subclasses, if not given by @tag_registry.register().

class gisserver.parsers.fes20.expressions.Function(name: str, arguments: list[Expression])

Bases: Expression

The <fes:Function name="..."> element.

This parses the syntax such as:

<fes:Function name="Add">
    <fes:ValueReference>field-name</fes:ValueReference>
    <fes:Literal>2</fes:Literal>
</fes:Function>

Each argument of the function can be another Expression, such as a Function, ValueReference or Literal.

__init__(name: str, arguments: list[Expression]) None
build_rhs(compiler) Func

Build the SQL function object

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.

class gisserver.parsers.fes20.expressions.Literal(raw_value: None | str | GM_Object | GM_Envelope | TM_Object, raw_type: str | None = None)

Bases: Expression

The <fes:Literal> element that holds a literal value.

This can be a string value, possibly annotated with a type:

<fes:Literal type="xs:boolean">true</fes:Literal>

Following the spec, the value may also contain a complete geometry:

<fes:Literal>
    <gml:Envelope xmlns:gml="http://www.opengis.net/gml/3.2" srsName="urn:ogc:def:crs:EPSG::4326">
        <gml:lowerCorner>5.7 53.1</gml:lowerCorner>
        <gml:upperCorner>6.1 53.5</gml:upperCorner>
    </gml:Envelope>
</fes:Literal>
__init__(raw_value: None | str | GM_Object | GM_Envelope | TM_Object, raw_type: str | None = None) None
bind_type(type: XsdTypes)

Assign the expected type that this literal is compared against

build_lhs(compiler) str

Alias the value when it’s used in the left-hand-side.

By aliasing the value using an annotation, it can be queried like a regular field name.

build_rhs(compiler) Combinable | Q | int | str | date | Decimal | datetime | GM_Object | GM_Envelope | TM_Object | None

Return the value when it’s used in the right-hand-side

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.

property type: XsdTypes | None

Tell which datatype the literal holds. This returns the type=”…” value of the element.

property value: int | str | date | Decimal | datetime | GM_Object | GM_Envelope | TM_Object | None

Access the value of the element, cast to the appropriate data type. :raises ExternalParsingError: When the value can’t be converted to the proper type.

class gisserver.parsers.fes20.expressions.ValueReference(xpath: str, xpath_ns_aliases: dict[str, str] | None = None)

Bases: Expression

The <fes:ValueReference> element that holds an XPath string. In the fes XSD, this is declared as a subclass of xsd:string.

This parses the syntax like:

<fes:ValueReference>field-name</fes:ValueReference>
<fes:ValueReference>path/to/field-name</fes:ValueReference>
<fes:ValueReference>collection[@attr=value]/field-name</fes:ValueReference>

The old WFS1/FES1 “PropertyName” is allowed as an alias. Various clients still send this, and mapserver/geoserver support this.

__init__(xpath: str, xpath_ns_aliases: dict[str, str] | None = None) None
build_lhs(compiler) str

Use the field name in a left-hand-side expression.

build_rhs(compiler) Combinable | Func | Q | GEOSGeometry | bool | int | Decimal | str | date | datetime | tuple

Use the field name in a right-hand expression. This generates an F-expression for the ORM.

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.

parse_xpath(feature_types: list) XPathMatch

Convert the XPath into the required ORM query elements.

xpath: str

The XPath value

xpath_ns_aliases: dict[str, str] | None = None

The known namespaces aliases at this point in the XML tree

Operators

These classes map to the FES 2.0 specification for operators. The class names and attributes are identical to those in the FES spec.

Inheritance structure:

class gisserver.parsers.fes20.operators.BetweenComparisonOperator(expression: Expression, lowerBoundary: Expression, upperBoundary: Expression, _source: str | None = None)

Bases: ComparisonOperator

Check whether a value is between two elements.

This parses and handles the syntax:

<fes:PropertyIsBetween>
    <fes:ValueReference>DEPTH</fes:ValueReference>
    <fes:LowerBoundary><fes:Literal>100</fes:Literal></fes:LowerBoundary>
    <fes:UpperBoundary><fes:Literal>200</fes:Literal></fes:UpperBoundary>
</fes:PropertyIsBetween>

Note that both boundary arguments receive expressions, so these can be value references, literals or functions!

__init__(expression: Expression, lowerBoundary: Expression, upperBoundary: Expression, _source: str | None = None) None
build_query(compiler: CompiledQuery) Q
expression: Expression
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.

lowerBoundary: Expression
upperBoundary: Expression
class gisserver.parsers.fes20.operators.BinaryComparisonName(*values)

Bases: TagNameEnum

XML tag names for value comparisons. This also maps their names to ORM field lookups.

PropertyIsEqualTo = 'exact'
PropertyIsGreaterThan = 'gt'
PropertyIsGreaterThanOrEqualTo = 'gte'
PropertyIsLessThan = 'lt'
PropertyIsLessThanOrEqualTo = 'lte'
PropertyIsNotEqualTo = 'fes_notequal'
class gisserver.parsers.fes20.operators.BinaryComparisonOperator(operatorType: BinaryComparisonName, expression: tuple[Expression, Expression], matchCase: bool = True, matchAction: MatchAction = MatchAction.Any, _source: str | None = None)

Bases: ComparisonOperator

A comparison between 2 values, e.g. A == B.

This parses and handles the syntax:

<fes:PropertyIsEqualTo>
    <fes:ValueReference>city/name</fes:ValueReference>
    <fes:Literal>CloudCity</fes:Literal>
</fes:PropertyIsEqualTo>

…and all variations (<fes:PropertyIsLessThan>, etc…) that are listed in the BinaryComparisonName enum.

Note that both arguments are expressions, so these can be value references, literals or functions. The <fes:Literal> element may hold a GML element as its value.

__init__(operatorType: BinaryComparisonName, expression: tuple[Expression, Expression], matchCase: bool = True, matchAction: MatchAction = MatchAction.Any, _source: str | None = None) None
build_query(compiler: CompiledQuery) Q
expression: tuple[Expression, Expression]
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.

matchAction: MatchAction = 'Any'
matchCase: bool = True
operatorType: BinaryComparisonName
class gisserver.parsers.fes20.operators.BinaryLogicOperator(operands: list[NonIdOperator], operatorType: BinaryLogicType, _source: str | None = None)

Bases: LogicalOperator

Apply an ‘AND’ or ‘OR’ operator.

This parses and handles the syntax:

<fes:And>
    <fes:PropertyIsGreaterThanOrEqualTo>
        ...
    </fes:PropertyIsGreaterThanOrEqualTo>
    <fes:BBOX>
        ...
    </fes:BBOX>
</fes:And>

Any tag deriving from NonIdOperator is allowed here.

__init__(operands: list[NonIdOperator], operatorType: BinaryLogicType, _source: str | None = None) None
build_query(compiler: CompiledQuery) Q

Apply the AND/OR operation to the Q-object

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.

operands: list[NonIdOperator]
operatorType: BinaryLogicType
class gisserver.parsers.fes20.operators.BinaryLogicType(*values)

Bases: TagNameEnum

XML tag names for the BinaryLogicOperator.

And = <built-in function and_>
Or = <built-in function or_>
class gisserver.parsers.fes20.operators.BinarySpatialOperator(operatorType: SpatialOperatorName, operand1: ValueReference | None, operand2: GM_Object | GM_Envelope | ValueReference, _source: str | None = None)

Bases: SpatialOperator

A comparison of geometries using 2 values, e.g. A Within B.

This parses and handles the syntax, and its variants:

<fes:BBOX>
    <fes:ValueReference>Geometry</fes:ValueReference>
    <gml:Envelope srsName="http://www.opengis.net/def/crs/epsg/0/4326">
        <gml:lowerCorner>13.0983 31.5899</gml:lowerCorner>
        <gml:upperCorner>35.5472 42.8143</gml:upperCorner>
    </gml:Envelope>
</fes:BBOX>

It also handles the <fes:Equals>, <fes:Within>, <fes:Intersects>, etc.. that exist in the SpatialOperatorName enum.

__init__(operatorType: SpatialOperatorName, operand1: ValueReference | None, operand2: GM_Object | GM_Envelope | ValueReference, _source: str | None = None) None
allow_geometries = True
build_query(compiler: CompiledQuery) Q
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.

operand1: ValueReference | None
operand2: GM_Object | GM_Envelope | ValueReference
operatorType: SpatialOperatorName
class gisserver.parsers.fes20.operators.ComparisonOperator

Bases: NonIdOperator

Base class for comparisons. This class name mirrors the fes-spec name, and allows grouping various comparisons together.

class gisserver.parsers.fes20.operators.DistanceOperator(valueReference: ValueReference, operatorType: DistanceOperatorName, geometry: GM_Object, distance: Measure, _source: str | None = None)

Bases: SpatialOperator

Comparing the distance to a geometry.

This parses and handles the syntax:

<fes:DWithin>
    <fes:ValueReference>geometry</fes:ValueReference>
    <gml:Point srsDimension="2">
        <gml:pos>43.55749 1.525864</gml:pos>
    </gml:Point>
    <fes:Distance oum="m:>100</fes:Distance>
</fes:DWithin>
__init__(valueReference: ValueReference, operatorType: DistanceOperatorName, geometry: GM_Object, distance: Measure, _source: str | None = None) None
allow_geometries = True
build_query(compiler: CompiledQuery) Q
distance: Measure
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.

geometry: GM_Object
operatorType: DistanceOperatorName
valueReference: ValueReference
class gisserver.parsers.fes20.operators.DistanceOperatorName(*values)

Bases: TagNameEnum

XML tag names mapped to distance operators for the ORM.

Beyond = 'fes_beyond'
DWithin = 'dwithin'
class gisserver.parsers.fes20.operators.ExtensionOperator

Bases: NonIdOperator

Base class for extensions to FES 2.0.

It’s fully allowed to introduce new operators on your own namespace. These need to inherit from this class.

class gisserver.parsers.fes20.operators.IdOperator(id: list[Id])

Bases: Operator

List of ResourceId objects.

A <fes:Filter> only has a single predicate. Hence, this operator is used to wrap the <fes:ResourceId> elements in the syntax:

<fes:Filter>
    <fes:ResourceId rid="typename.123" />
    <fes:ResourceId rid="typename.345" />
</fes:Filter>
__init__(id: list[Id]) None
build_query(compiler)

Generate the ID lookup query.

As these identifiers also reference the type name, no Q-object is returned. The lookups are directly added to the fes query object.

get_type_names() list[str]

Provide a list of all type names accessed by this operator

property grouped_ids: dict[str, list[Id]]
id: list[Id]
class gisserver.parsers.fes20.operators.LikeOperator(expression: tuple[Expression, Expression], wildCard: str, singleChar: str, escapeChar: str, _source: str | None = None)

Bases: ComparisonOperator

Perform wildcard matching.

This parses and handles the syntax:

<fes:PropertyIsLike wildCard="*" singleChar="#" escapeChar="!">
    <fes:ValueReference>last_name</fes:ValueReference>
    <fes:Literal>John*</fes:Literal>
</fes:PropertyIsLike>
__init__(expression: tuple[Expression, Expression], wildCard: str, singleChar: str, escapeChar: str, _source: str | None = None) None
build_query(compiler: CompiledQuery) Q
escapeChar: str
expression: tuple[Expression, Expression]
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.

singleChar: str
wildCard: str
class gisserver.parsers.fes20.operators.LogicalOperator

Bases: NonIdOperator

Base class in the fes-spec for AND, OR, NOT comparisons

class gisserver.parsers.fes20.operators.MatchAction(*values)

Bases: Enum

Values for the ‘matchAction’ attribute of the BinaryComparisonOperator.

All = 'All'
Any = 'Any'
One = 'One'
class gisserver.parsers.fes20.operators.Measure(value: Decimal, uom: str)

Bases: AstNode

A measurement for a distance element.

This parses and handles the syntax:

<fes:Distance uom="...">value</fes:Distance>

This element is used within the DistanceOperator that handles the <fes:DWithin> and <fes:Beyond> tags.

The “unit of measurement” (uom) supports most standard units, like meters (m), kilometers (km), nautical mile (nm), miles (mi), inches (inch). The full list can be found at: https://docs.djangoproject.com/en/5.1/ref/contrib/gis/measure/#supported-units

__init__(value: Decimal, uom: str) None
build_rhs(compiler) Distance
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.

uom: str
value: Decimal
xml_ns: xmlns | str | None = 'http://www.opengis.net/fes/2.0'

Default namespace of the element and subclasses, if not given by @tag_registry.register().

class gisserver.parsers.fes20.operators.NilOperator(expression: Expression | None, nilReason: str, _source: str | None = None)

Bases: ComparisonOperator

Check whether the value evaluates to null/None. If the WFS returned a property element with <app:field xsi:nil='true'>, this returns true.

It parses and handles syntax such as:

<fes:PropertyIsNil>
    <fes:ValueReference>city/name</fes:ValueReference>
</fes:PropertyIsNil>

Note that the provided argument can be any expression, not just a value reference. Thus, it can also check whether a function returns null.

__init__(expression: Expression | None, nilReason: str, _source: str | None = None) None
allow_geometries: ClassVar[bool] = True
build_query(compiler: CompiledQuery) Q
expression: Expression | None
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.

nilReason: str
class gisserver.parsers.fes20.operators.NonIdOperator

Bases: Operator

Abstract base class, as defined by FES spec.

This is used for nearly all operators, except those that have <fes:ResourceId> elements as children.

Some operators, such as the <fes:And>, <fes:Or> and <fes:Not> operators explicitly support only NonIdOperator elements as arguments. Hence, having this base class as Python type simplifies parsing.

allow_geometries = False
build_compare(compiler: CompiledQuery, lhs: Expression, lookup: str, rhs: Expression | Combinable | Func | Q | GEOSGeometry | bool | int | Decimal | str | date | datetime | tuple) Q

Use the value in comparison with some other expression.

This calls build_lhs() and build_rhs() on the expressions.

build_compare_between(compiler: CompiledQuery, lhs: Expression, lookup: str, rhs: tuple[Expression | ValueReference | GM_Object, Expression | Measure]) Q

Use the value in comparison with 2 other values (e.g. between query)

validate_comparison(compiler: CompiledQuery, lhs: Expression, lookup: str, rhs: Expression | GM_Object | Combinable | Func | Q | GEOSGeometry | bool | int | Decimal | str | date | datetime | tuple) str

Validate whether a given comparison is even possible.

For example, comparisons like name == "test" are fine, but geometry < 4 or datefield == 35.2 raise an error.

Parameters:
  • compiler – The object that holds the intermediate state

  • lhs – The left-hand-side of the comparison (e.g. the element).

  • lookup – The ORM lookup expression being used (e.g. equals or fes_like).

  • rhs – The right-hand-side of the comparison (e.g. the value).

class gisserver.parsers.fes20.operators.NullOperator(expression: Expression, _source: str | None = None)

Bases: ComparisonOperator

Check whether the property exists. If the WFS would not return the property element <app:field>, this returns true.

It parses and handles syntax such as:

<fes:PropertyIsNull>
    <fes:ValueReference>city/name</fes:ValueReference>
</fes:PropertyIsNull>

Note that the provided argument can be any expression, not just a value reference.

__init__(expression: Expression, _source: str | None = None) None
allow_geometries: ClassVar[bool] = True
build_query(compiler: CompiledQuery) Q
expression: Expression
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.

class gisserver.parsers.fes20.operators.Operator

Bases: AstNode

Abstract base class, as defined by FES spec.

This base class is also used in parsing; for example the <fes:Filter> tag only allows Operator and Expression subclasses as allowed arguments. Having all those classes as Python types, makes it very easy to validate whether a given child element is the expected node type.

build_query(compiler: CompiledQuery) Q | None
xml_ns: xmlns | str | None = 'http://www.opengis.net/fes/2.0'

Default namespace of the element and subclasses, if not given by @tag_registry.register().

gisserver.parsers.fes20.operators.SpatialDescription

Define the types that a <gml:SpatialDescription> can be:

alias of GM_Object | GM_Envelope | ValueReference

class gisserver.parsers.fes20.operators.SpatialOperator

Bases: NonIdOperator

Abstract base class, as defined by FES spec.

class gisserver.parsers.fes20.operators.SpatialOperatorName(*values)

Bases: TagNameEnum

XML tag names mapped to geometry operators.

The values correspond with GeoDjango operators. So a BBOX query will translate into geometry__intersects=Polygon(...).

BBOX = 'intersects'
Contains = 'contains'
Crosses = 'crosses'
Disjoint = 'disjoint'
Equals = 'equals'
Intersects = 'intersects'
Overlaps = 'overlaps'
Touches = 'touches'
Within = 'within'
gisserver.parsers.fes20.operators.TemporalOperand

Define the types that a <gml:TemporalOperand> can be:

alias of TM_Object | ValueReference

class gisserver.parsers.fes20.operators.TemporalOperator(operatorType: TemporalOperatorName, operand1: ValueReference, operand2: TM_Object | ValueReference, _source: str | None = None)

Bases: NonIdOperator

Comparisons with dates.

For these operators, only the parsing is implemented. These are not translated into ORM queries yet.

It supports a syntax such as:

<fes:TEquals>
   <fes:ValueReference>SimpleTrajectory/gml:validTime/gml:TimeInstant</fes:ValueReference>
   <gml:TimeInstant gml:id="TI1">
      <gml:timePosition>2005-05-19T09:28:40Z</gml:timePosition>
   </gml:TimeInstant>
</fes:TEquals>

or:

<fes:During>
   <fes:ValueReference>SimpleTrajectory/gml:validTime/gml:TimeInstant</fes:ValueReference>
   <gml:TimePeriod gml:id="TP1">
      <gml:begin>
         <gml:TimeInstant gml:id="TI1">
            <gml:timePosition>2005-05-17T00:00:00Z</gml:timePosition>
         </gml:TimeInstant>
      </gml:begin>
      <gml:end>
         <gml:TimeInstant gml:id="TI2">
            <gml:timePosition>2005-05-23T00:00:00Z</gml:timePosition>
         </gml:TimeInstant>
      </gml:end>
   </gml:TimePeriod>
</fes:During>
__init__(operatorType: TemporalOperatorName, operand1: ValueReference, operand2: TM_Object | ValueReference, _source: str | None = None) None
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.

operand1: ValueReference
operand2: TM_Object | ValueReference
operatorType: TemporalOperatorName
class gisserver.parsers.fes20.operators.TemporalOperatorName(*values)

Bases: TagNameEnum

XML tag names mapped to datetime operators.

Explanation here: http://old.geotools.org/Temporal-Filters_211091519.html and: https://github.com/geotools/geotools/wiki/temporal-filters

After = 'after'
AnyInteracts = 'anyinteracts'
Before = 'before'
Begins = 'begins'
BegunBy = 'begunby'
During = 'during'
EndedBy = 'endedby'
Meets = 'meets'
MetBy = 'metby'
OverlappedBy = 'overlappedby'
TContains = 'tcontains'
TEquals = 'tequals'
TOverlaps = 'toverlaps'
class gisserver.parsers.fes20.operators.UnaryLogicOperator(operands: NonIdOperator, operatorType: UnaryLogicType, _source: str | None = None)

Bases: LogicalOperator

Apply a NOT operator.

This parses and handles the syntax:

<fes:Not>
    <fes:PropertyIsNil>
        <fes:ValueReference>city/name</fes:ValueReference>
    </fes:PropertyIsNil>
</fes:Not>
__init__(operands: NonIdOperator, operatorType: UnaryLogicType, _source: str | None = None) None
build_query(compiler: CompiledQuery) Q

Apply the NOT operation to the Q-object

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.

operands: NonIdOperator
operatorType: UnaryLogicType
class gisserver.parsers.fes20.operators.UnaryLogicType(*values)

Bases: TagNameEnum

XML tag names for the UnaryLogicOperator.

Not = <built-in function inv>

Sorting

The FES elements that handle sorting.

class gisserver.parsers.fes20.sorting.SortBy(sort_properties: list[SortProperty])

Bases: AstNode

The sortBy clause.

This parses and handles the syntax:

<fes:SortBy>
    <fes:SortProperty>
        <fes:ValueReference>name</fes:ValueReference>
        <fes:SortOrder>ASC</fes:SortOrder>
    </fes:SortProperty>
</fes:SortBy>

It also supports the SORTBY parameter for GET requests.

__init__(sort_properties: list[SortProperty]) None
as_kvp() str

Translate the POST request into KVP GET parameters. This is needed for pagination.

build_ordering(compiler: CompiledQuery)

Build the ordering for the Django ORM call.

classmethod from_kvp_request(kvp: KVPRequest) SortBy | None

Construct the SortBy object from a KVP “SORTBY” parameter, and considering NAMESPACES.

classmethod from_xml(element: NSElement) SortBy

Parse the XML tag.

sort_properties: list[SortProperty]

The <fes:SortProperty> elements.

class gisserver.parsers.fes20.sorting.SortOrder(*values)

Bases: Enum

A = ''

WFS 1 name that clients still use for ascending.

ASC = ''

Ascending order

D = '-'

WFS 1 name that clients still use for descending.

DESC = '-'

Descrending order

classmethod from_string(direction)
classmethod from_xml(element: NSElement)
class gisserver.parsers.fes20.sorting.SortProperty(value_reference: ValueReference, sort_order: SortOrder = SortOrder.ASC)

Bases: AstNode

This class name is based on the WFS spec.

This parses and handles the syntax:

<fes:SortProperty>
    <fes:ValueReference>name</fes:ValueReference>
    <fes:SortOrder>ASC</fes:SortOrder>
</fes:SortProperty>
__init__(value_reference: ValueReference, sort_order: SortOrder = SortOrder.ASC) None
as_kvp()

Translate the POST request into KVP GET parameters. This is needed for pagination.

classmethod from_string(value: str, ns_aliases: dict[str, str]) SortProperty

Parse the incoming GET parameter.

classmethod from_xml(element: NSElement) SortProperty

Parse the incoming XML

sort_order: SortOrder = ''
value_reference: ValueReference

Identifiers

These classes map to the FES 2.0 specification for identifiers. The class names are identical to those in the FES spec.

Inheritance structure:

class gisserver.parsers.fes20.identifiers.Id

Bases: AstNode

Abstract base class, as defined by FES spec. Any custom identifier-element needs to extend from this node. By default, the ResourceId element is supported.

build_query(compiler) Q
get_type_name()
xml_ns: xmlns | str | None = 'http://www.opengis.net/fes/2.0'

Default namespace of the element and subclasses, if not given by @tag_registry.register().

class gisserver.parsers.fes20.identifiers.ResourceId(rid: str, type_name: str | None, version: int | datetime | VersionActionTokens | None = None, startTime: datetime | None = None, endTime: datetime | None = None)

Bases: Id

The <fes:ResourceId> element. This element allow queries to retrieve a resource by their identifier.

This parses the syntax:

<fes:ResourceId rid="typename.123" />

This element is placed inside a Filter.

__init__(rid: str, type_name: str | None, version: int | datetime | VersionActionTokens | None = None, startTime: datetime | None = None, endTime: datetime | None = None) None
build_query(compiler) Q

Render the SQL filter

endTime: datetime | None = None
classmethod from_string(rid, ns_aliases: dict[str, str])
classmethod from_xml(element)

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.

get_type_name()

Implemented/override to expose the inferred type name.

rid: str

A raw “resource identifier”. It typically includes the object name, which is completely unrelated to XML namespacing.

startTime: datetime | None = None
type_name: str | None

Internal extra attribute, referencing the inferred typename from the rid.

version: int | datetime | VersionActionTokens | None = None

Unused, this is part of additional conformance classes.

class gisserver.parsers.fes20.identifiers.VersionActionTokens(*values)

Bases: Enum

Values for the ‘version’ attribute of the ResourceId node.

ALL = 'ALL'
FIRST = 'FIRST'
LAST = 'LAST'
NEXT = 'NEXT'
PREVIOUS = 'PREVIOUS'

Extra ORM lookups

Additional ORM lookups used by the fes-filter code.

class gisserver.parsers.fes20.lookups.FesArrayAnyNotEqual(*args, **kwargs)

Bases: Lookup

Inequality test for a single item in the array

as_sql(compiler, connection)

Generate the required SQL.

class gisserver.parsers.fes20.lookups.FesArrayLike(*args, **kwargs)

Bases: FesLike

Allow like lookups for array fields.

as_sql(compiler, connection)

Generate the required SQL.

class gisserver.parsers.fes20.lookups.FesBeyondLookup(*args, **kwargs)

Bases: DWithinLookup

Allow fieldname__fes_beyond=... lookups in querysets.

Based on the FES 2.0.3 corrigendum:

  • DWithin(A,B,d) = Distance(A,B) < d

  • Beyond(A,B,d) = Distance(A,B) > d

See: https://docs.opengeospatial.org/is/09-026r2/09-026r2.html#61

class gisserver.parsers.fes20.lookups.FesLike(*args, **kwargs)

Bases: Lookup

Allow fieldname__fes_like=... lookups in querysets.

as_sql(compiler, connection)

Generate the required SQL.

get_db_prep_lookup(value, connection)

This expects that the right-hand-side already has wildcard characters.

class gisserver.parsers.fes20.lookups.FesNotEqual(*args, **kwargs)

Bases: Lookup

Allow fieldname__fes_notequal=... lookups in querysets.

as_sql(compiler, connection)

Generate the required SQL.