Skip to content

xsdkit

A generic XSD reader: parse W3C XML Schema into a queryable schema component model, in Rust and Python.

XSD is three languages at once — schema documents, schema components, and validation semantics defined over those components. The specification defines every rule it has against the middle layer. Most tools skip it: they read documents and emit code, or they read documents and answer valid/invalid. xsdkit builds the middle layer and hands it to you.

That is the difference between asking "is this document valid?" and asking "what may go inside a report, may it repeat, and what type is it?" — the second question is the one you have when you are generating a form, mapping a schema onto a dataframe, or writing a converter.


In thirty seconds

import xsdkit

schemas = xsdkit.SchemaSet.from_file("report.xsd")
report = schemas["{urn:example}report"]

print(report.tree())
report: {urn:example}Report
  @id
  title: xs:string
  issued: xs:date
  item+: {urn:example}Item
    @sku
    @quantity?
    price: {urn:example}Money
      @currency
    note?: xs:string
use xsdkit::{Diagnostics, SchemaSetBuilder};

fn main() -> Result<(), Diagnostics> {
    let schemas = SchemaSetBuilder::new()
        .file("report.xsd")
        .compile()
        .into_result()?;

    let report = schemas.element(Some("urn:example"), "report").unwrap();
    for child in report.children() {
        println!(
            "{}  repeating={}  optional={}",
            child.display_name(),
            child.repeats(),
            child.optional(),
        );
    }
    Ok(())
}

Every example on this site runs against report.xsd, which is 60 lines and worth a glance.


What it gives you

  • The component model, not a parse tree

    Types, elements, attributes, particles, model groups, wildcards, identity constraints, notations and annotations — with all seven symbol spaces kept separate, attribute groups flattened, and substitution groups closed.

    The component model

  • Answers about content, from an automaton

    Content models compile to Glushkov position automata, so "which children, can they repeat, can they be absent, does this sequence fit" are lookups rather than a walk over particles you have to interpret yourself.

    Querying the model

  • Validation with typed values

    One streaming pass, and a PSVI where values arrive as 42 and Decimal("19.95") — not strings for you to parse a second time.

    Validating documents

  • Diagnostics that name the problem

    Stable codes, source spans, help text, and every error rather than the first — because someone fixing a 40-file import graph needs the list.

    Diagnostics


Status

The component model, loading, composition, content automata, instance validation and the Python bindings work, and are measured against the W3C XML Schema Test Suite on every change.

XSD 1.0 XSD 1.1
valid schemas accepted 99.8% 99.8%
invalid schemas rejected 77.8% 69.9%
documents judged correctly 99.8% 99.0%

The gap in the second row is the honest description of what this is. xsdkit reads real schemas well; it enforces some of the specification's validity constraints and not others — which ones, rule by rule — so a schema it accepts is not thereby a valid schema. If you need a conformance checker, reach for Xerces or Saxon. If you need to read a schema that already works, this is built for that.

The full conformance picture

Next up is XSD 1.1 assertions and conditional type assignment. Code generation is permanently out of scope — that is xsd-parser's job.


Where to go next