The schematron package implements a rules-based XML validation engine that complements grammar-based validators like XSD and RELAX NG. It targets complex, context-sensitive rules by leveraging XPath for expressing conditions and message generation. The package follows a compile-then-validate pattern, parsing the Schematron XML into an internal Schema structure before applying the rules to an XML document. Key features include three-phase parsing (title, namespaces, patterns), the rule-assert-report model, message interpolation with embedded XPath, scoped variable bindings via <let>, and XPath-based assertion evaluation.
Schematron compilation involves transforming the declarative XML form of a Schematron schema into a runtime representation with compiled XPath expressions. This three-phase parse strategy organizes schema information progressively, ensuring static namespaces and XPath expressions are available for validation.
The compilation proceeds in three distinct phases:
Phase 1 – Title Extraction
The parser first extracts the optional <title> element's text content from the root <schema>. This title describes the schema and is stored as a string property on the Schema struct.
Phase 2 – Namespace Registration
The package processes all <ns> child elements that declare namespace prefix-to-URI bindings. These mappings populate the namespaces map on Schema, establishing a static, global namespace context used by all XPath expressions during validation.
Phase 3 – Patterns and Rules
Finally, it collects all <pattern> elements, each containing multiple <rule>s. Each rule declares a context XPath expression to select nodes on which assertions and reports apply.
Within each rule:
<let> declarations bind variables to XPath expressions with lexical scoping.<assert> elements specify tests that fail validation if their XPath test evaluates to false.<report> elements specify tests that fail if their XPath test evaluates to true.For all applicable XPath expressions — in context, test, and select attributes — the package uses the xpath3 engine to compile them into *xpath.Expression for efficient runtime evaluation.
This phased approach ensures namespace mappings are established prior to compiling XPath expressions, maintaining correctness and reducing repeated work during validation.
Validation messages inside <assert> and <report> elements are not treated as raw strings but parsed into a sequence of typed messagePart values:
<name path="..."/>: Produces the QName of the current node or a node selected by XPath relative to the context node.<value-of select="..."/>: Evaluates an XPath expression and inserts its string value dynamically.These components are concatenated during validation to produce clear, context-sensitive error or report messages.
The schematron package performs validation by iterating all compiled patterns and applying their rules against the target XML document.
Create XPath Context:
Each validation run starts by creating an XPath evaluation context xpath3.NewContext() seeded with the schema's static namespace bindings.
Pattern and Rule Matching:
For every rule, the contextExpr XPath expression is evaluated against the input document to obtain the subset of nodes (context nodes) for which this rule applies.
Let Variable Binding:
For each node selected by the context expression:
<let> expressions are evaluated sequentially.Test Evaluation:
Each <assert> or <report> test is evaluated as follows:
<assert test="condition"/>: If the expression evaluates to false (Effective Boolean Value), the assertion has failed and a validation error is recorded.<report test="condition"/>: If the expression evaluates to true, this is considered a failure condition as well.Message Formatting and Error Reporting:
On failure, the message template parts are interpolated, substituting dynamic names and evaluated expressions. A ValidationError is constructed with detailed location info and the generated message. This error is delivered to the configured ErrorHandler.
The internal data model closely represents the Schematron XML, with explicit support for XPath expressions compiled to the xpath3 package.
| XML Element | Go Type / Field | Description |
|---|---|---|
<schema> | schematron.Schema | Root container holding namespaces and patterns |
<ns prefix="x" uri="..."> | Schema.namespaces map[string]string | Namespace prefix to URI map (static XPath namespace context) |
<pattern> | schematron.pattern | Group containing multiple rules |
<rule context="..."> | schematron.rule | Defines rule context XPath, lets, asserts, reports |
<let> | schematron.letBinding | Scoped variable binding with compiled XPath expr |
<assert test="..."> | schematron.test | Assertion with test XPath expression and message parts |
<report test="..."> | schematron.test | Report test, triggers error if condition true |
This diagram illustrates how the Schematron XML constructs map directly to key Go structs and types, including XPath 3.1 compiled expressions.
Sources: schematron/schematron.go50-110
This flow shows the full pipeline from Schematron XML parsing, compilation of rules and tests to runtime validation of an XML document, including let bindings and message interpolation.
Sources: schematron/validate.go20-90
schematron.Parse(ctx context.Context, doc *helium.Document) (*Schema, error)
Parses the root <schema> element, running three-phase parsing and compiling XPath expressions for rules, lets, asserts, and reports.
Sources: schematron/schematron.go40-42
compilePattern(patNode Node) (*pattern, error)
Parses a <pattern> element node extracting its rules.
Sources: schematron/schematron.go112
compileRule(ruleNode Node) (*rule, error)
Compiles a single <rule> element, including compiling the context XPath and its nested let/test elements.
Sources: schematron/schematron.go130
compileTest(testNode Node) (*test, error)
Parses <assert> or <report>, compiles test XPath expressions and parses message parts.
Sources: schematron/schematron.go160
Validate(ctx context.Context, schema *Schema, doc *helium.Document) error
The main validation function which runs all patterns and rules on the document, evaluates tests with let bindings, aggregates and reports errors.
Sources: schematron/validate.go20
(mp messagePart) Interpolate(ctx context.Context, node Node, lets map[string]any) string
Interpolates message components, substituting XPath name or value-of evaluations in the current context.
Sources: schematron/schematron.go200
<let> elements inside a <rule> declare XPath expressions bound to a variable name, which are:
<let>, <assert>, and <report> tests.This scoping mechanism extends XPath's evaluation context with custom-defined external variables handled by the package's XPath environment.
Schematron validation hinges on XPath expressions:
context XPath expression of a rule selects the set of nodes for which the rule applies.<assert> and <report> contains a test XPath expression evaluated under the current node.<value-of> elements in messages use select XPath expressions to extract values dynamically.The package employs the xpath3 engine, supporting XPath 3.1 fully, compiling all expressions at parse-time for maximum runtime efficiency.
During validation:
Upon test failures, the package generates ValidationError instances that:
ErrorHandler interface.The interpolation process involves concatenating:
<name> QNames from the current or selected node.<value-of> XPath expression results converted to strings.The schematronError() function in schematron/errors.go formats these errors as {file}:{line}: element {elem}: schematron error : {path} line {line}: {msg}\n, noting that the line number appears twice. schematron/errors.go10
Validation returns a sentinel error (ErrValidationFailed) on any failed assertion or report, allowing callers to detect overall outcome easily.
Sources: schematron/errors.go10
The schematron package in helium provides a robust rule-based XML validation facility built on XPath 3.1. It rigorously separates parsing and compilation from execution, supports rich, XPath-aware message interpolation, and manages variable scoping cleanly. Its design allows expressive, complex validation rules with efficient runtime execution, suitable for demanding XML validation scenarios.
Sources:
schematron/schematron.go30-110
schematron/validate.go20-90
.claude/docs/validation-pipeline.md120-160
.claude/docs/error-formatting.md70-80
Refresh this wiki
This wiki was recently refreshed. Please wait 1 day to refresh again.