Saxon-Forms
Saxon-Forms is an XForms implementation written using Interactive XSLT 3.0. Interactive XSLT 3.0 is a feature of Saxon-JS, which is an XSLT 3.0 run-time written in pure JavaScript for use in the browser or a platform that supports JavaScript.
See conference papers below:
Implementing XForms using interactive XSLT 3.0. XML Prague 2018.
Distributing XSLT Processing between Client and Server. XML London 2017.
Quickstart (5 minutes)
For first-time contributor onboarding, run:
npm run setup
npm run doctor
npm run verify:setup
Prerequisites
- Node.js + npm
- Saxon-JS 3 runtime assets available in
Saxon-JS/(or copied to your hosting location)
Saxon-JS can be downloaded at Saxon-JS (older versions available at the archive).
1) Bootstrap environment
npm run setup
2) Build Saxon-Forms SEF
npm run build:sef
This generates sef/saxon-xforms.sef.json and syncs it into test-app/sef/saxon-xforms.sef.json.
3) Run examples locally
npm run examples
Then open http://127.0.0.1:5174/ and start with:
examples/hello.htmlexamples/native-xforms-fiddle.htmlexamples/sample1.html(direct XForms-source loading)examples/sample2.html(restored legacy sample page)examples/sample3.html(restored legacy sample page)
npm run examples starts a local server and continues running until you stop it manually.
4) Run end-to-end tests (Playwright)
npm run test:e2e
Run with a specific browser mode:
npm run test:e2e:chrome
npm run test:e2e:firefox
npm run test:e2e:both
Or pass the harness flag directly:
npm run test:e2e -- --browser=firefox
To run tests interactively:
npm run test:e2e:ui
Common commands
- Build SEF:
npm run build:sef - Run all examples:
npm run examples - Compile stylesheet-driven examples on demand:
npm run examples:compile - Fetch W3C suite:
npm run fetch:w3c - Fetch NIST xsdtests dataset:
npm run fetch:nist - Build precomputed NIST Playwright case index:
npm run build:nist-engine-index - Run e2e in Chrome only:
npm run test:e2e:chrome - Run e2e in Firefox only:
npm run test:e2e:firefox - Run e2e in both browsers:
npm run test:e2e:both - Run full e2e flow (prepare + build + test):
npm run test:e2e:full - Run xsd helper tests:
npm run test:xsd-helpers - Run NIST facet harness with Saxon-Forms engine:
npm run test:nist-facets - Run NIST facet inventory by datatype families:
npm run test:nist-facets:inventory - Run diagnostics tests:
npm run test:e2e:diagnostics
NIST Playwright engine index
tests/xsd/nist/nist-facets-engine.spec.ts reads precomputed case data from:
tests/xsd/nist/.cache/nist-engine-case-index.json
Generate/update this file with:
npm run build:nist-engine-index
Use a custom index path for experimentation by setting NIST_ENGINE_CASE_INDEX to an absolute or repo-relative JSON path.
Troubleshooting
- If W3C tests are missing assets, run
npm run fetch:w3c. - If NIST workflows are missing assets, run
npm run fetch:nist. - If
tests/xsd/nist/nist-facets-engine.spec.tsreports missing index data, runnpm run build:nist-engine-index. - If runtime output looks stale, rerun
npm run build:sef. - If docs builds fail, ensure
antis on PATH (or use--ant-binwithscripts/run-docbook-build.mjs).
Contributing
See CONTRIBUTING.md for development workflow, validation expectations, and PR standards.
For complete machine/bootstrap setup (including external datasets and tools), see SETUP.md.
Support expectations
Saxon-Forms support maturity is tracked by conformance behavior and implementation coverage.
- Supported and stable: core controls, many processing model actions, and major portions of chapter-based W3C tests.
- Partial support: areas with known behavioral gaps or edge-case limitations.
- In progress: features tracked as active gaps in conformance status.
For current details:
tests/xforms/w3c/STATUS.mdfor live gap and resolution trackingdocs/docbook/for implementation architecture and behavior mapping
If you are evaluating feature readiness for production, use those files as the source of truth.
Documentation workflow (DocBook + ant4docbook)
The repository now includes a DocBook-based implementation guide under docs/docbook/, with chapter-level checkpoints and standalone UML/BPMN references.
Prerequisite for DocBook builds:
-
Install Apache Ant and ensure
antis available on PATH (or provide a custom path via--ant-bininscripts/run-docbook-build.mjs). -
Validate DocBook sources, XInclude targets, and checkpoint metadata:
npm run docs:docbook:validate
-
Build DocBook HTML + PDF using the local
ant4docbook-0.10.0distribution:npm run docs:docbook:build
-
Build only one output format:
npm run docs:docbook:build -- --format=htmlnpm run docs:docbook:build -- --format=pdf
-
List checkpoint definitions and targeted chapter test commands:
npm run docs:docbook:checkpoints
Generated DocBook outputs are written to builds/docs-docbook/.
GitHub Pages documentation site (CI/CD)
The repository supports an assembled static docs site artifact under builds/site/.
This includes:
- Curated markdown docs (allowlisted)
- DocBook implementation guide HTML output
- Published
examples/pages and required runtime assets
Build and validate locally:
npm run site:buildnpm run site:validate
The CI workflow .github/workflows/pages-docs.yml builds and validates this artifact on pull requests, and deploys to GitHub Pages on pushes to the default branch.
Note on examples in static hosting:
- Most examples render normally on Pages.
- Endpoint-backed submission demos (paths such as
/api/test,/api/echo,/api/book-submit) require the local examples server for full behavior (npm run examples).
Cryptographic Functions (Optional)
The XForms digest() and hmac() functions require the
@noble/hashes library (MIT license).
These functions are optional — forms that do not
use digest() or hmac() work without it. When the library is not loaded,
these functions return an empty string instead of crashing.
Quick setup
-
Install the dependency:
npm install @noble/hashes -
Build the crypto bundle:
node scripts/build-crypto.mjsThis produces
builds/saxon-forms-crypto.js(~14 KB, 6 KB gzipped). -
Load the bundle before Saxon-Forms in your HTML:
<script src="saxon-forms-crypto.js"></script> <!-- then load SaxonJS and your XForm as usual -->
CDN alternative
If you prefer not to install locally, you can load the pre-built bundle from
your own CDN or copy builds/saxon-forms-crypto.js alongside your other assets.
What happens without it
If the crypto bundle is not loaded, digest() and hmac() return empty strings.
Forms that use these functions will render normally but any conditional logic
that depends on hash values (e.g. ref="self::node()[digest(...) = '...']")
will not match.