Skip to content

Fix xsd:import without namespace incorrectly inheriting parent targetNamespace#1488

Open
pauloxnet wants to merge 1 commit intomvantellingen:mainfrom
pauloxnet:fix-visit-import-no-namespace-inherit
Open

Fix xsd:import without namespace incorrectly inheriting parent targetNamespace#1488
pauloxnet wants to merge 1 commit intomvantellingen:mainfrom
pauloxnet:fix-visit-import-no-namespace-inherit

Conversation

@pauloxnet
Copy link
Copy Markdown

@pauloxnet pauloxnet commented May 5, 2026

The block at lines 255-259 of src/zeep/xsd/visitor.py (elif not schema_tns and not namespace: namespace = self.document._target_namespace) forces an xsd:import schemaLocation="..." without a namespace attribute to inherit the importing schema's targetNamespace. That is xsd:include semantics, not xsd:import semantics. The practical effect: elements declared in the imported no-namespace schema get re-registered under the parent namespace, and any unqualified QName referencing them (typically wsdl:part element="Header" in a soap:header binding) fails to resolve, surfacing as IndexError: No definition '{tns}Header' in 'messages' found. WCF/.NET-generated WSDLs hit this routinely.

The block was introduced in 713c779 ("Fix an issue with resolving qualified qname's used in references", #879, Dec 2018). One week later #888 / b7ad93e partially reverted the chameleon support and added the _has_empty_import flag, but only for the <import/> case (no namespace, no location). At the time @mvantellingen noted "I'm wondering if that unittest is actually ok" and @apollo13 replied "Not sure if the test is wrong or the code needs more work". That uncertainty was never resolved. Issues #600 (Jan 2018) and #662 (Jun 2018) report the same symptom against WCF WSDLs and have stayed open or closed-without-fix since.

Fix

Two changes in visit_import:

  1. The inheritance block is removed.
  2. _has_empty_import is activated whenever an import omits namespace, per W3C XSD 4.1.2. The activation is placed at the three exit points so that an import naming a namespace incorrectly (which the existing XMLParseError rejects a few lines later) cannot poison the parent's QName resolution: on a cache hit, only when the cached document has no _target_namespace; on the canonical empty <import/>, in the missing-schemaLocation branch; and post-load, only when the imported schema has no targetNamespace either.

tests/test_wsdl.py::test_import_schema_without_namespace_and_header reproduces the original failure (namespaced schema importing a no-namespace schema whose element is used as a SOAP header part) and asserts both that the element ends up under the null namespace and that no {tns}Header ghost registration exists.

Breaking change

Strict W3C QName resolution has a real consequence. In a schema with elementFormDefault="qualified" that does <xsd:import schemaLocation="..."/> (no namespace) of a no-namespace schema, an unqualified ref to an element defined in the same importing schema now resolves in the null namespace and fails. The spec-compliant fix on the consumer side is the qualified form:

<xsd:element ref="tns:local"/>

This case is captured in tests/test_xsd_schemas.py::test_no_target_namespace_unqualified_ref_to_own_element, marked xfail(strict=True) so any future change is a deliberate one. No existing test in the repository hits this pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant