A JVM needs Xerces, Xalan, Saxon, FOP and Santuario to do this. Rust now needs one workspace.
Today we released OxiXML 0.1.0 — the first release of the Pure-Rust foundation for all XML and RDF processing in the COOLJAPAN ecosystem. Forty-four independently publishable crates, from a byte-level XML scanner up through XSLT 3.0 essentials, XQuery 3.1, XSD 1.1, RELAX NG, Schematron, XMLDSig, XSL-FO, and the complete RDF 1.2 / Turtle / RDF-XML / JSON-LD / RDFa / canonicalization / SPARQL-results stack.
No C, no C++, no Fortran, no libxml2, no libxslt, no Xerces, no JVM. Not in the default build, and not behind any feature. Zero external crates in default features — serde and tokio exist only behind off-by-default flags. It compiles to a single static binary, targets WASM, and runs everywhere.
Why OxiXML 0.1.0 is a game changer
Rust’s XML story has been a patchwork. You reach for quick-xml to pull events, and then you stop — because the moment you need real validation, XPath, XSLT, or signature verification, the ecosystem hands you an FFI binding to a 25-year-old C library, or nothing at all:
- XSD 1.1 validation — no Pure-Rust implementation.
- XSLT — no Pure-Rust implementation;
libxsltbindings or shell out toxsltproc. - XQuery 3.1 — no Pure-Rust implementation; Saxon on a JVM.
- XMLDSig / XMLEnc — no Pure-Rust implementation; Apache Santuario on a JVM.
- RELAX NG, Schematron, XInclude, XML Catalogs, XSL-FO — the same story, over and over.
- And on the RDF side, the Oxigraph crates are excellent — but they are a separate stack, with a separate IRI type, a separate datatype library, and no shared XML core.
OxiXML 0.1.0 ends all of that:
- A drop-in
quick-xmlreplacement.oxixml-xmlmirrors the quick-xml 0.41 API —Reader,NsReader,Writer/ElementWriter, the event types, escaping,Config— including the serde deserializer/serializer and anasync-tokiofeature.oxixml-quickxml-compatis a path-compatible shim, so existingquick_xml-based code switches over with a one-lineCargo.tomlchange. - An Oxigraph-shaped RDF stack.
oxrdf,oxttl,oxrdfxml,oxjsonld,oxrdfio,spargebra,sparesults,oxsdatatypes,oxiri, andrdf-canoneach have an equivalent-or-compatible crate here — sharing one IRI type, one datatype library, and one XML core with the validation and query tiers. - The JVM tiers, natively. DOM Level 3 Core-class trees, SAX2, XDM, HTML5 tokenizer + tree construction, DTD/XSD 1.1/RELAX NG/Schematron validation, XPath 1.0–3.1, XQuery 3.1, XSLT 1.0 complete plus 2.0/3.0 essentials, Canonical XML 1.0/1.1/Exclusive/2.0, XMLDSig sign+verify, XMLEnc, and an XSL-FO 1.1 tree/property model.
- Conformance, not confidence. Every parser, validator, and engine is gated on its own W3C test suite. Aggregate across all suites end-to-end: 137,656 of 138,249 cases (99.6%), with every individual suite at or above a 99% production gate.
- ~296,000 lines of Rust across 918 files (297,939 total SLoC per tokei) — a COCOMO estimate of roughly 33.9 months and 28.1 people.
Technical Deep Dive: nine tiers, one workspace
- Primitives and atoms.
oxixml-support(SWAR byte scanning, SHA-1/2 + HMAC, bigint modpow),oxixml-unicode(Unicode 17.0.0 tables, NFC/NFD/NFKC/NFKD),oxixml-encoding(UTF-8/16, the WHATWG single-byte set, plus Shift_JIS, EUC-JP and ISO-2022-JP with incremental state machines),oxixml-text,oxixml-regex(XSD and XPath regex flavors), thenoxixml-iri(RFC 3987),oxixml-langtag(BCP 47),oxixml-xsd(XSD 1.1 datatypes),oxixml-qname. - XML core and trees.
oxixml-xmlis the pull parser and writer everything else reads through;oxixml-dom,-sax,-infoset, and-htmlbuild the tree, push, XDM, and HTML5 views over it. XML 1.1 RestrictedChar enforcement, Namespaces 1.1 prefix undeclaration, an entity-expansion budget (10k expansions / 10 MiB), and a configurable element-depth guard are in the core, not bolted on. - Validation and query.
oxixml-dtd,-schema(XSD 1.0/1.1),-relaxng(XML and compact syntax, derivative validation),-schematron,-catalog(OASIS XML Catalogs 1.1),-xinclude; thenoxixml-fn(the XPath/XQuery F&O 3.1 function library) under-xpath,-xquery, and-xslt. - Security, formatting, and RDF.
oxixml-c14n,-dsig,-enc,-fo; and the RDF tier —oxixml-model,-turtle,-rdfxml,-jsonld,-rdfa,-trix,-hdt,-canon,-io,-vocab, plusoxixml-sparql-syntaxand-sparql-results. Theoxixmlfacade gathers all of it behind 42 feature-gated re-exports across 8 families;oxixml-cliexposes it as onexmllint/xsltproc/rapper-class binary.
Execution engines stay where they belong: SPARQL query execution, SHACL validation, FO→PDF rendering, and OWL/RDFS reasoning live in oxirs-arq, oxirs-shacl, fop, and oxirs — and depend on OxiXML for parsing, the data model, and validation primitives.
Getting Started
The facade, with only the features you need:
cargo add oxixml --features turtle,xslt
[dependencies]
oxixml = { version = "0.1.0", features = ["turtle", "xslt"] }
# ...or reach for everything at once:
# oxixml = { version = "0.1.0", features = ["full"] }
Or take a single crate on its own — here, the quick-xml-shaped core:
use oxixml_xml::escape::{escape, unescape};
use oxixml_xml::events::{BytesStart, Event};
use oxixml_xml::name::QName;
// Build a start tag and inspect its name and attributes.
let start = BytesStart::new("greeting").with_attributes([("lang", "en")]);
assert_eq!(start.name(), QName(b"greeting"));
// Wrap it in an event; events borrow their payload bytes.
let event = Event::Start(start);
assert_eq!(&*event, b"greeting lang=\"en\"".as_ref());
// Escape and unescape round-trip.
assert_eq!(escape("a < b & c"), "a < b & c");
assert_eq!(unescape("a < b & c").expect("valid"), "a < b & c");
And the CLI, which installs a binary named oxixml:
$ cargo install oxixml-cli
$ echo '<a><b/></a>' | oxixml fmt -
<a>
<b/>
</a>
What’s inside 0.1.0
- XML core: a complete quick-xml 0.41-shaped pull parser and writer, the serde deserializer/serializer behind
serialize, anasync-tokiofeature, andoxixml-quickxml-compatas a drop-in shim. - RDF: RDF 1.2 model, N-Triples/N-Quads/Turtle/TriG/N3, RDF/XML, TriX, JSON-LD 1.1 (expand/compact/flatten/toRdf/fromRdf), RDFC-1.0 canonicalization, HDT binary read/write, a unified I/O facade, and SPARQL 1.0/1.1/1.2 query+update parsed to algebra with XML/JSON/CSV/TSV results I/O.
- Trees and validation: DOM Level 3 Core-class arena tree with namespace-fixup serialization, SAX2, XDM, an HTML5 tokenizer + tree construction, and validating DTD / XSD 1.0+1.1 / RELAX NG / Schematron / XML Catalogs / XInclude processors.
- Query and transform: the F&O 3.1 function library, XPath 1.0–3.1, XQuery 3.1, and XSLT 1.0 complete with 2.0/3.0 essentials.
- Security and format: Canonical XML 1.0/1.1/Exclusive + 2.0, XMLDSig sign+verify (incl. RSA PKCS#1 v1.5 and HMAC), XMLEnc (AES-CBC/GCM, AES-KW, RSA-OAEP), and an XSL-FO 1.1 tree/property model.
- Async everywhere it matters: an
async-tokiofeature across the full RDF I/O stack, signature-compatible with upstream oxttl/oxrdfio/sparesults and forwarded by the facade. - Hardening: a production sweep of 100+ confirmed findings — iterative rewrites and depth guards eliminating stack-overflow aborts across infoset/html/xpath/xquery/jsonld/sparql/regex/dsig, an unbounded-memory fix in end-of-input well-formedness checking,
XdmMaprewritten as a persistent HAMT (map:put/map:remove were O(n) full copies), and F&O implicit-timezone semantics threaded end-to-end. - Conformance: RDF 1.1 Turtle 313/313 · RDF/XML 166/166 · RDFC-1.0 86/86 · JSON-LD toRdf 455/455 · SPARQL 1.2 syntax 198/198 · DTD validation 933/933 · Schematron 307/307 · RELAX NG schemas 385/385 · html5lib tokenizer 7032/7032 and tree construction 1792/1792 (both 100%) · W3C RDFa across all four host languages 654/654 (100%) · XSD 1.1 whole-suite 99.6% · QT3 XPath 99.6% / XQuery 99.3% · xslt30-test 99.9% · Canonical XML 2.0 30/30.
- 7,084 tests passing with
--all-features(4,469 with default features), 787 doc-tests, 0 failures;cargo doc --workspaceclean underRUSTDOCFLAGS="-D warnings";cargo deny check bansclean.
Tips
- Migrating off
quick-xml? Change one line. Alias the compat shim inCargo.toml—quick_xml = { package = "oxixml-quickxml-compat", version = "0.1.0" }— and your existinguse quick_xml::…paths keep working. - There is no default feature on the facade — that’s deliberate. Enable exactly what you need; enabling a feature pulls in whatever it is built on (
xsltbringsxpathanddom, which bringsxml;rdfabringshtmlandrdf), so you never have to name the transitive tier yourself. - Prefer the individual crates over the facade for leaf dependencies. All 44 are published independently — a crate that only parses Turtle should depend on
oxixml-turtle, not onoxixmlwith one feature turned on. - Untrusted input has knobs, not just defaults. The entity-expansion budget (10k expansions / 10 MiB) is on by default, and
Config::max_element_depth(default 1024) is configurable — surfaced throughoxixml-domasBuilderOptions::with_max_element_depth. - Embedding XSLT? Two escape hatches worth knowing.
Parameters::with_recursion_limitraises the default 1000-level template-instantiation ceiling, andStaticOptions::with_backwards_compatibility(false)switches from the permissive default to strictXTDE0160rejection of evaluatedversion="1.0"elements.CompiledStylesheet::transform_optionalruns a transform with no source document at all. - Reach for
oxixml-clibefore writing glue.doc,fmt,lint,validate,transform,query,canon,convert,rdf-format,hdt, andsparqlare all there, with--catalogand--xincludesupport — andoxixml_cli::run_statusis public, so you can drive the same code path from a test.
This is the foundation
OxiXML depends on nothing else in the ecosystem, so any project can adopt it without a dependency cycle — which is the whole point of putting it at the bottom. OxiRS (and oxirs-arq / oxirs-shacl), OxiGeo, OxiMedia, Legalis-RS, and every COOLJAPAN project that currently pulls quick-xml or an Oxigraph crate are the migration targets, tier by tier: trivial XML consumers first, then the serde-based ones, then oxirs-core’s async + NsReader + Decoder surface.
Repository: https://github.com/cool-japan/oxixml
Star the repo if you want XSD 1.1, XSLT, XQuery and XMLDSig in Rust without a JVM or a C library underneath.
The era of shelling out to xsltproc is over. Pure Rust XML and RDF — complete, conformant, and sovereign — is here.
— KitaSan at COOLJAPAN OÜ July 30, 2026