diff --git a/owslib/feature/schema.py b/owslib/feature/schema.py
index 403642bf..c862e194 100644
--- a/owslib/feature/schema.py
+++ b/owslib/feature/schema.py
@@ -54,6 +54,7 @@ def get_schema(
type_element = root.find("./{%s}element" % XS_NAMESPACE)
if type_element is None:
return None
+
complex_type = type_element.attrib["type"].split(":")[1]
elements = _get_elements(complex_type, root)
nsmap = None
@@ -78,16 +79,45 @@ def _get_elements(complex_type, root):
return found_elements
+def _get_datatype(element, schema_key, gml_key):
+ """Extract the data type from an element based on different XML structure variants.
+
+ :param element: The XML element to extract the data type from
+ :param str schema_key: The XML namespace key for schema elements
+ :param str gml_key: The XML namespace key for GML elements
+ :return: The extracted data type as string
+ """
+ # Case 1: Type defined as attribute
+ if "type" in element.attrib:
+ data_type = element.attrib["type"]
+ # Remove any namespace prefix
+ if ":" in data_type:
+ data_type = data_type.split(":")[-1]
+ return data_type
+ # Case 2: Reference to another element
+ elif "ref" in element.attrib:
+ return element.attrib["ref"].split(":")[-1]
+ # Case 3: Type defined as SimpleType with Restriction
+ simple_type = element.find(".//{%s}restriction" % XS_NAMESPACE)
+ if simple_type is not None:
+ return simple_type.attrib.get("base", "").replace(schema_key + ":", "")
+ # Case 4: Complex Type Definition
+ complex_type = element.find(".//{%s}complexType//{%s}element" % (XS_NAMESPACE, XS_NAMESPACE))
+ if complex_type is not None and "type" in complex_type.attrib:
+ return complex_type.attrib["type"].replace(schema_key + ":", "")
+ return None
+
+
def _construct_schema(elements, nsmap):
- """Consruct fiona schema based on given elements
+ """Construct fiona schema based on given elements
:param list Element: list of elements
:param dict nsmap: namespace map
-
:return dict: schema
"""
if elements is None:
return None
+
schema = {"properties": {}, "required": [], "geometry": None}
schema_key = None
@@ -123,10 +153,16 @@ def _construct_schema(elements, nsmap):
}
for element in elements:
- data_type = element.attrib["type"].replace(gml_key + ":", "")
+ if "name" not in element.attrib:
+ continue
+
name = element.attrib["name"]
non_nillable = element.attrib.get("nillable", "false") == "false"
+ data_type = _get_datatype(element, schema_key, gml_key)
+ if data_type is None:
+ continue
+
if data_type in mappings:
schema["geometry"] = mappings[data_type]
schema["geometry_column"] = name
diff --git a/tests/resources/wfs_koeln_arcgis_describefeaturetype_110.xml b/tests/resources/wfs_koeln_arcgis_describefeaturetype_110.xml
new file mode 100644
index 00000000..11046540
--- /dev/null
+++ b/tests/resources/wfs_koeln_arcgis_describefeaturetype_110.xml
@@ -0,0 +1,177 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/resources/wfs_koeln_arcgis_describefeaturetype_200.xml b/tests/resources/wfs_koeln_arcgis_describefeaturetype_200.xml
new file mode 100644
index 00000000..55b6ac5a
--- /dev/null
+++ b/tests/resources/wfs_koeln_arcgis_describefeaturetype_200.xml
@@ -0,0 +1,177 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/resources/wfs_koeln_arcgis_getcapabilities_110.xml b/tests/resources/wfs_koeln_arcgis_getcapabilities_110.xml
new file mode 100644
index 00000000..44bd0450
--- /dev/null
+++ b/tests/resources/wfs_koeln_arcgis_getcapabilities_110.xml
@@ -0,0 +1,1256 @@
+
+
+
+ Adressen je Stadtteil
+
+
+ ESRI(LongLat)
+
+ WFS
+ 1.1.0
+
+
+
+
+ Stadt Köln - Amt für Stadtentwicklung und Statistik
+
+ Raumbezugssystem
+
+
+
+
+
+
+
+ Willy-Brandt-Platz 2
+ Köln
+
+ 50679
+ Deutschland
+ statistik-rbs@stadt-koeln.de
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.1.0
+
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+
+
+
+
+
+
+
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+
+
+
+
+
+
+
+
+ results
+ hits
+
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+
+
+
+ Query
+
+
+ adressen_stadtteil:Altstadt_Nord
+ Altstadt_Nord
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Altstadt_Süd
+ Altstadt_Süd
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Bayenthal
+ Bayenthal
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Bickendorf
+ Bickendorf
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Bilderstöckchen
+ Bilderstöckchen
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Blumenberg
+ Blumenberg
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Bocklemünd_Mengenich
+ Bocklemünd_Mengenich
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Braunsfeld
+ Braunsfeld
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Brück
+ Brück
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Buchforst
+ Buchforst
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Buchheim
+ Buchheim
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Chorweiler
+ Chorweiler
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Dellbrück
+ Dellbrück
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Deutz
+ Deutz
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Dünnwald
+ Dünnwald
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Ehrenfeld
+ Ehrenfeld
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Eil
+ Eil
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Elsdorf
+ Elsdorf
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Ensen
+ Ensen
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Esch_Auweiler
+ Esch_Auweiler
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Finkenberg
+ Finkenberg
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Flittard
+ Flittard
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Fühlingen
+ Fühlingen
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Godorf
+ Godorf
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Gremberghoven
+ Gremberghoven
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Grengel
+ Grengel
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Hahnwald
+ Hahnwald
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Heimersdorf
+ Heimersdorf
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Höhenberg
+ Höhenberg
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Höhenhaus
+ Höhenhaus
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Holweide
+ Holweide
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Humboldt_Gremberg
+ Humboldt_Gremberg
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Immendorf
+ Immendorf
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Junkersdorf
+ Junkersdorf
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Kalk
+ Kalk
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Klettenberg
+ Klettenberg
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Langel
+ Langel
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Libur
+ Libur
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Lind
+ Lind
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Lindenthal
+ Lindenthal
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Lindweiler
+ Lindweiler
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Longerich
+ Longerich
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Lövenich
+ Lövenich
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Marienburg
+ Marienburg
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Mauenheim
+ Mauenheim
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Merheim
+ Merheim
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Merkenich
+ Merkenich
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Meschenich
+ Meschenich
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Mülheim
+ Mülheim
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Müngersdorf
+ Müngersdorf
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Neubrück
+ Neubrück
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Neuehrenfeld
+ Neuehrenfeld
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Neustadt_Nord
+ Neustadt_Nord
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Neustadt_Süd
+ Neustadt_Süd
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Niehl
+ Niehl
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Nippes
+ Nippes
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Ossendorf
+ Ossendorf
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Ostheim
+ Ostheim
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Pesch
+ Pesch
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Poll
+ Poll
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Porz
+ Porz
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Raderberg
+ Raderberg
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Raderthal
+ Raderthal
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Rath_Heumar
+ Rath_Heumar
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Riehl
+ Riehl
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Rodenkirchen
+ Rodenkirchen
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Roggendorf_Thenhoven
+ Roggendorf_Thenhoven
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Rondorf
+ Rondorf
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Seeberg
+ Seeberg
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Stammheim
+ Stammheim
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Sülz
+ Sülz
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Sürth
+ Sürth
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Urbach
+ Urbach
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Vingst
+ Vingst
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Vogelsang
+ Vogelsang
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Volkhoven_Weiler
+ Volkhoven_Weiler
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Wahn
+ Wahn
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Wahnheide
+ Wahnheide
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Weiden
+ Weiden
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Weidenpesch
+ Weidenpesch
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Weiß
+ Weiß
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Westhoven
+ Westhoven
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Widdersdorf
+ Widdersdorf
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Worringen
+ Worringen
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Zollstock
+ Zollstock
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Zündorf
+ Zündorf
+ urn:ogc:def:crs:EPSG::25832
+
+ GML3
+ text/xml; subtype=gml/3.1.1
+
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+
+
+
+ gml:Envelope
+ gml:Point
+ gml:Polygon
+ gml:LineString
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ EqualTo
+ NotEqualTo
+ LessThan
+ GreaterThan
+ LessThanEqualTo
+ GreaterThanEqualTo
+ Like
+ Between
+ NullCheck
+
+
+
+
+
+
+
+
diff --git a/tests/resources/wfs_koeln_arcgis_getcapabilities_200.xml b/tests/resources/wfs_koeln_arcgis_getcapabilities_200.xml
new file mode 100644
index 00000000..820822cf
--- /dev/null
+++ b/tests/resources/wfs_koeln_arcgis_getcapabilities_200.xml
@@ -0,0 +1,1022 @@
+
+
+
+ WFS
+
+
+ ESRI(LongLat)
+
+ WFS
+ 2.0.0
+
+
+
+
+ Stadt Köln - Amt für Stadtentwicklung und Statistik
+
+ Raumbezugssystem
+
+
+
+
+
+
+
+ Willy-Brandt-Platz 2
+ Köln
+
+ 50679
+ Deutschland
+ statistik-rbs@stadt-koeln.de
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.0.0
+ 1.1.0
+ 2.0.0
+
+
+
+
+
+
+
+
+
+
+
+
+ text/xml; subtype=gml/3.2
+
+
+
+
+
+
+
+
+
+
+
+
+ none
+ local
+
+
+
+
+
+
+
+
+
+
+
+
+ results
+ hits
+
+
+
+
+ GML32
+ GML32+ZIP
+ GML32+GZIP
+ application/gml+xml; version=3.2
+ GML3
+ GML3+ZIP
+ GML3+GZIP
+ text/xml; subtype=gml/3.1.1
+ GML2
+ GML2+ZIP
+ GML2+GZIP
+ text/xml; subtype=gml/2.1.2
+ GEOJSON
+ GEOJSON+ZIP
+ GEOJSON+GZIP
+ ESRIGEOJSON
+ ESRIGEOJSON+ZIP
+ ESRIGEOJSON+GZIP
+ KML
+ application/vnd.google-earth.kml xml
+ application/vnd.google-earth.kml+xml
+ KMZ
+ application/vnd.google-earth.kmz
+ SHAPE+ZIP
+ CSV
+ CSV+ZIP
+ CSV+GZIP
+ Geopackage
+ Geopackage+ZIP
+
+
+
+
+ none
+ local
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TRUE
+ FALSE
+ FALSE
+ TRUE
+ TRUE
+ FALSE
+ FALSE
+ FALSE
+ TRUE
+ FALSE
+ FALSE
+ FALSE
+ FALSE
+ FALSE
+
+
+
+ adressen_stadtteil:Altstadt_Nord
+ Altstadt_Nord
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Altstadt_Süd
+ Altstadt_Süd
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Bayenthal
+ Bayenthal
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Bickendorf
+ Bickendorf
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Bilderstöckchen
+ Bilderstöckchen
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Blumenberg
+ Blumenberg
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Bocklemünd_Mengenich
+ Bocklemünd_Mengenich
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Braunsfeld
+ Braunsfeld
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Brück
+ Brück
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Buchforst
+ Buchforst
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Buchheim
+ Buchheim
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Chorweiler
+ Chorweiler
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Dellbrück
+ Dellbrück
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Deutz
+ Deutz
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Dünnwald
+ Dünnwald
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Ehrenfeld
+ Ehrenfeld
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Eil
+ Eil
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Elsdorf
+ Elsdorf
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Ensen
+ Ensen
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Esch_Auweiler
+ Esch_Auweiler
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Finkenberg
+ Finkenberg
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Flittard
+ Flittard
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Fühlingen
+ Fühlingen
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Godorf
+ Godorf
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Gremberghoven
+ Gremberghoven
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Grengel
+ Grengel
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Hahnwald
+ Hahnwald
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Heimersdorf
+ Heimersdorf
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Höhenberg
+ Höhenberg
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Höhenhaus
+ Höhenhaus
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Holweide
+ Holweide
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Humboldt_Gremberg
+ Humboldt_Gremberg
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Immendorf
+ Immendorf
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Junkersdorf
+ Junkersdorf
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Kalk
+ Kalk
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Klettenberg
+ Klettenberg
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Langel
+ Langel
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Libur
+ Libur
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Lind
+ Lind
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Lindenthal
+ Lindenthal
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Lindweiler
+ Lindweiler
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Longerich
+ Longerich
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Lövenich
+ Lövenich
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Marienburg
+ Marienburg
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Mauenheim
+ Mauenheim
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Merheim
+ Merheim
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Merkenich
+ Merkenich
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Meschenich
+ Meschenich
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Mülheim
+ Mülheim
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Müngersdorf
+ Müngersdorf
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Neubrück
+ Neubrück
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Neuehrenfeld
+ Neuehrenfeld
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Neustadt_Nord
+ Neustadt_Nord
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Neustadt_Süd
+ Neustadt_Süd
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Niehl
+ Niehl
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Nippes
+ Nippes
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Ossendorf
+ Ossendorf
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Ostheim
+ Ostheim
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Pesch
+ Pesch
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Poll
+ Poll
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Porz
+ Porz
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Raderberg
+ Raderberg
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Raderthal
+ Raderthal
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Rath_Heumar
+ Rath_Heumar
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Riehl
+ Riehl
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Rodenkirchen
+ Rodenkirchen
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Roggendorf_Thenhoven
+ Roggendorf_Thenhoven
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Rondorf
+ Rondorf
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Seeberg
+ Seeberg
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Stammheim
+ Stammheim
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Sülz
+ Sülz
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Sürth
+ Sürth
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Urbach
+ Urbach
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Vingst
+ Vingst
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Vogelsang
+ Vogelsang
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Volkhoven_Weiler
+ Volkhoven_Weiler
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Wahn
+ Wahn
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Wahnheide
+ Wahnheide
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Weiden
+ Weiden
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Weidenpesch
+ Weidenpesch
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Weiß
+ Weiß
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Westhoven
+ Westhoven
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Widdersdorf
+ Widdersdorf
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Worringen
+ Worringen
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Zollstock
+ Zollstock
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+ adressen_stadtteil:Zündorf
+ Zündorf
+ urn:ogc:def:crs:EPSG::25832
+
+ 6.80534263 50.83164204
+ 7.13337013 51.08846294
+
+
+
+
+
+ TRUE
+ TRUE
+ TRUE
+ TRUE
+ TRUE
+ TRUE
+ TRUE
+ TRUE
+ FALSE
+ FALSE
+ FALSE
+ TRUE
+ FALSE
+ TRUE
+ FALSE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/test_wfs_schema.py b/tests/test_wfs_schema.py
index a6c9feef..e0ccfd5d 100644
--- a/tests/test_wfs_schema.py
+++ b/tests/test_wfs_schema.py
@@ -82,6 +82,9 @@ def __remote_describefeaturetype(*args, **kwargs):
__remote_describefeaturetype)
+
+
+
class TestOnline(object):
"""Class grouping online tests for the WFS get_schema method."""
@pytest.mark.xfail
@@ -173,3 +176,177 @@ def test_get_schema_typename_eq_attribute(
"""
wfs110 = WebFeatureService(WFS_SERVICE_URL, version='1.1.0')
schema = wfs110.get_schema('gw_varia:hhz')
+
+ def test_get_datatype_geometry(self):
+ """Test the _get_datatype helper function with geometry types."""
+ from owslib.feature.schema import _get_datatype, XS_NAMESPACE
+ from owslib.etree import etree
+
+ ns = {
+ 'xs': XS_NAMESPACE,
+ 'gml': 'http://www.opengis.net/gml',
+ 'xsd': 'http://www.w3.org/2001/XMLSchema'
+ }
+
+ # Test geometry type
+ # XML:
+ element = etree.Element('{%s}element' % XS_NAMESPACE,
+ attrib={'name': 'field1', 'type': 'gml:PointPropertyType'},
+ nsmap=ns)
+ assert _get_datatype(element, "xsd", "gml") == "PointPropertyType"
+
+ def test_get_datatype_reference(self):
+ """Test the _get_datatype helper function with element references."""
+ from owslib.feature.schema import _get_datatype, XS_NAMESPACE
+ from owslib.etree import etree
+
+ ns = {
+ 'xs': XS_NAMESPACE,
+ 'gml': 'http://www.opengis.net/gml',
+ 'xsd': 'http://www.w3.org/2001/XMLSchema'
+ }
+
+ # Test element reference
+ # XML:
+ element = etree.Element('{%s}element' % XS_NAMESPACE,
+ attrib={'name': 'field2', 'ref': 'gml:polygonProperty'},
+ nsmap=ns)
+ assert _get_datatype(element, "xsd", "gml") == "polygonProperty"
+
+ @pytest.mark.parametrize("data_type", [
+ "xsd:boolean",
+ "xsd:date",
+ "xsd:dateTime",
+ "xsd:double",
+ "xsd:float",
+ "xsd:integer",
+ "xsd:int",
+ "xsd:string",
+ ])
+ def test_get_datatype_simple_types(self, data_type):
+ """Test the _get_datatype helper function with different simple types.
+
+ Parameters
+ ----------
+ data_type : str
+ The XML Schema data type to test
+ """
+ from owslib.feature.schema import _get_datatype, XS_NAMESPACE
+ from owslib.etree import etree
+
+ ns = {
+ 'xs': XS_NAMESPACE,
+ 'gml': 'http://www.opengis.net/gml',
+ 'xsd': 'http://www.w3.org/2001/XMLSchema'
+ }
+
+ # Test simple type with restriction
+ # XML:
+ #
+ #
+ #
+ #
+ #
+ element = etree.Element('{%s}element' % XS_NAMESPACE, attrib={'name': 'field3'}, nsmap=ns)
+ simple_type = etree.SubElement(element, '{%s}simpleType' % XS_NAMESPACE)
+ restriction = etree.SubElement(simple_type, '{%s}restriction' % XS_NAMESPACE,
+ attrib={'base': data_type})
+ expected_type = data_type.split(":")[-1]
+ assert _get_datatype(element, "xsd", "gml") == expected_type
+
+ @pytest.mark.parametrize("data_type", [
+ "xsd:boolean",
+ "xsd:date",
+ "xsd:dateTime",
+ "xsd:double",
+ "xsd:float",
+ "xsd:integer",
+ "xsd:int",
+ "xsd:string",
+ ])
+ def test_get_datatype_direct_types(self, data_type):
+ """Test the _get_datatype helper function with direct type attributes.
+
+ Parameters
+ ----------
+ data_type : str
+ The XML Schema data type to test
+ """
+ from owslib.feature.schema import _get_datatype, XS_NAMESPACE
+ from owslib.etree import etree
+
+ ns = {
+ 'xs': XS_NAMESPACE,
+ 'gml': 'http://www.opengis.net/gml',
+ 'xsd': 'http://www.w3.org/2001/XMLSchema'
+ }
+
+ # Test direct type attribute
+ # XML:
+ element = etree.Element('{%s}element' % XS_NAMESPACE,
+ attrib={'name': 'field1', 'type': data_type},
+ nsmap=ns)
+ expected_type = data_type.split(":")[-1]
+ assert _get_datatype(element, "xsd", "gml") == expected_type
+
+ @pytest.mark.parametrize("data_type", [
+ "xsd:boolean",
+ "xsd:date",
+ "xsd:dateTime",
+ "xsd:double",
+ "xsd:float",
+ "xsd:integer",
+ "xsd:int",
+ "xsd:string",
+ ])
+ def test_get_datatype_complex_types(self, data_type):
+ """Test the _get_datatype helper function with complex type definitions.
+
+ Parameters
+ ----------
+ data_type : str
+ The XML Schema data type to test
+ """
+ from owslib.feature.schema import _get_datatype, XS_NAMESPACE
+ from owslib.etree import etree
+
+ ns = {
+ 'xs': XS_NAMESPACE,
+ 'gml': 'http://www.opengis.net/gml',
+ 'xsd': 'http://www.w3.org/2001/XMLSchema'
+ }
+
+ # Test complex type
+ # XML:
+ #
+ #
+ #
+ #
+ #
+ #
+ #
+ element = etree.Element('{%s}element' % XS_NAMESPACE, attrib={'name': 'field4'}, nsmap=ns)
+ complex_type = etree.SubElement(element, '{%s}complexType' % XS_NAMESPACE)
+ sequence = etree.SubElement(complex_type, '{%s}sequence' % XS_NAMESPACE)
+ sub_element = etree.SubElement(sequence, '{%s}element' % XS_NAMESPACE,
+ attrib={'type': data_type})
+ expected_type = data_type.split(":")[-1]
+ assert _get_datatype(element, "xsd", "gml") == expected_type
+
+
+
+ def test_get_datatype_unknown(self):
+ """Test the _get_datatype helper function with unknown structure."""
+ from owslib.feature.schema import _get_datatype, XS_NAMESPACE
+ from owslib.etree import etree
+
+ ns = {
+ 'xs': XS_NAMESPACE,
+ 'gml': 'http://www.opengis.net/gml',
+ 'xsd': 'http://www.w3.org/2001/XMLSchema'
+ }
+
+ # Test unknown structure
+ # XML:
+ element = etree.Element('{%s}element' % XS_NAMESPACE, attrib={'name': 'field5'}, nsmap=ns)
+ assert _get_datatype(element, "xsd", "gml") is None
diff --git a/tests/test_wfs_schema_arcgis_server.py b/tests/test_wfs_schema_arcgis_server.py
new file mode 100644
index 00000000..be75c768
--- /dev/null
+++ b/tests/test_wfs_schema_arcgis_server.py
@@ -0,0 +1,154 @@
+import pytest
+
+import owslib
+from owslib.etree import etree
+from owslib.wfs import WebFeatureService
+from tests.utils import service_ok
+
+WFS_SERVICE_URL = 'https://geoportal.stadt-koeln.de/arcgis/services/basiskarten/adressen_stadtteil/MapServer/WFSServer?SERVICE=WFS&request=GetCapabilities'
+
+
+@pytest.fixture
+def mp_wfs_110(monkeypatch):
+ """Monkeypatch the call to the remote GetCapabilities request of WFS
+ version 1.1.0.
+
+ Parameters
+ ----------
+ monkeypatch : pytest.fixture
+ PyTest monkeypatch fixture.
+ """
+ def read(*args, **kwargs):
+ with open('tests/resources/wfs_koeln_arcgis_getcapabilities_110.xml', 'r') as f:
+ data = f.read()
+ if type(data) is not bytes:
+ data = data.encode('utf-8')
+ data = etree.fromstring(data)
+ return data
+
+ monkeypatch.setattr(
+ owslib.feature.common.WFSCapabilitiesReader, 'read', read)
+
+
+@pytest.fixture
+def mp_wfs_200(monkeypatch):
+ """Monkeypatch the call to the remote GetCapabilities request of WFS
+ version 2.0.0.
+
+ Parameters
+ ----------
+ monkeypatch : pytest.fixture
+ PyTest monkeypatch fixture.
+ """
+ def read(*args, **kwargs):
+ with open('tests/resources/wfs_koeln_arcgis_getcapabilities_200.xml', 'r') as f:
+ data = f.read()
+ if type(data) is not bytes:
+ data = data.encode('utf-8')
+ data = etree.fromstring(data)
+ return data
+
+ monkeypatch.setattr(
+ owslib.feature.common.WFSCapabilitiesReader, 'read', read)
+
+
+@pytest.fixture()
+def mp_remote_describefeaturetype(monkeypatch):
+ """Monkeypatch the call to the remote DescribeFeatureType request.
+
+ Returns a standard DescribeFeatureType response.
+
+ Parameters
+ ----------
+ monkeypatch : pytest.fixture
+ PyTest monkeypatch fixture.
+ """
+ def __remote_describefeaturetype(*args, **kwargs):
+ with open('tests/resources/wfs_koeln_arcgis_describefeaturetype_110.xml', 'r') as f:
+ data = f.read()
+ if type(data) is not bytes:
+ data = data.encode('utf-8')
+ data = etree.fromstring(data)
+ return data
+
+ monkeypatch.setattr(owslib.feature.schema,
+ '_get_remote_describefeaturetype',
+ __remote_describefeaturetype)
+
+
+class TestOnline(object):
+ """Class grouping online tests for the WFS get_schema method."""
+
+ @pytest.mark.xfail
+ @pytest.mark.online
+ @pytest.mark.skipif(not service_ok(WFS_SERVICE_URL),
+ reason="WFS service is unreachable")
+ @pytest.mark.parametrize("wfs_version", ["1.1.0", "2.0.0"])
+ def test_get_schema(self, wfs_version):
+ """Test the get_schema method for a standard schema."""
+ wfs = WebFeatureService(WFS_SERVICE_URL, version=wfs_version)
+ schema = wfs.get_schema('adressen_stadtteil:Blumenberg')
+
+ @pytest.mark.xfail
+ @pytest.mark.online
+ @pytest.mark.skipif(not service_ok(WFS_SERVICE_URL),
+ reason="WFS service is unreachable")
+ @pytest.mark.parametrize("wfs_version", ["1.1.0", "2.0.0"])
+ def test_schema_result(self, wfs_version):
+ """Test whether the output from get_schema is a wellformed dictionary."""
+ wfs = WebFeatureService(WFS_SERVICE_URL, version=wfs_version)
+ schema = wfs.get_schema('adressen_stadtteil:Blumenberg')
+ assert isinstance(schema, dict)
+
+ assert 'properties' in schema or 'geometry' in schema
+
+ if 'geometry' in schema:
+ assert 'geometry_column' in schema
+
+ if 'properties' in schema:
+ assert isinstance(schema['properties'], dict)
+
+ assert 'required' in schema
+ assert isinstance(schema['required'], list)
+
+
+class TestOffline(object):
+ """Class grouping offline tests for the WFS get_schema method."""
+
+ def test_get_schema(self, mp_wfs_110, mp_remote_describefeaturetype):
+ """Test the get_schema method for a standard schema.
+
+ Parameters
+ ----------
+ mp_wfs_110 : pytest.fixture
+ Monkeypatch the call to the remote GetCapabilities request.
+ mp_remote_describefeaturetype : pytest.fixture
+ Monkeypatch the call to the remote DescribeFeatureType request.
+ """
+ wfs = WebFeatureService(WFS_SERVICE_URL, version='1.1.0')
+ schema = wfs.get_schema('adressen_stadtteil:Blumenberg')
+
+ def test_schema_result(self, mp_wfs_110, mp_remote_describefeaturetype):
+ """Test whether the output from get_schema is a wellformed dictionary.
+
+ Parameters
+ ----------
+ mp_wfs_110 : pytest.fixture
+ Monkeypatch the call to the remote GetCapabilities request.
+ mp_remote_describefeaturetype : pytest.fixture
+ Monkeypatch the call to the remote DescribeFeatureType request.
+ """
+ wfs = WebFeatureService(WFS_SERVICE_URL, version='1.1.0')
+ schema = wfs.get_schema('adressen_stadtteil:Blumenberg')
+ assert isinstance(schema, dict)
+
+ assert 'properties' in schema or 'geometry' in schema
+
+ if 'geometry' in schema:
+ assert 'geometry_column' in schema
+
+ if 'properties' in schema:
+ assert isinstance(schema['properties'], dict)
+
+ assert 'required' in schema
+ assert isinstance(schema['required'], list)
diff --git a/tests/utils.py b/tests/utils.py
index 56de5205..e52cf838 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -83,12 +83,13 @@ def sorted_url_query(url):
def service_ok(url, timeout=5):
try:
- resp = requests.head(url, allow_redirects=True, timeout=timeout)
+ resp = requests.get(url, allow_redirects=True, timeout=timeout, stream=True)
if 'html' in resp.headers.get('content-type', '').lower():
+ resp.close()
return False
- if not resp.ok: # if HEAD is not supported try GET with streaming
- resp = requests.get(url, timeout=timeout, stream=True)
- return resp.ok
+ ok = resp.ok
+ resp.close()
+ return ok
except requests.exceptions.ReadTimeout:
ok = False
except requests.exceptions.ConnectTimeout: