relax-ng
A pure-Rust implementation of RELAX NG — reads a
RELAX NG schema (compact .rnc or XML .rng syntax) and validates a
document's structure against it: which elements/attributes are allowed
where, in what order, how many times.
Generic and standalone — not tied to HTML, XML parsing, or any specific document type. Callers provide their own parsed document via a trait; this crate only implements the RELAX NG side (schema parsing, composition, pattern matching, datatypes).
Usage
use ;
// This crate never reads files or the network itself — it always asks a
// caller-supplied resolver for any `include`/`externalRef`. A schema with
// none of those never actually calls it.
;
let source = new;
let schema = compile.expect;
// Implement `Element` over your own document tree — an XML DOM, an HTML
// parser's tree, whatever you already have. This crate parses none of it.
let errors = schema.validate
.expect;
assert!;
See examples/validate.rs for a complete,
runnable version (cargo run --example validate), and the Schema/
Element rustdoc for the full contract.
Datatype libraries
- The RELAX NG built-in library (empty
datatypeLibrary,string/token) and XSD (http://www.w3.org/2001/XMLSchema-datatypes— all 19 primitive types, the built-in derived types, and all facets) are implemented and registered by default viaDatatypeRegistry::new().decimal/date-time ordering anddurationcomparison have documented, deliberate precision limits — seeplan/DECISIONS.md's Phase 06 entry. - Any other
datatypeLibrary(e.g. vnu's ownhttp://whattf.org/datatype-draft) is not implemented by this crate — register your own [DatatypeLibrary] implementation on the registry instead; an unregistered library fails schema compilation fast, with a clear error, rather than silently mismatching.
Resource loading
This crate never opens a file or makes a network request on its own.
SchemaSource carries schema text plus a base URI; a caller-supplied
SchemaResolver resolves any include/externalRef an href — reading
from disk, an in-memory map, HTTP, or anything else, with whatever
security boundary (allowed schemes, path restrictions) fits the caller.
Status
Parsing (both .rnc and .rng), composition/simplification, the
Brzozowski-derivative validation engine, and the built-in+XSD datatype
libraries are implemented. The vendored official RELAX NG test suite
passes at 100% for both schema classification and instance validation
(the subset not requiring a multi-file resolver — see
plan/07-conformance-loop.md). Not yet published to crates.io; the public
API may still change before 1.0. See plan/00-STATUS.md for the
authoritative, up-to-date phase-by-phase status (not tracked in git,
local working document; see plan/README.md for why).
Why this exists
Built for html-conform's
RELAX NG validation layer (schema.rs), after evaluating two existing
options and rejecting both — see that project's plan/DECISIONS.md for
the full writeup:
xmloxide's RelaxNG engine has several confirmed bugs (upstream issues #52–#56), the worst of which rejects almost any attribute in a realistically modular schema.dholroyd/relaxng-rustis technically strong (passes the official 384-test RELAX NG test suite, reads.rncnatively, handles multi-file composition) but carries no license at all — unusable as a dependency without the author's explicit permission.
This crate is architecturally informed by relaxng-rust's public
design (the syntax → model → validator split, targeting the official
RELAX NG test suite) but is an independent, clean-room implementation —
no code taken from it — published under MIT from the start.
Package name and versioning
Published on crates.io as relax-ng. The current 0.1.1 in Cargo.toml
is a pre-release working version, not a semver commitment — breaking
changes to the public API are still expected before a 1.0 release.
After that, this crate follows normal semver.
License
MIT — see LICENSE.