Skip to content

Commit 1d011de

Browse files
authored
Enhance datatype determination and improve service_ok util (#994)
* fix: update datatype determination for WFS attributes * fix: update service_ok util to support arcgis server * test: parametrize data_type tests
1 parent b839d69 commit 1d011de

8 files changed

+3007
-7
lines changed

owslib/feature/schema.py

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def get_schema(
5454
type_element = root.find("./{%s}element" % XS_NAMESPACE)
5555
if type_element is None:
5656
return None
57+
5758
complex_type = type_element.attrib["type"].split(":")[1]
5859
elements = _get_elements(complex_type, root)
5960
nsmap = None
@@ -78,16 +79,45 @@ def _get_elements(complex_type, root):
7879
return found_elements
7980

8081

82+
def _get_datatype(element, schema_key, gml_key):
83+
"""Extract the data type from an element based on different XML structure variants.
84+
85+
:param element: The XML element to extract the data type from
86+
:param str schema_key: The XML namespace key for schema elements
87+
:param str gml_key: The XML namespace key for GML elements
88+
:return: The extracted data type as string
89+
"""
90+
# Case 1: Type defined as attribute
91+
if "type" in element.attrib:
92+
data_type = element.attrib["type"]
93+
# Remove any namespace prefix
94+
if ":" in data_type:
95+
data_type = data_type.split(":")[-1]
96+
return data_type
97+
# Case 2: Reference to another element
98+
elif "ref" in element.attrib:
99+
return element.attrib["ref"].split(":")[-1]
100+
# Case 3: Type defined as SimpleType with Restriction
101+
simple_type = element.find(".//{%s}restriction" % XS_NAMESPACE)
102+
if simple_type is not None:
103+
return simple_type.attrib.get("base", "").replace(schema_key + ":", "")
104+
# Case 4: Complex Type Definition
105+
complex_type = element.find(".//{%s}complexType//{%s}element" % (XS_NAMESPACE, XS_NAMESPACE))
106+
if complex_type is not None and "type" in complex_type.attrib:
107+
return complex_type.attrib["type"].replace(schema_key + ":", "")
108+
return None
109+
110+
81111
def _construct_schema(elements, nsmap):
82-
"""Consruct fiona schema based on given elements
112+
"""Construct fiona schema based on given elements
83113
84114
:param list Element: list of elements
85115
:param dict nsmap: namespace map
86-
87116
:return dict: schema
88117
"""
89118
if elements is None:
90119
return None
120+
91121
schema = {"properties": {}, "required": [], "geometry": None}
92122

93123
schema_key = None
@@ -123,10 +153,16 @@ def _construct_schema(elements, nsmap):
123153
}
124154

125155
for element in elements:
126-
data_type = element.attrib["type"].replace(gml_key + ":", "")
156+
if "name" not in element.attrib:
157+
continue
158+
127159
name = element.attrib["name"]
128160
non_nillable = element.attrib.get("nillable", "false") == "false"
129161

162+
data_type = _get_datatype(element, schema_key, gml_key)
163+
if data_type is None:
164+
continue
165+
130166
if data_type in mappings:
131167
schema["geometry"] = mappings[data_type]
132168
schema["geometry_column"] = name
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xsd:schema xmlns:adressen_stadtteil="https://k00364:6443/arcgis/admin/services/adressen_stadtteil/MapServer/WFSServer" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" targetNamespace="https://k00364:6443/arcgis/admin/services/adressen_stadtteil/MapServer/WFSServer" elementFormDefault="qualified" attributeFormDefault="unqualified">
3+
<xsd:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/gml.xsd"/>
4+
<xsd:element name="Blumenberg" type="adressen_stadtteil:BlumenbergFeatureType" substitutionGroup="gml:_Feature"/>
5+
<xsd:complexType name="BlumenbergFeatureType">
6+
<xsd:complexContent>
7+
<xsd:extension base="gml:AbstractFeatureType">
8+
<xsd:sequence>
9+
<xsd:element minOccurs="0" maxOccurs="1" name="objectid" type="xsd:int"/>
10+
<xsd:element minOccurs="0" maxOccurs="1" name="Nummer">
11+
<xsd:simpleType>
12+
<xsd:restriction base="xsd:string">
13+
<xsd:maxLength value="11"/>
14+
</xsd:restriction>
15+
</xsd:simpleType>
16+
</xsd:element>
17+
<xsd:element minOccurs="0" maxOccurs="1" name="Adresse">
18+
<xsd:simpleType>
19+
<xsd:restriction base="xsd:string">
20+
<xsd:maxLength value="47"/>
21+
</xsd:restriction>
22+
</xsd:simpleType>
23+
</xsd:element>
24+
<xsd:element minOccurs="0" maxOccurs="1" name="Strassenschlüssel">
25+
<xsd:simpleType>
26+
<xsd:restriction base="xsd:string">
27+
<xsd:maxLength value="5"/>
28+
</xsd:restriction>
29+
</xsd:simpleType>
30+
</xsd:element>
31+
<xsd:element minOccurs="0" maxOccurs="1" name="Straße">
32+
<xsd:simpleType>
33+
<xsd:restriction base="xsd:string">
34+
<xsd:maxLength value="40"/>
35+
</xsd:restriction>
36+
</xsd:simpleType>
37+
</xsd:element>
38+
<xsd:element minOccurs="0" maxOccurs="1" name="Amtl._Straßenname">
39+
<xsd:simpleType>
40+
<xsd:restriction base="xsd:string">
41+
<xsd:maxLength value="100"/>
42+
</xsd:restriction>
43+
</xsd:simpleType>
44+
</xsd:element>
45+
<xsd:element minOccurs="0" maxOccurs="1" name="Straße__Stadtbezirk_">
46+
<xsd:simpleType>
47+
<xsd:restriction base="xsd:string">
48+
<xsd:maxLength value="100"/>
49+
</xsd:restriction>
50+
</xsd:simpleType>
51+
</xsd:element>
52+
<xsd:element minOccurs="0" maxOccurs="1" name="Hausnummer">
53+
<xsd:simpleType>
54+
<xsd:restriction base="xsd:string">
55+
<xsd:maxLength value="5"/>
56+
</xsd:restriction>
57+
</xsd:simpleType>
58+
</xsd:element>
59+
<xsd:element minOccurs="0" maxOccurs="1" name="Gebäude_ID_ALKIS">
60+
<xsd:simpleType>
61+
<xsd:restriction base="xsd:string">
62+
<xsd:maxLength value="16"/>
63+
</xsd:restriction>
64+
</xsd:simpleType>
65+
</xsd:element>
66+
<xsd:element minOccurs="0" maxOccurs="1" name="Nutzung__ALKIS_Gebäudefunktion_">
67+
<xsd:simpleType>
68+
<xsd:restriction base="xsd:string">
69+
<xsd:maxLength value="80"/>
70+
</xsd:restriction>
71+
</xsd:simpleType>
72+
</xsd:element>
73+
<xsd:element minOccurs="0" maxOccurs="1" name="Blockseite">
74+
<xsd:simpleType>
75+
<xsd:restriction base="xsd:string">
76+
<xsd:maxLength value="8"/>
77+
</xsd:restriction>
78+
</xsd:simpleType>
79+
</xsd:element>
80+
<xsd:element minOccurs="0" maxOccurs="1" name="Stadtviertel__Nr._">
81+
<xsd:simpleType>
82+
<xsd:restriction base="xsd:string">
83+
<xsd:maxLength value="5"/>
84+
</xsd:restriction>
85+
</xsd:simpleType>
86+
</xsd:element>
87+
<xsd:element minOccurs="0" maxOccurs="1" name="Stadtviertel">
88+
<xsd:simpleType>
89+
<xsd:restriction base="xsd:string">
90+
<xsd:maxLength value="40"/>
91+
</xsd:restriction>
92+
</xsd:simpleType>
93+
</xsd:element>
94+
<xsd:element minOccurs="0" maxOccurs="1" name="Statistisches_Quartier__Nr._">
95+
<xsd:simpleType>
96+
<xsd:restriction base="xsd:string">
97+
<xsd:maxLength value="9"/>
98+
</xsd:restriction>
99+
</xsd:simpleType>
100+
</xsd:element>
101+
<xsd:element minOccurs="0" maxOccurs="1" name="Statistisches_Quartier">
102+
<xsd:simpleType>
103+
<xsd:restriction base="xsd:string">
104+
<xsd:maxLength value="100"/>
105+
</xsd:restriction>
106+
</xsd:simpleType>
107+
</xsd:element>
108+
<xsd:element minOccurs="0" maxOccurs="1" name="Stadtteil__Nr._">
109+
<xsd:simpleType>
110+
<xsd:restriction base="xsd:string">
111+
<xsd:maxLength value="3"/>
112+
</xsd:restriction>
113+
</xsd:simpleType>
114+
</xsd:element>
115+
<xsd:element minOccurs="0" maxOccurs="1" name="Stadtteil">
116+
<xsd:simpleType>
117+
<xsd:restriction base="xsd:string">
118+
<xsd:maxLength value="40"/>
119+
</xsd:restriction>
120+
</xsd:simpleType>
121+
</xsd:element>
122+
<xsd:element minOccurs="0" maxOccurs="1" name="Stadtbezirk__Nr._">
123+
<xsd:simpleType>
124+
<xsd:restriction base="xsd:string">
125+
<xsd:maxLength value="1"/>
126+
</xsd:restriction>
127+
</xsd:simpleType>
128+
</xsd:element>
129+
<xsd:element minOccurs="0" maxOccurs="1" name="Stadtbezirk">
130+
<xsd:simpleType>
131+
<xsd:restriction base="xsd:string">
132+
<xsd:maxLength value="40"/>
133+
</xsd:restriction>
134+
</xsd:simpleType>
135+
</xsd:element>
136+
<xsd:element minOccurs="0" maxOccurs="1" name="Stimmbezirk">
137+
<xsd:simpleType>
138+
<xsd:restriction base="xsd:string">
139+
<xsd:maxLength value="5"/>
140+
</xsd:restriction>
141+
</xsd:simpleType>
142+
</xsd:element>
143+
<xsd:element minOccurs="0" maxOccurs="1" name="Postleitzahlgebiet">
144+
<xsd:simpleType>
145+
<xsd:restriction base="xsd:string">
146+
<xsd:maxLength value="5"/>
147+
</xsd:restriction>
148+
</xsd:simpleType>
149+
</xsd:element>
150+
<xsd:element minOccurs="0" maxOccurs="1" name="Schiedsamtsbezirk">
151+
<xsd:simpleType>
152+
<xsd:restriction base="xsd:string">
153+
<xsd:maxLength value="2"/>
154+
</xsd:restriction>
155+
</xsd:simpleType>
156+
</xsd:element>
157+
<xsd:element minOccurs="0" maxOccurs="1" name="Sozialraum__Nr._">
158+
<xsd:simpleType>
159+
<xsd:restriction base="xsd:string">
160+
<xsd:maxLength value="9"/>
161+
</xsd:restriction>
162+
</xsd:simpleType>
163+
</xsd:element>
164+
<xsd:element minOccurs="0" maxOccurs="1" name="Sozialraum">
165+
<xsd:simpleType>
166+
<xsd:restriction base="xsd:string">
167+
<xsd:maxLength value="100"/>
168+
</xsd:restriction>
169+
</xsd:simpleType>
170+
</xsd:element>
171+
<xsd:element minOccurs="0" maxOccurs="1" name="globalid" type="xsd:string"/>
172+
<xsd:element minOccurs="0" maxOccurs="1" name="shape" type="gml:PointPropertyType"/>
173+
</xsd:sequence>
174+
</xsd:extension>
175+
</xsd:complexContent>
176+
</xsd:complexType>
177+
</xsd:schema>

0 commit comments

Comments
 (0)