pygml package

Submodules

pygml.axisorder module

pygml.axisorder.get_crs_code(crs: str) Union[int, str]

Extract the CRS code from the given CRS identifier string, which can be one of:

  • EPSG:<EPSG code>

  • http://www.opengis.net/def/crs/EPSG/0/<EPSG code>

  • http://www.opengis.net/gml/srs/epsg.xml#<EPSG code>

  • urn:EPSG:geographicCRS:<epsg code>

  • urn:ogc:def:crs:EPSG::<EPSG code>

  • urn:ogc:def:crs:OGC::<EPSG code>

  • urn:ogc:def:crs:EPSG:<EPSG code>

Returns the code as an integer in case of EPSG code or as the string 'CRS84'.

>>> get_crs_code('EPSG:4326')
4326
>>> get_crs_code('urn:ogc:def:crs:OGC::CRS84')
'CRS84'
>>> get_crs_code('something')
Traceback (most recent call last):
    ...
ValueError: Failed to retrieve CRS code
pygml.axisorder.is_crs_yx(crs: str) bool

Determines whether the given CRS uses Y/X (or latitude/longitude) axis order.

>>> is_crs_yx('EPSG:4326')
True
>>> is_crs_yx('EPSG:3857')
False
>>> is_crs_yx('urn:ogc:def:crs:OGC::CRS84')
False

pygml.basics module

pygml.basics.parse_coordinates(value: str, cs: str = ',', ts: str = ' ', decimal: str = '.') List[Tuple[float, ...]]

Parses the the values of a gml:coordinates node to a list of lists of floats. Takes the coordinate separator and tuple separator into account, and also custom decimal separators.

>>> parse_coordinates('12.34 56.7,89.10 11.12')
[(12.34, 56.7), (89.1, 11.12)]
>>> parse_coordinates('12.34 56.7;89.10 11.12', cs=';')
[(12.34, 56.7), (89.1, 11.12)]
>>> parse_coordinates('12.34:56.7,89.10:11.12', ts=':')
[(12.34, 56.7), (89.1, 11.12)]
>>> parse_coordinates('12.34:56.7;89.10:11.12', cs=';', ts=':')
[(12.34, 56.7), (89.1, 11.12)]
>>> parse_coordinates(
...     '12,34:56,7;89,10:11,12', cs=';', ts=':', decimal=','
... )
[(12.34, 56.7), (89.1, 11.12)]
pygml.basics.parse_pos(value: str) Tuple[float, ...]

Parses a single gml:pos to a Coordinate structure.

>>> parse_pos('12.34 56.7')
(12.34, 56.7)
>>> parse_pos('12.34 56.7 89.10')
(12.34, 56.7, 89.1)
pygml.basics.parse_poslist(value: str, dimensions: int = 2) List[Tuple[float, ...]]

Parses the value of a single gml:posList to a Coordinates structure.

>>> parse_poslist('12.34 56.7 89.10 11.12')
[(12.34, 56.7), (89.1, 11.12)]
>>> parse_poslist('12.34 56.7 89.10 11.12 13.14 15.16', dimensions=3)
[(12.34, 56.7, 89.1), (11.12, 13.14, 15.16)]
>>> parse_poslist('12.34 56.7 89.10 11.12', dimensions=3)
Traceback (most recent call last):
    ...
ValueError: Invalid dimensionality of pos list
pygml.basics.swap_coordinate_xy(coordinate: Tuple[float, ...]) Tuple[float, ...]

Swaps the X and Y coordinates of a given coordinate

>>> swap_coordinate_xy((12.34, 56.7))
(56.7, 12.34)
>>> swap_coordinate_xy((12.34, 56.7, 89.10))
(56.7, 12.34, 89.1)
pygml.basics.swap_coordinates_xy(coordinates: List[Tuple[float, ...]]) List[Tuple[float, ...]]

Swaps the X and Y coordinates of a given coordinates list

>>> swap_coordinates_xy(
...     [(12.34, 56.7), (89.10, 11.12)]
... )
[(56.7, 12.34), (11.12, 89.1)]
>>> swap_coordinates_xy(
...     [(12.34, 56.7, 89.10), (11.12, 13.14, 15.16)]
... )
[(56.7, 12.34, 89.1), (13.14, 11.12, 15.16)]

pygml.dimensionality module

pygml.dimensionality.get_dimensionality(geometry: pygml.types.GeomDict) Optional[int]

Returns the dimensionality of a given GeoJSON geometry. This is obtained by descending into the first coordinate and using its length. When no coordinates can be retrieved (e.g: in case of GeometryCollections) None is returned.

>>> get_dimensionality({
...     'type': 'Polygon',
...     'coordinates': [
...         [
...             (0.5, 1.0),
...             (0.5, 2.0),
...             (1.5, 2.0),
...             (1.5, 1.0),
...             (0.5, 1.0)
...         ]
...     ]
... })
2
>>> get_dimensionality({
...     'type': 'MultiPoint',
...     'coordinates': [
...         (1.0, 1.0, 1.0),
...         (2.0, 2.0, 1.0),
...     ]
... })
3
>>> get_dimensionality({
...     'type': 'GeometryCollection',
...     'geometries': [
...         {
...             'type': 'Point',
...             'coordinates': (1.0, 1.0)
...         },
...         {
...             'type': 'Polygon',
...             'coordinates': [
...                 [(1.0, 1.0)],
...                 [(1.0, 1.0)],
...             ]
...         },
...     ]
... })

pygml.georss module

pygml.georss.encode_georss(geometry: pygml.types.GeomDict, gml_encoder: Callable[[pygml.types.GeomDict, str], lxml.etree._Element] = <function encode_pre_v32>) lxml.etree._Element

Encodes a GeoJSON geometry as a GeoRSS lxml.etree.Element. Tries to use the native GeoRSS elements point, line, or polygon when possible. Falls back to georss:where with using the gml_encoder function (defaulting to GML 3.2):

  • MultiPoint, MultiLineString, MultiPolygon geometries

  • Polygons with interiors

  • GeometryCollections

  • any geometry with CRS other than CRS84 or EPSG:4326

  • when dealing with >2D geometries

pygml.georss.parse_georss(element: lxml.etree._Element) pygml.types.GeomDict

Parses the GeoRSS basic elements to their respective GeoJSON representation. As all coordinates in GeoRSS are expressed in WGS84 and in Latitude/Longitude order, the coordinates are swapped to XY order.

In case of georss:where, it is expected that it contains a single GML element which is parsed as either GML 3.1.1, GML 3.2 or GML 3.3 CE.

pygml.parse module

pygml.parse.parse(source: Union[lxml.etree._Element, str]) pygml.types.Geometry

pygml.pre_v32 module

pygml.pre_v32.encode_pre_v32(geometry: pygml.types.GeomDict, identifier: Optional[str] = None) lxml.etree._Element

Encodes the given GeoJSON dict to its most simple GML 3 representation.

In preparation of the encoding, the coordinates may have to be swapped from XY order to YX order, depending on the used CRS. This includes the case when no CRS is specified, as this means the default WGS84 in GeoJSON, which in turn uses latitude/longitude ordering GML.

This function returns an lxml.etree._Element which can be altered or serialized.

>>> from pygml.pre_v32 import encode_pre_v32
>>> from lxml import etree
>>> tree = encode_pre_v32({
...     'type': 'Point',
...     'coordinates': (1.0, 1.0)
... }, 'ID')
>>> print(etree.tostring(tree, pretty_print=True).decode())
<gml:Point xmlns:gml="http://www.opengis.net/gml"
    srsName="urn:ogc:def:crs:OGC::CRS84" gml:id="ID">
  <gml:pos>1.0 1.0</gml:pos>
</gml:Point>
pygml.pre_v32.parse_pre_v32(element: lxml.etree._Element) pygml.types.GeomDict

Main parsing function for GML 3.0 and 3.1 XML structures.

The following XML tags can be parsed to their respective GeoJSON counterpart:

  • gml:Point -> Point

  • gml:MultiPoint -> MultiPoint

  • gml:LineString -> LineString

  • gml:MultiCurve (with only gml:LineString curve members) -> MultiLineString

  • gml:MultiLineString -> MultiLineString

  • gml:Polygon -> Polygon

  • gml:MultiPolygon -> MultiPolygon

  • gml:MultiSurface (with only gml:Polygon surface members) -> MultiPolygon

  • gml:MultiGeometry (with any of the aforementioned types as geometry members) -> GeometryCollection

The SRS of the geometry is determined and the coordinates are flipped to XY order in GeoJSON when they are in YX order in GML.

Returns:

the parsed GeoJSON geometry as a dict. Contains a ‘type’ field, a ‘coordinates’ field and potentially a ‘crs’ field when the geometries SRS could be determined. This field follows the structure laid out in the draft for GeoJSON.

pygml.types module

class pygml.types.GeomDict(*args, **kwargs)

Bases: dict

coordinates: Union[Tuple, List]
crs: Optional[dict]
type: str
class pygml.types.Geometry(geometry: pygml.types.GeomDict)

Bases: object

Simple container class to hold a geometry and expose it via the __geo_interface__ property

geometry: pygml.types.GeomDict

pygml.v32 module

pygml.v32.encode_v32(geometry: pygml.types.GeomDict, identifier: str) lxml.etree._Element

Encodes the given GeoJSON dict to its most simple GML 3.2 representation. As in GML 3.2 the gml:id attribute is mandatory, the identifier must be passed as well.

In preparation of the encoding, the coordinates may have to be swapped from XY order to YX order, depending on the used CRS. This includes the case when no CRS is specified, as this means the default WGS84 in GeoJSON, which in turn uses latitude/longitude ordering GML.

This function returns an lxml.etree._Element which can be altered or serialized.

>>> from pygml.v32 import encode_v32
>>> from lxml import etree
>>> tree = encode_v32({
...     'type': 'Point',
...     'coordinates': (1.0, 1.0)
... }, 'ID')
>>> print(etree.tostring(tree, pretty_print=True).decode())
<gml:Point xmlns:gml="http://www.opengis.net/gml/3.2"
    srsName="urn:ogc:def:crs:OGC::CRS84" gml:id="ID">
  <gml:pos>1.0 1.0</gml:pos>
</gml:Point>
pygml.v32.parse_v32(element: lxml.etree._Element) pygml.types.GeomDict

Main parsing function for GML 3.2 XML structures.

The following XML tags can be parsed to their respective GeoJSON counterpart:

  • gml:Point -> Point

  • gml:MultiPoint -> MultiPoint

  • gml:LineString -> LineString

  • gml:MultiCurve (with only gml:LineString curve members) -> MultiLineString

  • gml:Polygon -> Polygon

  • gml:MultiSurface (with only gml:Polygon surface members) -> MultiPolygon

  • gml:MultiGeometry (with any of the aforementioned types as geometry members) -> GeometryCollection

The SRS of the geometry is determined and the coordinates are flipped to XY order in GeoJSON when they are in YX order in GML.

Returns:

the parsed GeoJSON geometry as a dict. Contains a ‘type’ field, a ‘coordinates’ field and potentially a ‘crs’ field when the geometries SRS could be determined. This field follows the structure laid out in the draft for GeoJSON.

pygml.v33 module

class pygml.v33.GML33CEEncoder

Bases: pygml.v3_common.GML3Encoder

encode_polygon(coordinates: List[Tuple[float, ...]], attrs: dict) lxml.etree._Element
pygml.v33.encode_v33_ce(geometry: pygml.types.GeomDict, identifier: str) lxml.etree._Element

Encodes the given GeoJSON dict to its most simple GML 3.3 CE representation, with a fallback to encoding it GML 3.2 when the compact encoding is not possible. As in GML 3.2 the gml:id attribute is mandatory, the identifier must be passed as well.

In preparation of the encoding, the coordinates may have to be swapped from XY order to YX order, depending on the used CRS. This includes the case when no CRS is specified, as this means the default WGS84 in GeoJSON, which in turn uses latitude/longitude ordering GML.

This function returns an lxml.etree._Element which can be altered or serialized.

>>> from pygml.v33 import encode_v33_ce
>>> from lxml import etree
>>> tree = encode_v33_ce({
...     'type': 'Polygon',
...     'coordinates': [
...         [
...             (1.0, 2.0),
...             (1.0, 3.0),
...             (2.0, 2.0),
...             (1.0, 2.0),
...         ],
...     ],
... }, 'ID')
>>> print(etree.tostring(tree, pretty_print=True).decode())
<gmlce:SimpleTriangle xmlns:gmlce="http://www.opengis.net/gml/3.3/ce"
        xmlns:gml="http://www.opengis.net/gml/3.2"
        srsName="urn:ogc:def:crs:OGC::CRS84" gml:id="ID">
  <gml:posList>1.0 2.0 1.0 3.0 2.0 2.0</gml:posList>
</gmlce:SimpleTriangle>
pygml.v33.parse_simple_multi_point(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[pygml.types.GeomDict, str]
pygml.v33.parse_simple_polygon(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[pygml.types.GeomDict, str]
pygml.v33.parse_simple_triangle_or_rectangle(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[pygml.types.GeomDict, str]
pygml.v33.parse_v33_ce(element: lxml.etree._Element) pygml.types.GeomDict

Main parsing function for GML 3.3 CE XML structures.

The following XML tags can be parsed to their respective GeoJSON counterpart:

  • gmlce:SimpleTriangle -> Polygon

  • gmlce:SimpleRectangel -> Polygon

  • gmlce:SimplePolygon -> Polygon

  • TODO: gmlce:SimpleMultiPoint -> MultiPoint

  • gml:Point -> Point

  • gml:MultiPoint -> MultiPoint

  • gml:LineString -> LineString

  • gml:MultiCurve (with only gml:LineString curve members) -> MultiLineString

  • gml:Polygon -> Polygon

  • gml:MultiSurface (with only gml:Polygon surface members) -> MultiPolygon

  • gml:MultiGeometry (with any of the aforementioned types as geometry members) -> GeometryCollection

The SRS of the geometry is determined and the coordinates are flipped to XY order in GeoJSON when they are in YX order in GML.

Returns:

the parsed GeoJSON geometry as a dict. Contains a ‘type’ field, a ‘coordinates’ field and potentially a ‘crs’ field when the geometries SRS could be determined. This field follows the structure laid out in the draft for GeoJSON.

pygml.v3_common module

class pygml.v3_common.GML3Encoder(namespace: str, nsmap: Dict[str, str], id_required: bool)

Bases: object

encode(geometry: pygml.types.GeomDict, identifier: Optional[str] = None) lxml.etree._Element
encode_line_string(coordinates: List[Tuple[float, ...]], attrs: dict) lxml.etree._Element
encode_multi_line_string(coordinates: List[Tuple[float, ...]], identifier: str, attrs: dict) lxml.etree._Element
encode_multi_point(coordinates: List[Tuple[float, ...]], identifier: str, attrs: dict) lxml.etree._Element
encode_multi_polygon(coordinates: List[Tuple[float, ...]], identifier: str, attrs: dict) lxml.etree._Element
encode_point(coordinates: List[Tuple[float, ...]], attrs: dict) lxml.etree._Element
encode_polygon(coordinates: List[Tuple[float, ...]], attrs: dict) lxml.etree._Element
class pygml.v3_common.GML3Parser(namespaces: List[str], nsmap: Dict[str, str], handlers: Dict[str, Callable[[lxml.etree._Element, Dict[str, str]], Tuple[pygml.types.GeomDict, str]]])

Bases: object

parse(element: lxml.etree._Element) pygml.types.GeomDict
pygml.v3_common.determine_srs(*srss: List[Optional[str]]) Optional[str]
pygml.v3_common.maybe_swap_coordinates(geometry: pygml.types.GeomDict, srs: str) pygml.types.GeomDict
pygml.v3_common.parse_coord(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[float, ...]
pygml.v3_common.parse_envelope(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[pygml.types.GeomDict, str]
pygml.v3_common.parse_linestring_or_linear_ring(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[pygml.types.GeomDict, str]
pygml.v3_common.parse_multi_curve(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[pygml.types.GeomDict, str]
pygml.v3_common.parse_multi_geometry(element: lxml.etree._Element, nsmap: Dict[str, str], geometry_parser: Callable[[lxml.etree._Element], pygml.types.GeomDict]) Tuple[pygml.types.GeomDict, str]
pygml.v3_common.parse_multi_linestring(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[pygml.types.GeomDict, str]
pygml.v3_common.parse_multi_point(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[pygml.types.GeomDict, str]
pygml.v3_common.parse_multi_polygon(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[pygml.types.GeomDict, str]
pygml.v3_common.parse_multi_surface(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[pygml.types.GeomDict, str]
pygml.v3_common.parse_point(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[pygml.types.GeomDict, str]
pygml.v3_common.parse_polygon(element: lxml.etree._Element, nsmap: Dict[str, str]) Tuple[pygml.types.GeomDict, str]

Module contents

pygml.parse(source: Union[lxml.etree._Element, str]) pygml.types.Geometry