ISO/IEC 19757-3

What is implemented

Area Status Note
schema, pattern, rule, assert, report Full
ns, let, phase, active, include, extends Full
Abstract patterns (abstract, is-a, param) Full
Abstract rules (rule/@abstract + extends) Full
diagnostics, properties, value-of, name, emph, span, dir Full
@flag, @role, @subject, @see, @icon, @fpi Full
pattern/@documents Full
key and key() Full A non-ISO extension — see spec/keys/.
Streaming validation (--stream) Full A non-ISO extension, for schemas provably local to one record — see spec/streaming/.
Phases, #ALL, #DEFAULT, @defaultPhase Full
SVRL output Full
XPath 1.0 — 13 axes, 27 core functions, exact conversion semantics Full
XPath document(), with cross-document node-sets Full
document(uri, base) Full Resolves against the second argument's first node.
XPath 2.0 kind tests as node tests — element(), attribute(id), document-node() Full Under an xslt2 binding.
XPath 2.0 sequences, dates, durations, type operators, value and node comparisons, for, some, every, ranges, regular expressions Subset See spec/xpath2/.
XPath 3.0 function items, =>, ||, !, let, Q{uri}local, the higher-order sequence functions Subset See spec/xpath3/.
queryBinding="xslt", "xpath", or absent Full
queryBinding="xslt2", "xpath2" Subset See spec/xpath2/.
queryBinding="xslt3", "xpath3" Subset See spec/xpath3/.
queryBinding="xslt31" and later Refused By default.
extends rule and extends href, with #fragment identifiers Full

XPath 2.0

A subset, with a hard edge

XPath 2.0 is a different language, not XPath 1.0 with extra functions. The crate implements a documented subset of it — regular expressions, conditionals, and the string and numeric functions schemas actually use — and makes everything outside that subset a hard error naming the construct, never a wrong answer.

An xslt2 schema may still evaluate some things with XPath 1.0 semantics.

spec/xpath2/ is explicit about what is in, what is out, and the handful of places where that happens. Read it before depending on an xslt2 binding.

XPath 3.0

Function items and the operators built on them

An xslt3/xpath3 schema gets everything XPath 1.0 and 2.0 already provide, plus XPath 3.0's own additions: inline function expressions, named function references, and dynamic calls — the machinery a real for-each() needed — the arrow operator =>, string concatenation ||, the simple map operator !, the let expression, EQNames (Q{uri}local, naming an element or attribute by namespace URI directly — node name tests only, not variable or function names), and the rest of the higher-order sequence function library (filter, fold-left, fold-right, for-each-pair, function-lookup, function-arity, function-name). As with XPath 2.0, everything outside the documented subset is a hard error naming the construct.

Maps, arrays, and sort are XPath 3.1, not 3.0 — and stay refused.

spec/xpath3/ states exactly what is implemented, and why neither fn:sort nor union types in casts and signatures were ever actually XPath 3.0 gaps to begin with — the first does not exist until 3.1, and the second has no literal syntax in any version's grammar at all.

Measured

Against the reference implementation

Beyond the test suite, the crate is compared against the ISO Schematron reference implementation — the XSLT stylesheets that compile a schema into a validator — over the whole corpus. Twenty of twenty-three cases agree exactly; the other three are documented, and in each the difference is the reference's rather than this crate's.

sh tests/differential/fetch-skeleton.sh /tmp/skeleton
SCHEMATRON_SKELETON=/tmp/skeleton cargo test --test differential -- --ignored

The documented divergences include:

  • rules on text(), comment() and processing instructions, which the reference never fires;
  • a let that shadows an outer one, which the reference refuses outright;
  • a rule's @flag, which the reference drops.

Two checks

Lint asks one question; portability asks another

--lint reports constructs that are legal but almost certainly wrong — a shadowed rule, an unprefixed name in a namespaced schema, a variable or key nothing uses, a rule that reports nothing.

schematron --schema rules.sch --lint

--portability asks whether the schema will behave the same under another Schematron processor. What it reports is not wrong — it is correct, and works here, and the reference implementation treats it differently. Each of the seven checks is backed by a divergence in spec/conformance/, established by running both implementations against the same schema.

schematron --schema rules.sch --portability

They are separate on purpose, because a linter that reports correct code gets switched off.

The authoritative conformance document What is next, and what is not planned The whole specification