XSD dialects
Last Updated: 2026-06-10 Status: 🟢 APPROVATO — allineato al contratto v0.8.0 (XML core + builder-only codegen). Maintainer: core team.
XSD support is a codegen pipeline (the transpiler) plus a light
grammar base. Given an XSD schema, the transpiler writes a
self-contained Python module — a <Dialect>Builder — that you commit
and import with no runtime dependency on the parser. On-the-wire
format is XML.
Purpose
Turn an XML Schema into an ergonomic, validated builder grammar: one
@element per schema element, cardinalities as sub_tags, enumerations
as Literal, bounded/patterned simple types as Annotated[...]. The
schema itself remains the canonical conformance check — the grammar is an
authoring aid (documents the schema, validates tag placement, helps
editors), not a full XSD validator. The pre-render cardinality check
(contract PAG.4) is the structural first net.
The grammar base
from genro_builders.xml import XmlBuilderBase
XmlBuilderBase(BuilderBase) — shared grammar base for the
XML-on-the-wire dialects (XSLT and the schema-generated ones); default
render mode is xml. The namespace-tag mechanism (_meta
ns/local, xmlns_<prefix> attributes) lives on the core
XmlRenderer. A generated dialect is an ordinary builder: subclass it
for a page, or mount it on a BuilderHandler like any other.
The XML render is the core’s real XmlRenderer (pointers resolved,
framework markers filtered) — see HTML grammar for the xml
mode vs. the raw source.to_xml() view.
Quick start — bundled Sitemap example
from decimal import Decimal
from genro_builders.xml.examples.sitemap import SitemapBuilder
class MySitemap(SitemapBuilder):
def main(self, root):
s = root.urlset()
home = s.url()
home.loc("https://www.example.com/")
home.changefreq("daily")
home.priority(Decimal("1.0"))
sm = MySitemap()
sm.create()
print(sm.render(pretty=True))
Generating a dialect
python -m genro_builders.xml.transpiler \
--xsd path/to/schema.xsd \
--dialect-name MySchema \
--output path/to/my_schema.py
Requires the [xsd] extra (xmlschema), needed only to run the
transpiler. The generated module imports neither xmlschema nor the
transpiler.
A starting base, to refine
The transpiler emits as builder grammar:
one
@elementper element (global + locally declared);sub_tags='a[1],b[0:],c[1:5]'with explicit cardinalities;attributes /
simpleContentas call-args, withLiteral[...]for enumerations andAnnotated[..., Regex(...)]/Annotated[..., Range(...)]for pattern /minInclusive/maxInclusivefacets.
It does not silently swallow what it cannot express — it surfaces it as
# NOTE: comments for the developer to refine by hand:
minLength/maxLength/totalDigits/fractionDigits(grammar gaps);XSD patterns Python’s
recannot compile — most notably Unicode block properties (\p{IsBasicLatin}, XML Schema / Java / .NET syntax). The validator is emitted commented out, so construction never raises on a patternrewould reject; the original pattern stays in the comment.
Bundled examples
Under src/genro_builders/xml/examples/:
sitemap/— small schema modelled on the public Sitemaps protocol 0.9 (urlset/url,changefreqenum,priorityrange).fatturapa/— Italian PA electronic invoice (Schema_VFPA12_V1.2.3.xsd); large real-world schema, several patterns commented out per the rule above.