Skip to content

Commit 2b7b58a

Browse files
committed
Fix xsd:import without namespace incorrectly inheriting parent targetNamespace
1 parent 368861c commit 2b7b58a

2 files changed

Lines changed: 77 additions & 14 deletions

File tree

src/zeep/xsd/visitor.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -199,14 +199,11 @@ def visit_import(self, node, parent):
199199
sourceline=node.sourceline,
200200
)
201201

202-
# We found an empty <import/> statement, this needs to trigger 4.1.2
203-
# from https://www.w3.org/TR/2012/REC-xmlschema11-1-20120405/#src-resolve
204-
# for QName resolving.
205-
# In essence this means we will resolve QNames without a namespace to no
206-
# namespace instead of the target namespace.
207-
# The following code snippet works because imports have to occur before we
208-
# visit elements.
209-
if not namespace and not location:
202+
# Per W3C XSD 4.1.2 (https://www.w3.org/TR/2012/REC-xmlschema11-1-20120405/#src-resolve):
203+
# an import without a namespace attribute provides access to the no-namespace
204+
# components. In that case unqualified QNames should resolve to no namespace
205+
# instead of the target namespace.
206+
if not namespace:
210207
self.document._has_empty_import = True
211208

212209
# Check if the schema is already imported before based on the
@@ -252,12 +249,6 @@ def visit_import(self, node, parent):
252249
sourceline=node.sourceline,
253250
)
254251

255-
# If the imported schema doesn't define a target namespace and the
256-
# node doesn't specify it either then inherit the existing target
257-
# namespace.
258-
elif not schema_tns and not namespace:
259-
namespace = self.document._target_namespace
260-
261252
schema = self.schema.create_new_document(
262253
schema_node, location, target_namespace=namespace
263254
)

tests/test_wsdl.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,78 @@ def test_import_cyclic():
12681268
)
12691269

12701270

1271+
def test_import_schema_without_namespace_and_header():
1272+
"""An xsd:import with schemaLocation but no namespace attribute that
1273+
points to a schema without targetNamespace should not inherit the
1274+
parent schema's targetNamespace. When the imported element is used
1275+
in a soap:header binding, the unqualified QName must still resolve.
1276+
"""
1277+
xsd_content = (
1278+
b'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">'
1279+
b'<xs:element name="Header" type="xs:string"/>'
1280+
b"</xs:schema>"
1281+
)
1282+
1283+
wsdl_main = StringIO(
1284+
"""\
1285+
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
1286+
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
1287+
xmlns:tns="http://tests.python-zeep.org/tns"
1288+
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
1289+
targetNamespace="http://tests.python-zeep.org/tns" name="TestService">
1290+
<wsdl:types>
1291+
<xsd:schema targetNamespace="http://tests.python-zeep.org/tns">
1292+
<xsd:import schemaLocation="http://tests.python-zeep.org/header.xsd"/>
1293+
<xsd:element name="Request" type="xsd:string"/>
1294+
</xsd:schema>
1295+
</wsdl:types>
1296+
<wsdl:message name="InputMsg">
1297+
<wsdl:part name="body" element="tns:Request"/>
1298+
</wsdl:message>
1299+
<wsdl:message name="HeaderMsg">
1300+
<wsdl:part name="h" element="Header"/>
1301+
</wsdl:message>
1302+
<wsdl:portType name="TestPort">
1303+
<wsdl:operation name="Op">
1304+
<wsdl:input message="tns:InputMsg"/>
1305+
<wsdl:output message="tns:InputMsg"/>
1306+
</wsdl:operation>
1307+
</wsdl:portType>
1308+
<wsdl:binding name="TestBinding" type="tns:TestPort">
1309+
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
1310+
<wsdl:operation name="Op">
1311+
<soap:operation soapAction="Op"/>
1312+
<wsdl:input>
1313+
<soap:body use="literal"/>
1314+
<soap:header message="tns:HeaderMsg" part="h" use="literal"/>
1315+
</wsdl:input>
1316+
<wsdl:output>
1317+
<soap:body use="literal"/>
1318+
</wsdl:output>
1319+
</wsdl:operation>
1320+
</wsdl:binding>
1321+
<wsdl:service name="TestService">
1322+
<wsdl:port name="TestPort" binding="tns:TestBinding">
1323+
<soap:address location="http://tests.python-zeep.org/endpoint"/>
1324+
</wsdl:port>
1325+
</wsdl:service>
1326+
</wsdl:definitions>
1327+
"""
1328+
)
1329+
1330+
transport = DummyTransport()
1331+
transport.bind("http://tests.python-zeep.org/header.xsd", xsd_content)
1332+
1333+
document = wsdl.Document(
1334+
wsdl_main, transport, "http://tests.python-zeep.org/test.wsdl"
1335+
)
1336+
1337+
service = document.services.get("TestService")
1338+
assert service is not None
1339+
port = service.ports.get("TestPort")
1340+
assert port is not None
1341+
1342+
12711343
def test_import_no_location():
12721344
node_a = etree.fromstring(
12731345
"""

0 commit comments

Comments
 (0)