Quickstart¶
pyxsd maps an XML document into a Python object tree according to its XML Schema (XSD), reports validation issues, runs user-defined transforms, and writes the tree back out as XML. The base install’s runtime dependencies are elementpath (XSD regular expressions and XPath) and defusedxml, both pure Python with no compiled extensions. defusedxml is loaded only when an opt-in parser profile selects it; the default parser keeps the stdlib’s speed and compatibility.
Requirements¶
Python 3.11 or newer (3.11–3.15 tested)
Two pure-Python dependencies:
elementpath(XSD regular expressions) anddefusedxml(opt-in parser hardening); no compiled extensions
Note
Parsing untrusted XML is a decision, not a default. See XML security and untrusted input for
XmlParserPolicy, XmlLimits, remote schema rules, and the XPath/DoS boundary.
Installation¶
pip install pyxsd
or with uv:
uv tool install pyxsd
Command line¶
Given a schema and an instance document:
pyxsd --inputXml inventory.xml
pyxsd locates the schema from the instance’s xsi:schemaLocation-style hints
(or you can pass -s schema.xsd), builds the object tree, and validates it.
By default nothing is written: a bare run is a validation pass. Pass -k to
write the parsed tree, or give a transform with -t; transform output goes
to standard output by default. Use -o FILE (or -o stdout) to choose the
destination explicitly, or -d for the default filename
(<input>Transformed.xml). Useful flags:
# Validate strictly: exit 1 if the report contains errors
pyxsd -i inventory.xml -s schema.xsd --strict
# Write the parsed tree to a file, then apply a transform
pyxsd -i inventory.xml -s schema.xsd -k -o transformed.xml -t 'PrintData()'
# Chain transforms with '>'
pyxsd -i inventory.xml -t 'PrintData() > PrintData()'
See Command-line reference for the complete flag reference and Transforms for transform syntax.
Library use¶
Two objects do the work: a compiled Schema and the
Document instances it produces. Compiling the
schema builds the Python classes; each parse binds one instance document:
import pyxsd
schema = pyxsd.Schema.compile("inventory.xsd")
schema.require_valid() # raises pyxsd.ValidationError if the schema is bad
document = schema.parse("inventory.xml")
document.require_valid() # raises pyxsd.ValidationError if the document is bad
A failed check raises ValidationError, whose
report attribute holds every issue found so far. Without it, the
document keeps going — pyxsd is a lax validator — and the report is
there when you want it:
if document.report.has_errors:
for issue in document.report.issues:
print(issue.format())
document.root is the parsed tree’s root instance. Transforms are plain
callables that take the root; one returning a tree root comes back as a
new Document you can write out:
def normalize_units(root): ...
updated = document.transform(normalize_units)
updated.write("normalized.xml")
A transform that changes the tree’s shape leaves the report describing
the tree as it was parsed; call updated.revalidate() to re-parse the
serialized tree and get a fresh report for its current shape. The tree
walks with pyxsd.tree.iter_tree or the walk/visitor helpers in
The Transform class; the node shape is documented in Data model.
What pyxsd validates¶
pyxsd is a lax validator for recoverable issues: it builds the tree even
when the document has validation errors and records non-fatal issues in a
Validation report rather than aborting. The supported feature set includes the built-in type lattice,
sequence / choice / all content models, groups, wildcards, substitution
groups, xsi:type dispatch, nil/default/fixed, identity constraints, and
schema composition. Known gaps are tabulated in Supported features.
Next steps¶
Architecture — how the ER system generates classes from your schema
Writing transforms — write your own transforms
Migrating from pyxsd 0.1 to 1.0 — coming from pyxsd 0.1?