Saxon extensions to the W3C XSLT/XQuery specifications
Changes to existing Saxon extensions and new extensions in Saxon 12 are outlined below. This includes
extension functions and instructions in the saxon
namespace, as well as
experimental implementations for version 4.0 extensions to XPath, XSLT, and XQuery. A W3C
Community Group is working on these proposals; for more information see the QT4CG Specifications, and documentation about the Saxon
implementations at Experimental 4.0 extensions.
New Extension Functions
A number of proposed 4.0 functions are implemented (see New functions):
fn:all()
, fn:all-different()
, fn:all-equal()
, fn:characters()
,
fn:contains-sequence()
, fn:ends-with-sequence()
,
fn:expanded-QName()
, fn:foot()
, fn:highest()
, fn:identity()
, fn:index-where()
,
fn:in-scope-namespaces()
, fn:intersperse()
, fn:is-NaN()
,
fn:items-after()
, fn:items-at()
, fn:items-before()
, fn:items-ending-where()
, fn:items-starting-where()
,
fn:iterate-while()
, fn:lowest()
, fn:op()
, fn:parcel()*
,
fn:parse-html()
, fn:parse-QName()
, fn:parts()*
,
fn:replicate()
, fn:some()
, fn:starts-with-sequence()
,
fn:trunk()
, and fn:unparcel()*
. Specifications of these functions
can be found in the QT4CG draft specification.
The proposed 4.0 functions map:build()
and map:filter()
are implemented.
The proposed 4.0 functions array:empty()
, array:exists()
,
array:foot()
, array:index-where()
, and array:trunk()
are implemented.
From Saxon 12.1:
-
The
options
parameter offn:deep-equal()
is implemented. -
The
fn:atomic-equal()
function is implemented. -
The
fn:slice()
function (available in 12.0) is dropped. -
The functions
fn:build-uri()
andfn:parse-uri()
are implemented.
Dropped or Changed Extension Functions
The Saxon extension functions saxon:evaluate()
, saxon:eval()
, and saxon:expression()
have been dropped. (The function saxon:evaluate-node()
was dropped in Saxon 10).
The same effect (and more) can be achieved using the standard XSLT 3.0 instruction
xsl:evaluate.
The Saxon extension function saxon:in-scope-namespaces() has been
aligned with the proposed 4.0 function fn:in-scope-namespaces()
in that the returned map now always includes an entry for the
XML namespace.
The extension function saxon:parse-html() is now a synonym for
fn:parse-html()
, a new function proposed for 4.0. The function has been reimplemented on SaxonJ to use the
validator.nu
library in place of TagSoup
. In SaxonCS, it has been reimplemented to use AngleSharp
in place of HtmlAgilityPack
. In both cases this gives much closer conformance to the HTML5 parsing algorithm; the function
has also been much more thoroughly tested. However, a handful of the 1300 new tests are currently giving unexplained results (some of
these may turn out to be correct), so it remains work in progress.
XPath 4.0 Syntax Extensions
Some experimental syntax extensions intended for 4.0 have been dropped. "Dot Functions" (written as .{.+1}
or fn{.+1}
)
are now written as ->{.+1}
. "Underscore functions" (written as _{$1 + $2}
) are dropped
entirely (write instead ->($p1, $p2){$p1 + $p2}
).
Union NodeTests are implemented. This feature allows steps such as ancestor::(div1|div2|div3)
,
@(id|name)
, and following-sibling::(comment()|processing-instruction())
.
Static function calls may supply arguments by keyword as well as by position.
From Saxon 12.1, XPath 4.0 string templates are implemented.
Example: let $message := `{$day} of {$month}, {$year}`
.
From Saxon 12.1, XPath "braced if" expressions are implemented. Examples:
-
if ($condition) {<x>It's true</x>}
-
if ($condition) {<x>It's true</x>} else {<x>It's a lie</x>}
-
if ($condition) {<x>It's true</x>} else if ($polite) {<x>He mis-spoke</x>} else {<x>It's a lie</x>}
XQuery 4.0 extensions
Function declarations may declare some parameters as optional, with a default value. From Saxon 12.1, the default
value must either be a constant (for example, ()
, 0
, false()
, or
""
), or the context item expression .
. This restriction is imposed pending clarification
of the specification.
XSLT extensions
If XSLT 4.0 extensions are enabled, two new (experimental) values are available for xsl:mode/@on-no-match
,
namely shallow-copy-all
and shallow-skip-all
. These have the same effect as shallow-copy
and shallow-skip
respectively, except when processing maps and arrays.
For shallow-skip-all
:
- When processing an array that does not match any template rule, the array
is split into a set of parcels, one for each member of the array, and each parcel is processed by making
an implicit call on
xsl:apply-templates
. A parcel is represented as a single-entry map with the key"value"
, and can be matched using the patternmatch="record(value)"
. The value of the array member can be extracted from the parcel using the functionfn:unparcel()
. If a parcel does not match any template rule, then it will not be processed. - When processing a map that does not match any template rule, the map
is split into a set of map entries, one for each key-value pair in the map. These entries are represented
as singleton maps, and they are processed by making an implicit call on
xsl:apply-templates
. However, if a singleton map does not match any template rule, then to prevent infinite recursion it is not processed at all.
For shallow-copy-all
:
- When processing an array that does not match any template rule, a new array is created. The existing array
is split into a set of parcels, one for each member of the array, and each parcel is processed by making
an implicit call on
xsl:apply-templates
. A parcel is represented as a single-entry map with the key"value"
, and can be matched using the patternmatch="record(value)"
. The value of the array member can be extracted from the parcel using the functionfn:unparcel()
. - When processing a map that does not match any template rule, a new map is created. The existing map
is split into a set of map entries, one for each key-value pair in the map. These entries are represented
as singleton maps, and they are processed by making an implicit call on
xsl:apply-templates
. Any template rule that processes such a singleton map is required to return a result that is a map. The resulting maps are merged, effectively by callingmap:merge()
with theduplicates
option set touse-last
. If a singleton map does not match any template rule, then it is effectively skipped.
The experimental @array
and @map
attributes of xsl:for-each
,
xsl:for-each-group
, and xsl:iterate
added in Saxon 11 are dropped. In their place, use
select="array:members($array)"
or select="map:key-value-pairs($map)"
.
The proposed instruction xsl:match
added in Saxon 11 has been dropped.
Function declarations (xsl:function
) may declare some parameters as optional,
with a default value. From Saxon 12.1, the default
value must either be a constant (for example, ()
, 0
, false()
, or
""
), or the context item expression .
. This restriction is imposed pending clarification
of the specification.