Architecture¶
pyxsd’s core idea, unchanged since 2006: an XSD schema compiles into a set of Python classes, and an XML document compiles into an instance tree of those classes. Everything else — validation, transforms, the writers — operates on those two artifacts.
Pipeline¶
Schema load.
PyXSD.parseXSD()reads the schema (a file, path, orET.Element), resolvesxs:include/xs:import/xs:redefineby splicing the composed documents into the main tree before any class generation, and registers every top-level element as a descriptor in the global element-representative registry.Class generation. Every schema component named in the registry generates a Python class:
Simple types resolve to one of the ~45 built-in types in
pyxsd.xsd_data_types(validation happens in__new__) or to a generated class derived throughxs:restriction/xs:list/xs:union.Complex types / elements generate subclasses of
SchemaBasethroughtypes.new_class, withElementandAttributedescriptors wired up via__set_name__and class metadata (_elementNames_,_attributeNames_) computed bySchemaBase.__init_subclass__.
The generated class tree mirrors the derivation tree in your schema:
xs:extensionproduces real subclassing, soisinstancechecks and inherited descriptors work the way you’d expect.Instance construction.
parseXML()matches the document root against the global element declarations (honoringxsi:typedispatch and abstract-element rejection), then recursively builds instances. Text and attributes are validated against the declared types; undeclared children fall through wildcard (xs:any) declarations as generic nodes. Substitution-group members are accepted wherever their head is declared. Order/occurrence/identity checks run as post-passes.Transforms. A transform pipeline — built-in
PrintData,SendTreeToPyXSD, or user classes derived frompyxsd.transforms.Transform— is applied to the root instance. Transforms see a stable node shape (_name_,_attribs_,_children_,_value_; see Data model).Writers.
XmlTreeWriterserializes the (possibly transformed) tree back to XML, preserving document order and xsi declarations.
The ElementRepresentative system¶
While the schema is being processed, every xs:* tag (element,
complexType, sequence, attributeGroup, …) becomes an
ElementRepresentative (ER) — a lightweight object that collects the
schema’s own metadata (names, occurrence limits, type references, facets)
and links to its children ERs. ERs are the compiler front end: they
decide what class each component should get, resolve references (element
refs, group refs, substitution groups), and report schema-level errors.
The registry they populate is consulted during class generation and again
during instance construction (root matching, xsi:type resolution).
Key methods of the ER system:
ElementRepresentative.factory— creates the right ER class for a tag, recursively processing children.ElementRepresentative.registry— global map of component name → ERs.XsdType.clsFor— the class-generation entry point for a type.
Validation reporting¶
All non-fatal issues — from schema composition, instance validation, or
identity constraints — are recorded in one ValidationReport reachable at
PyXSD.report. Codes (e.g. order, occurrence-min, identity-key)
are stable strings suitable for grep-based CI checks; see Validation.
Overlay classes (experimental)¶
-c file.py loads a user module whose classes extend the generated ones by
subclassing SchemaBase — see parser.loadClassFromFile. This mechanism is
unchanged in spirit from 0.1 and remains experimental.