Resolve multi-file XML schemas¶
Use xs:include for declarations in the same target namespace (including
no namespace), and xs:import for another namespace. Relative
schemaLocation values resolve from the schema containing the directive,
not from the instance document.
Create the files¶
Create a schemas directory and save these four files inside it. The main
schema includes a local type and imports a code type from urn:codes.
schemas/orders.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:c="urn:codes">
<xs:include schemaLocation="fields.xsd"/>
<xs:import namespace="urn:codes"/>
<xs:element name="order">
<xs:complexType>
<xs:sequence>
<xs:element name="code" type="c:ProductCode"/>
<xs:element name="quantity" type="Quantity"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
schemas/fields.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="Quantity">
<xs:restriction base="xs:positiveInteger"/>
</xs:simpleType>
</xs:schema>
schemas/codes.xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:codes">
<xs:simpleType name="ProductCode">
<xs:restriction base="xs:string">
<xs:pattern value="[A-Z]{2}"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
schemas/order.xml:
<order xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="orders.xsd">
<code>AB</code><quantity>2</quantity>
</order>
Compile with an explicit namespace mapping¶
Run Python from the directory containing schemas:
from pathlib import Path
from pyxsd import ParseModes, Schema
base = Path("schemas").resolve()
schema = Schema.compile(
base / "orders.xsd",
mode=ParseModes.NAMESPACED,
namespace_schemas={"urn:codes": "codes.xsd"},
)
schema.require_valid()
document = schema.parse(base / "order.xml")
document.require_valid()
print(document.root.code, document.root.quantity) # AB 2
The mapping supplies the location omitted by xs:import. Its relative path
resolves from the main schema, so codes.xsd means schemas/codes.xsd here.
Alternatively, put schemaLocation="codes.xsd" on that import.
Loading a schema for a namespace does not add missing authored imports to
other schema documents. Each document using foreign components must declare
the appropriate xs:import; an xmlns prefix binding alone is not an import.
Keep require_valid() after compilation to catch composition problems
before processing instances.
Let an instance select the main schema¶
The same XML supplies xsi:noNamespaceSchemaLocation for its no-namespace
root. The one-call parser can use that hint:
import pyxsd
hinted = pyxsd.parse(
base / "order.xml",
mode=pyxsd.ParseModes.NAMESPACED,
namespace_schemas={"urn:codes": "codes.xsd"},
)
hinted.require_valid()
print(hinted.is_valid) # True
For namespaced roots, xsi:schemaLocation contains namespace/location pairs,
for example urn:orders orders.xsd urn:codes codes.xsd. Instance-relative
locations resolve from the instance file. Additional hints are advisory;
inspect schema-hint warnings rather than assuming every hint was loaded.
schema.parse(...) instead uses the already compiled schema; an instance
hint does not replace it.
Paths, streams, and remote resources¶
Use absolute input paths, as above, when the working directory can change. In-memory streams do not inherently identify the directory containing their dependencies. Prefer file paths for composed schemas, or provide resolvable absolute references. A trusted resource policy can supply canonical source identities and base paths; see XML security and untrusted input for that interface and remote-access rules. Namespace URIs are identifiers, not URLs pyxsd fetches automatically.
If a dependency fails to load, inspect schema.report first. Confirm the
resolved path, target namespace, import directive, and namespace-aware mode.
Do not use lax binding as a substitute for resolving a missing type.