saxon:streamable - streamable assertions
Saxon (from 10.1) allows the attribute <xs:assert saxon:streamable="true">
to request that assertions be implemented using streaming.
This is useful to reduce memory requirements when validating large source documents, especially for assertions that apply to the root element of the document, or to another element with a large subtree.
If the attribute is present, Saxon will check at compile time that the assertion is actually streamable. If not, it will issue a warning and ignore the request.
A streamable assertion may either be:
motionless: the assertion only looks at the attributes of the element being validated, and not at its children or descendants. For example:
@discount lt @price
.consuming: the assertion can examine children or descendants of the element being validated, but it can only make one downwards selection.
For example, the assertion
count(x) mod 2 = 0
is streamable, because it only has one access to a child element. But the assertioncount(x) = count(y)
is not streamable, because there are two subexpressions that select downwards.
The rules for assessing streamability are the same as in XSLT 3.0. Specifically, the rules
that apply are those that apply to expressions in a boolean context such as xsl:if/@test
.
An assertion that refers to $value
is never streamable. (This variable is only
used with simple content, and elements with simple content are generally too small to justify
streamed evaluation anyway).
In the current implementation of streamable assertions, there are some minor deviations from the W3C XSD 1.1 specification in the way assertions are evaluated:
- The XPath expression is not prevented from accessing attributes of ancestors of the
element being validated (for example
../@xml:lang
). - The XPath expression has access to comments and processing instructions in the source document.
- The element on which the assertion is defined will carry its final type annotation, as if it were already validated.
When an assertion declared with saxon:streamable
is motionless,
Saxon always uses streamed evaluation. When the assertion is consuming, Saxon uses
streamed evaluation only if this avoids constructing an in-memory tree. If an in-memory
tree already exists (because some parent element has a non-streamable assertion), then
the consuming assertion is evaluated in non-streamed mode to take advantage of the existing
in-memory tree.