COOLJAPAN
← All posts

OxiXML 0.1.0 Released — Xerces, Xalan, Saxon, FOP and Oxigraph, Rewritten in Pure Rust

OxiXML 0.1.0 is the first release of the COOLJAPAN Pure-Rust foundation for all XML and RDF processing — 44 crates spanning a quick-xml-compatible parser, DOM/SAX/HTML5 trees, XSD 1.1/RELAX NG/Schematron validation, XPath/XQuery/XSLT, XMLDSig/XMLEnc, and the full RDF 1.2/Turtle/JSON-LD/RDFa/SPARQL stack. 137,656 of 138,249 W3C conformance cases passing (99.6%), 0 external crates in default features.

release oxixml xml rdf xslt xpath sparql json-ld pure-rust

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 featuresserde 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:

OxiXML 0.1.0 ends all of that:

Technical Deep Dive: nine tiers, one workspace

  1. 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), then oxixml-iri (RFC 3987), oxixml-langtag (BCP 47), oxixml-xsd (XSD 1.1 datatypes), oxixml-qname.
  2. XML core and trees. oxixml-xml is the pull parser and writer everything else reads through; oxixml-dom, -sax, -infoset, and -html build 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.
  3. 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; then oxixml-fn (the XPath/XQuery F&O 3.1 function library) under -xpath, -xquery, and -xslt.
  4. Security, formatting, and RDF. oxixml-c14n, -dsig, -enc, -fo; and the RDF tier — oxixml-model, -turtle, -rdfxml, -jsonld, -rdfa, -trix, -hdt, -canon, -io, -vocab, plus oxixml-sparql-syntax and -sparql-results. The oxixml facade gathers all of it behind 42 feature-gated re-exports across 8 families; oxixml-cli exposes it as one xmllint/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 &lt; b &amp; c");
assert_eq!(unescape("a &lt; b &amp; 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

Tips

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

↑ Back to all posts