node-schematron
The `node-schematron` package provides a pure JavaScript implementation of the Schematron validation language, designed for use in Node.js environments, web browsers (with bundlers like Webpack), and as a command-line interface (CLI) tool. As of version 2.1.0, it offers a robust solution for validating XML documents against Schematron schemas, returning results as a JSON object. Key differentiators include its complete JavaScript implementation, avoiding native dependencies, and support for Schematron includes and various CLI options for file globbing and output reporters. The library utilizes `fontoxpath` for XPath 3.1 queries, though it notes that `fontoxpath` is not yet feature-complete. While there's no explicit release cadence, the project appears actively maintained, offering a flexible and integrated Schematron solution for JavaScript ecosystems.
Common errors
-
ENOENT: no such file or directory, stat '/path/to/include/files/file.xml'
cause A Schematron schema uses `<include href="file.xml" />` but the `resourceDir` option was not provided or points to an incorrect location, preventing the included file from being found.fixEnsure the `resourceDir` option in `Schema.fromString()` or `Schema.fromFileSync()` points to the correct directory containing the included Schematron files. For CLI, verify `schematronLocation` and any paths referenced within the schema. -
Error: XPath error: "Cannot convert XdmValue to single value: multiple values encountered"
cause An XPath expression in an `assert` or `report` test, or a `value-of` select, evaluates to a sequence of multiple items where a single item is expected (e.g., trying to compare `//element` with a string, when `//element` matches multiple elements).fixRefine the XPath expression to ensure it selects a single node or atomic value, or explicitly handle sequences using XPath functions like `string-join()`, `count()`, `head()`, `tail()`, or predicates like `[1]` to select a specific item from the sequence. -
Error: (XPath error) Cannot parse XQuery/XPath expression: Unexpected token "|" at position X
cause A syntax error in an XPath expression within a Schematron rule, often due to a typo or incorrect XPath syntax for the XPath 3.1 query language.fixCarefully review the XPath expression for syntax errors. Validate the XPath against an XPath 3.1 validator. Pay attention to common pitfalls like incorrect axis specifiers, mismatched parentheses, or improper use of operators.
Warnings
- gotcha The underlying XPath 3.1 implementation, `fontoxpath`, is noted as not yet feature-complete. Users relying on advanced or less common XPath 3.1 functions might encounter unsupported features or unexpected behavior.
- gotcha Schematron's rule matching behavior can be counter-intuitive: within a single pattern, a node will only match the *first* rule whose context matches it. Subsequent rules in the same pattern for that node will not be evaluated, even if their contexts also match.
- gotcha The library explicitly states that XSLT functions (`<xsl:function>`) are not supported. While there was a feature branch, it remains unimplemented.
- gotcha Some ISO/IEC 19757-3 2016 (Schematron) attributes are not supported, including `@abstract`, `@diagnostics`, `@icon`, `@see`, `@fpi`, `@flag`, `@role`, and `@subject` in certain contexts.
- gotcha When using `resourceDir` for schema includes, ensure the path is correct and accessible. Incorrect paths will lead to `file not found` errors, and the CLI tool may default to `*.xml` if `globPattern` is not used correctly or `schematronLocation` is relative and ambiguous.
Install
-
npm install node-schematron -
yarn add node-schematron -
pnpm add node-schematron
Imports
- Schema
const { Schema } = require('node-schematron');import { Schema } from 'node-schematron'; - registerCustomXPathFunction
const { registerCustomXPathFunction } = require('node-schematron');import { registerCustomXPathFunction } from 'node-schematron'; - validateString
Schema.validateString('<xml/>', options);schema.validateString('<xml/>', options);
Quickstart
import { Schema } from 'node-schematron';
const schematronSchema = `
<schema xmlns="http://purl.oclc.org/dsdl/schematron">
<pattern>
<rule context="thunder">
<let name="lightning" select="@foo"/>
<report test="$lightning = 'bar'">
Skeet boop <value-of select="$lightning" />
</report>
<assert test="@type = 'storm'">
Thunder must have a 'type' attribute with value 'storm'.
</report>
</rule>
<rule context="xml">
<assert test="count(thunder) > 0">
XML document must contain at least one thunder element.
</assert>
</rule>
</pattern>
</schema>`;
const schema = Schema.fromString(schematronSchema);
const xmlToValidate = `
<xml foo="err">
<thunder foo="bar" type="storm" />
</xml>`;
const results = schema.validateString(xmlToValidate, { debug: true });
console.log(JSON.stringify(results, null, 2));
/* Expected Output for the report (assertion passes):
[
{
"isReport": true,
"context": "<thunder foo="bar" type="storm"/>",
"message": "\n\t\t\t\tSkeet boop bar\n\t\t\t"
}
]
*/