What Is a Motionless Expression in XSLT 3.0?
In XSLT 3.0 streaming, a motionless expression is an XPath construct that does not advance the reader position or consume tokens from the underlying input document stream during evaluation. Streaming engines evaluate expressions based on static analysis properties called posture and sweep; an expression classified with a motionless sweep can inspect properties of the current node, read static values, or access pre-buffered data without changing the stream's cursor position. Understanding what constitutes a motionless expression is essential for writing valid, streamable stylesheets that process arbitrarily large XML documents in a single pass.
The Role of Sweep in XSLT 3.0 Streamability
XSLT 3.0 enforces rigorous streamability rules to ensure documents can be processed without building a complete in-memory Document Object Model (DOM) tree. The static analysis categorizes every construct using two core metrics:
- Posture: Describes the type of node reference the expression returns relative to the stream (e.g., grounded, striding, climbing, or roaming).
- Sweep: Describes how the evaluation of an expression moves the stream pointer. Sweep falls into three main categories: motionless, consuming, or free-ranging.
An expression has a motionless sweep if evaluating it requires zero forward movement along the document stream. Because the stream cursor remains unchanged, a motionless expression can be executed without preventing subsequent sibling expressions or template rules from reading the current node or its descendant content.
Key Characteristics of Motionless Expressions
An expression qualifies as motionless under the W3C XSLT 3.0 specification when its execution depends solely on data that is already available in memory or accessible without advancing the stream:
- No Forward Stream Navigation: The expression does
not traverse the
child::,descendant::, orfollowing-sibling::axes of unparsed nodes in the stream. - Repeated Evaluability: Because it does not exhaust or alter the incoming stream data, a motionless expression can safely be evaluated multiple times, such as within loop conditions or multiple predicates.
- Instantaneous Context Access: It can access instantaneous properties of the context item, such as its node kind, name, type annotation, or attributes, provided the parser has already read the opening tag.
Common Examples of Motionless Constructs
Several categories of XPath expressions satisfy the criteria for being motionless in a streaming context:
Literal Values and Static Calculations
Any atomic value, string literal, boolean constant, or arithmetic operation involving only static values is motionless:
'sample text'42 + 10true()
Variables and Grounded References
References to parameters or variables that hold atomic values, grounded sequences, or pre-constructed document fragments do not move the input stream:
$itemCount$configDoc//setting(where$configDocis loaded as a separate, grounded in-memory tree)
Context Node Inspection and Attributes
Accessing properties or attributes of the element currently positioned under the stream reader is motionless because attribute data is read during the opening tag event:
.(the context item itself)@idorattribute::statusname(),local-name(), andnamespace-uri()self::element(record)
Calls to Functions with Motionless Arguments
Standard XPath functions that operate strictly on motionless arguments or grounded inputs retain a motionless sweep:
string-length(@name)concat('ID-', @id)exists($preloadedSequence)contains(local-name(), 'data')
Why Motionless Expressions Are Critical for Streamed Stylesheets
Motionless expressions serve as the backbone for control flow in
streamed templates. Constructing conditional logic using
xsl:if, xsl:choose, or XPath
if (...) then ... else ... expressions requires the test
condition to be motionless when the conditional branch itself consumes
the stream.
If a test expression consumed nodes from the stream, the stream position would advance past those nodes, leaving the subsequent transformation branch unable to process the child data. By ensuring that conditional checks, variable declarations, and sorting keys remain motionless, developers can build robust streaming pipelines that reliably filter, validate, and route massive XML datasets.