diff --git a/src/zeep/xsd/visitor.py b/src/zeep/xsd/visitor.py index 5aa40f53..59ba3d57 100644 --- a/src/zeep/xsd/visitor.py +++ b/src/zeep/xsd/visitor.py @@ -199,14 +199,11 @@ def visit_import(self, node, parent): sourceline=node.sourceline, ) - # We found an empty statement, this needs to trigger 4.1.2 - # from https://www.w3.org/TR/2012/REC-xmlschema11-1-20120405/#src-resolve - # for QName resolving. - # In essence this means we will resolve QNames without a namespace to no - # namespace instead of the target namespace. - # The following code snippet works because imports have to occur before we - # visit elements. - if not namespace and not location: + # Per W3C XSD 4.1.2 (https://www.w3.org/TR/2012/REC-xmlschema11-1-20120405/#src-resolve): + # an import without a namespace attribute provides access to the no-namespace + # components. In that case unqualified QNames should resolve to no namespace + # instead of the target namespace. + if not namespace: self.document._has_empty_import = True # Check if the schema is already imported before based on the @@ -252,12 +249,6 @@ def visit_import(self, node, parent): sourceline=node.sourceline, ) - # If the imported schema doesn't define a target namespace and the - # node doesn't specify it either then inherit the existing target - # namespace. - elif not schema_tns and not namespace: - namespace = self.document._target_namespace - schema = self.schema.create_new_document( schema_node, location, target_namespace=namespace ) diff --git a/tests/test_wsdl.py b/tests/test_wsdl.py index ddf617b1..b3a502ab 100644 --- a/tests/test_wsdl.py +++ b/tests/test_wsdl.py @@ -1268,6 +1268,78 @@ def test_import_cyclic(): ) +def test_import_schema_without_namespace_and_header(): + """An xsd:import with schemaLocation but no namespace attribute that + points to a schema without targetNamespace should not inherit the + parent schema's targetNamespace. When the imported element is used + in a soap:header binding, the unqualified QName must still resolve. + """ + xsd_content = ( + b'' + b'' + b"" + ) + + wsdl_main = StringIO( + """\ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + """ + ) + + transport = DummyTransport() + transport.bind("http://tests.python-zeep.org/header.xsd", xsd_content) + + document = wsdl.Document( + wsdl_main, transport, "http://tests.python-zeep.org/test.wsdl" + ) + + service = document.services.get("TestService") + assert service is not None + port = service.ports.get("TestPort") + assert port is not None + + def test_import_no_location(): node_a = etree.fromstring( """