SaxonForms Implementation Guide

DocBook workflow for architecture, behavior, and conformance mapping

Working draft for incremental chapter checkpoints


Table of Contents

1. Introduction to SaxonForms
Overview and scope
Guide structure
Primary use-cases
Terminology and conventions
Checkpoint validation focus
2. SaxonForms and SaxonJS
Component architecture
Subsystem roles
SEF compilation and runtime loading
Package map
Source file inventory
3. Processing Model (XForms 1.1 Chapter 4)
Event mapping: XForms to DOM/runtime events
Model construction phase
Deferred update cycle
Processing-cycle sequence diagram
4. Data Types and Model Item Properties
Data types and XSD support
Type normalization
Type validation
Type coercion in XPath evaluation
Model item properties to runtime/DOM mapping
readonly
relevant
required
constraint
Revalidate-to-refresh MIP state projection
calculate
Binding resolution
Data types and MIP propagation diagram
5. XPath and Controls
XPath expression mapping
Function rewriting (xforms:impose)
Context resolution in repeat and action scopes
XForms function library
Edge-case behavior
Controls and rendering model
Core form controls
Container controls
Custom controls and fork enhancements
6. Actions and Submission
Actions: XForms to implementation hooks
Action dispatch pipeline
Action map builder
Individual action templates
Action dispatch sequence diagram
Submission
Submission flow overview
Known submission issues
Submission sequence diagram
7. Conformance
Test suite coverage summary
Conformance levels
Production-ready features (≥90% pass rate)
Implementation-defined behavior
Implementation-dependent behavior
Known gap clusters
Recently resolved gaps
Checkpoint validation focus
8. Additional Topics
Reusable components
Property resolution (get-properties mode)
Context instance resolution (get-context-instance-id mode)
XPath evaluation functions
DOM field accessors
Refresh subsystem
Web Component Binding
Usage in XForms
XForms namespace attributes
Rendering (get-html mode)
Value synchronisation
Event handling
JavaScript bridge (xforms-javascript-library.xsl)
Complete example: TinyMCE rich text editor
Web component requirements
Accessibility
Keyboard navigation
Labels and descriptions
CSS class hooks for state
XSLT API reference
Lifecycle templates (saxon-xforms.xsl)
Action templates (saxon-xforms.xsl)
Function library (xforms-function-library.xsl)
XPath functions (xforms-xpath-functions.xsl)
XSD helpers (xsd-helpers.xsl)

SaxonForms implements XForms behavior using Interactive XSLT 3.0 and SaxonJS. This guide maps the XForms 1.1 specification to concrete runtime structures in the SaxonForms so developers can understand behavior, locate implementation points, and validate conformance incrementally.

SaxonForms is an implementation of XForms built with Interactive XSLT 3.0 and SaxonJS. It runs in the browser and is authored primarily in XSLT, using SaxonJS extension mechanisms for event handling and DOM updates.

The project started from a practical need: rewriting Saxonica's internal license-management application so more processing could move into XSLT and into the browser, with less Java-specific application code.

A key design goal is integration with application logic. For example, the form pipeline can be combined with custom XSLT logic to parse incoming order text, populate instance data, apply business rules during edits, and handle submission responses in-application.

Historical context and implementation details are discussed in the presentation at https://www.youtube.com/watch?v=GWvl7EhsocI.

This chapter defines subsystem boundaries between browser APIs, the SaxonJS runtime, and SaxonForms XSLT packages. These boundaries are the anchor model for all subsequent diagrams and chapter discussions.

SaxonForms operates within three major subsystems: the browser environment (DOM, event loop, JavaScript runtime), the SaxonJS 3 Interactive XSLT engine, and the SaxonForms XSLT runtime itself. The component diagram below is the anchor model for all other diagrams — package, sequence, and class representations stay consistent with these component boundaries.

This chapter maps lifecycle events and deferred processing behavior to SaxonForms runtime dispatch, recalculate/revalidate/refresh orchestration, and DOM updates.

The XForms processing model defines a lifecycle that begins with model construction and culminates in a ready state where the form is interactive. SaxonForms implements this lifecycle through named templates in saxon-xforms.xsl that execute in sequence during the xformsjs-main entry point template.

The xformsjs-main template in src/saxon-xforms.xsl orchestrates model construction:

  1. Document parsing — The XForms source is read from the page DOM via ixsl:page(). The source may be an embedded xforms:xform element or an XHTML document with XForms in the <head>. Namespace declarations are propagated via addNamespaceDeclarationsToDocument() in src/saxon-xforms.xsl.

  2. Model and instance resolution — Models ($models) and the default instance ($first-instance) are extracted in xformsjs-main. Default IDs are assigned if not present using $global-default-model-id and $global-default-instance-id.

  3. Submission map construction — The $submissions variable in xformsjs-main builds a map(xs:string, map(*)) of all xforms:submission elements, keyed by ID, containing method, resource, serialization, replace mode, and other attributes.

  4. xforms-model-construct — The xforms-model-construct template in src/saxon-xforms.xsl initializes each model: loads instance data (inline or from @src), saves initial instance snapshots for xf:reset, and stores instances in JavaScript global state.

  5. xforms-rebuild — The xforms-rebuild template processes xforms:bind elements via the add-context mode in src/saxon-xforms.xsl, resolving @nodeset paths to absolute references and annotating binds with @instance-context.

  6. xforms-recalculate — The xforms-recalculate template evaluates all @calculate, @relevant, @readonly, @required, and @constraint expressions on binds via xforms-recalculate-binding.

  7. Validation stage boundary — In the default construction path, SaxonForms performs xforms-rebuild and xforms-recalculate before dispatching xforms-model-construct-done. xforms-revalidate runs during deferred update cycles and submission validation rather than as a mandatory construction step.

  8. xforms-model-construct-done — Dispatched after construction completes. Action handlers bound to this event (e.g., setvalue on xforms-model-construct-done) execute here. Known issue: event handler execution during model construction does not always update instance values (4.2.2.b).

  9. Control rendering — XForms control elements are matched by the control-entry templates in src/saxon-xforms.xsl and transformed to HTML. The get-properties mode resolves data bindings for each control. The set-action mode builds action maps. The registerOutput template registers output controls for refresh tracking.

  10. xforms-ready — Dispatched when the form is fully initialized and rendered. The form enters the interactive state.

After each user interaction or action execution, SaxonForms runs the deferred update cycle: recalculate → revalidate → refresh. This cycle is triggered by:

The recalculate phase (xforms-recalculate) iterates binds and evaluates MIP expressions. The xforms-recalculate-binding template evaluates each bind's @calculate expression and updates the instance node value if changed. For non-incremental <select>/<select1> controls, the deferred cycle runs inline during onchange via dedicated ixsl:onchange handlers to avoid duplicate outer dispatch (resolved: 4.6.3.a/b/c).

The revalidate phase (xforms-revalidate) checks required fields, constraint expressions, and XSD type validity. During each cycle, validation MIP state (valid/required) is rebuilt into a runtime registry keyed by instance ID and binding reference, and validation state changes dispatch xforms-valid/xforms-invalid events (resolved: 6.1.6.a).

The refresh phase (xforms-refresh) updates the DOM to reflect current model state: refreshOutputs-JS updates output/control values and projects validation CSS classes from the revalidate registry, refreshRepeats-JS regenerates repeat content, refreshRelevantFields-JS shows/hides controls based on relevant MIP, and refreshElementsUsingIndexFunction-JS updates elements whose values depend on index().

This chapter documents data typing support (including XSD-derived constraints) and the mapping between XForms model item properties and runtime state propagation into rendered controls.

SaxonForms provides partial XSD type validation through the xsd-helpers.xsl package (~148 lines). Type validation occurs during the revalidate phase via check-instance-xsi-types() in src/saxon-xforms.xsl.

MIPs are defined on xforms:bind elements within xforms:model. During the rebuild phase, binds are processed by add-context mode in src/saxon-xforms.xsl to resolve their @nodeset to absolute instance paths. During recalculate, xforms-recalculate-binding evaluates each MIP expression.

This chapter maps XForms XPath semantics to XPath 3.1 execution in SaxonForms and explains control rendering and interaction patterns for standard and custom controls.

SaxonForms translates XForms XPath expressions into XPath 3.1 at evaluation time through a function-rewriting pipeline. The central rewriting function is xforms:impose() in src/xforms-function-library.xsl, which rewrites XForms function calls to their xforms:-prefixed XSLT equivalents so SaxonJS can evaluate them natively.

SaxonForms maps each XForms control element to an HTML element via get-html mode templates. The control rendering entry point is the control-match template in src/saxon-xforms.xsl, which processes all XForms control elements and delegates to get-html mode for HTML output generation.

The diagram below maps each XForms control to its HTML output element and the DOM event handlers that wire interactive behavior back into the action dispatch pipeline.

Each core control template resolves its data binding via the get-properties mode template in src/saxon-xforms.xsl, which returns a map containing the bound nodeset, instance context, and matching bind element. Key control templates:

This chapter documents action dispatch semantics, context resolution, and submission processing behavior including request serialization, headers, and response handling.

action-setvalue

Evaluates the @value expression or uses element text content to set the bound instance node. Delegates to action-setvalue-inner for XPath evaluation and to action-setvalue-form-control for DOM control update.

action-insert

Clones and inserts nodes into the instance. Supports @origin, @at, @position (before/after), and @context attributes. Uses insert-node mode for DOM-level insertion. Known issues: multi-instance @context resolution (10.3.a/c), @bind/@model crash (10.3.b), @at position evaluation (10.3.d, 10.4.d).

action-delete

Removes nodes from instances. Uses delete-node mode. Known issues: post-delete repeat index tracking (10.4.e/f).

action-toggle

Toggles visibility of xforms:case elements within a xforms:switch. The $source-control scoping mechanism exists in src/saxon-xforms.xsl but is not always passed through the event dispatch chain. Known issues: toggle inside repeat affects all iterations (9.3.1.f), case child @value precedence (10.6.1.b).

action-dispatch

Dispatches a named event to a target, supporting @targetid, @bubbles, @cancelable, and @delay. Known issue: cancelable="true" + ev:preventDefault does not prevent default action (10.8.f).

action-message

Displays a modal message via alert(). Known issue: model-level event messages (xforms-rebuild, xforms-reset, etc.) do not invoke the modal (10.13.a, 10.8.1.a/b, 8.1.8.a, 8.2.2.a–c, 8.2.3.a–c).

action-send

Triggers submission by looking up the submission map and invoking the submission flow.

action-setindex

Sets the repeat index for a given repeat ID.

action-setfocus

Sets focus to a control. Enhanced with suffixed-ID fallback and group→first-child focus (resolved: 9.1.1.c, 10.7.a).

action-reset

Restores instance data from initial snapshots saved during model construction (resolved: 10.a).

action-recalculate / action-revalidate / action-refresh

Explicitly trigger the corresponding lifecycle phase. action-revalidate invokes xforms-revalidate (including validation MIP registry rebuild used by refresh class projection) and clears the deferred revalidate flag.

action-script

Fork enhancement: XForms 2.0 script execution via ixsl:call(window, 'eval', ...).

action-load

Fork enhancement: Supports show="new" (window.open), show="replace" (location.href), and javascript: URI scheme.

This chapter records conformance claims and known implementation-defined behavior. It is synchronized with the latest W3C test status (tests/xforms/w3c/STATUS.md) and regression gate outputs.

SaxonForms is validated against the W3C XForms 1.1 Test Suite via Playwright end-to-end tests. Current coverage as of the latest regression gate run:

ChapterDescriptionTestsPassRate
5Datatypes151173%
6Model Item Properties11982%
7XPath Expressions621829%
8Core Form Controls595390%
9Container Form Controls211571%
10XForms Actions151173%
BInsert/Delete Patterns1515100%
Total 19813267%

Additionally, 24 fork-specific tests (14 feature tests + 10 issue regression tests) exist outside the W3C suite, with 22 passing.

This chapter covers reusable components, accessibility, BPMN workflow diagrams, and the XSLT API reference.

SaxonForms contains several reusable template and function patterns that are used across controls, actions, and submissions. The class diagram below shows the logical structure of these runtime components.

SaxonForms provides a generic mechanism for binding arbitrary HTML custom elements (web components) to XForms instance data. Any non-XForms element that carries an @xforms:ref attribute is treated as a bound web component control and participates in the XForms processing model identically to native controls.

This section provides a summary of the public API surface of SaxonForms — the named templates and functions that form the implementation contract.