View Old View New View Both View Only Previous Next

This draft contains only sections that have differences from the version that it modified.

W3C

XSL Transformations (XSLT) Version 4.0

W3C Editor's Draft 23 February 2026

This version:
https://qt4cg.org/specifications/xslt-40/
Latest version:
https://qt4cg.org/specifications/xslt-40/
Most recent Recommendation of XSL Transformations (XSLT):
https://www.w3.org/TR/xslt-30/
Editor:
Michael Kay, Saxonica <http://www.saxonica.com/>

The following associated resources are available: Specification in XML format, XSD 1.1 Schema for XSLT 4.0 Stylesheets (non-normative), Relax-NG Schema for XSLT 4.0 Stylesheets (non-normative), Stylesheet for XML-to-JSON conversion (non-normative)


Abstract

This specification defines the syntax and semantics of XSLT 4.0, a language designed primarily for transforming XML documents into other XML documents, but also offering support for other data formats including JSON, HTML, and CSV.

XSLT 4.0 is a revised version of the XSLT 3.0 Recommendation [XSLT 3.0] published on 8 June 2017. Changes are presented in 1.2 What’s New in XSLT 4.0?.

XSLT 4.0 is designed to be used in conjunction with XPath 4.0, which is defined in [XPath 4.0]. XSLT shares the same data model as XPath 4.0, which is defined in [XDM 4.0], and it uses the library of functions and operators defined in [Functions and Operators 4.0]. XPath 4.0 and the underlying function library introduce a number of enhancements, for example the availability of union and record types.

This document contains hyperlinks to specific sections or definitions within other documents in this family of specifications. These links are indicated visually by a superscript identifying the target specification: for example XP for XPath 4.0, DM for the XDM data model version 4.0, FO for Functions and Operators version 4.0, SG for XSLT Streaming version 4.0.

An optional feature of the XSLT language is support for streamed transformations. The XSLT 4.0 specification has been modularized so that streaming is now described in a separate specification document. This has been done in order to make the specifications more manageable, both for editors and readers: it does not alter the status of streaming as an optional feature, available in some processors and not others.

Status of this Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document.

This document is a working draft developed and maintained by a W3C Community Group, the XQuery and XSLT Extensions Community Group unofficially known as QT4CG (where "QT" denotes Query and Transformation). This draft is work in progress and should not be considered either stable or complete. Standard W3C copyright and patent conditions apply.

The community group welcomes comments on the specification. Comments are best submitted as issues on the group's GitHub repository.

The community group maintains two extensive test suites, one oriented to XQuery and XPath, the other to XSLT. These can be found at qt4tests and xslt40-test respectively. New tests, or suggestions for correcting existing tests, are welcome. The test suites include extensive metadata describing the conditions for applicability of each test case as well as the expected results. They do not include any test drivers for executing the tests: each implementation is expected to provide its own test driver.

Dedication

The publications of this community group are dedicated to our co-chair, Michael Sperberg-McQueen (1954–2024).


19 Accumulators

Accumulators were introduced in XSLT 3.0 to enable data that is read during streamed processing of a document to be accumulated, processed or retained for later use. However, they may equally be used with non-streamed processing.

[Definition: An accumulator defines a series of values associated with the nodes of the tree. If an accumulator is applicable to a particular tree, then for each node in the tree, other than attribute and namespace nodes, there will be two values available, called the pre-descent and post-descent values. These two values are available via a pair of functions, accumulator-before and accumulator-after.]

There are two ways the values of an accumulator can be established for a given tree: they can be computed by evaluating the rules appearing in the xsl:accumulator declaration, or they can be copied from the corresponding nodes in a different tree. The second approach (copying the values) is available via the snapshot and copy-of functions, or by use of the xsl:copy-of instruction specifying copy-accumulators="yes". Accumulator values are also copied during the implicit invocation of the snapshot function performed by the xsl:merge instruction.

Note:

Accumulators can apply to trees rooted at any kind of node. But because they are most often applied to trees rooted at a document node, this section sometimes refers to the “document” to which an accumulator applies; use of this term should be taken to include all trees whether or not they are rooted at a document node.

Accumulators can apply to trees rooted at nodes (such as text nodes) that cannot have children, though this serves no useful purpose. In the case of a tree rooted at an attribute or namespace node, there is no way to obtain the value of the accumulator.

The following sections give first, the syntax rules for defining an accumulator; then an informal description of the semantics; then a more formal definition; and finally, examples. But to illustrate the concept intuitively, the following simple example shows how an accumulator can be used for numbering of nodes:

Example: Numbering Figures within a Chapter

This example assumes document input in which figure elements can appear within chapter elements (which we assume are not nested), and the requirement is to render the figures with a caption that includes the figure number within its containing chapter.

When the document is processed using streaming, the xsl:number instruction is not available, so a solution using accumulators is needed.

The required accumulator can be defined and used like this:

<xsl:accumulator name="figNr" as="xs:integer" 
                    initial-value="0" streamable="yes">
     <xsl:accumulator-rule match="chapter" select="0"/>
     <xsl:accumulator-rule match="figure" select="$value + 1"/>
</xsl:accumulator>
   
<xsl:mode streamable="yes"/>
<xsl:template match="figure" expand-text="yes">
     <xsl:apply-templates/>
     <p>Figure {accumulator-before('figNr')}</p>
</xsl:template>

19.7 fn:accumulator-after

Summary

Returns the post-descent value of the selected accumulator at the context node.

Signature
fn:accumulator-after(
$nameas (xs:string | xs:QName)
) as item()*
Properties

This function is deterministicFO, context-dependentFO, and focus-dependentFO.

Rules

The $name argument specifies the name of the accumulator. The value of the argument must be either an xs:QName, or a string containing an EQName. If it is a lexical QName, then it is expanded as described in 5.1.1 Qualified Names (no prefix means no namespace).

The function returns the post-descent value A(N) of the selected accumulator where N is the context node, as defined in 19.4 Formal Model for Accumulators.

If the context item is a node in a streamed document, then the accumulator must be declared with streamable="yes".

Note:

The converse is not true: an accumulator declared to be streamable is available on both streamed and unstreamed nodes.

Error Conditions

The following errors apply: [see ERR XTDE3340], [see ERR XTDE3350], [see ERR XTTE3360], [see ERR XTDE3362], [see ERR XTDE3400].

For constraints on the use of accumulator-after when streaming, see 12.8.1 Streamability of the accumulator-after Function???SG.

Notes

The accumulator-after function can be applied to a node whether or not the accumulator has a phase="end" rule for that node. In effect, there is a phase="end" rule for every node, where the default rule is to leave the accumulator value unchanged; the accumulator-after function delivers the value of the accumulator after processing the explicit or implicit phase="end" rule.

In XSLT 4.0, the argument can be supplied as a QName literal, for example accumulator-before( #accum ).

Examples

Given the accumulator:

<xsl:accumulator name="w" initial-value="0" streamable="true" as="xs:integer">
   <xsl:accumulator-rule match="text()" 
                         select="$value + count(tokenize(.))"/>
</xsl:accumulator>

and the template rule:

<xsl:template match="section">
   <xsl:apply-templates/>
   (words: <xsl:value-of select="accumulator-after('w') - accumulator-before('w')"/>)
</xsl:template>

The stylesheet will output at the end of each section a (crude) count of the number of words in that section.

20 Additional Functions

Changes in 4.0  

  1. Functions that accept a lexical QName as an argument, such as key, function-available, element-available, type-available, system-property, accumulator-before, and accumulator-after, now have the option of supplying an xs:QName value instead. [This change was in the editor's draft accepted by the WG as its baseline when it started work.]   [  1 January 2022]

This section describes XSLT-specific additions to the XPath function library. Some of these additional functions also make use of information specified by declarations in the stylesheet; this section also describes these declarations.

20.3 fn:copy-of

Summary

Returns a deep copy of the sequence supplied as the $input argument, or of the context item if the argument is absent.

Signature
fn:copy-of(
$inputas item()*:= .
) as item()*
Properties

The zero-argument form of this function is nondeterministicFO, focus-dependentFO, and context-independentFO.

The one-argument form of this function is nondeterministicFO, focus-independentFO, and context-independentFO.

Rules

The zero-argument form of this function is defined so that copy-of() returns the value of internal:copy-item(.), where internal:copy-item (which exists only for the purpose of this exposition) is defined below. Informally, copy-of() copies the context item.

The single argument form of this function is defined in terms of the internal:copy-item as follows: copy-of($input) is equivalent to $input ! internal:copy-item(.). Informally, copy-of($input) copies each item in the input sequence in turn.

The internal:copy-item function is defined as follows:

<xsl:function name="internal:copy-item" as="item()" 
              new-each-time="maybe">
  <xsl:param name="input" as="item()"/>
  <xsl:copy-of select="$input" 
               copy-namespaces="yes"
               copy-accumulators="yes"
               validation="preserve"/>
</xsl:function>

The streamability analysis, however, is different: see 12.8 Classifying Calls to Built-In Functions???SG.

The use of new-each-time="maybe" in the above definition means that if the internal:copy-item function is called more than once with the same node as argument (whether or not these calls are part of the same call on copy-of), then it is implementation-dependent whether each call returns the same node, or whether multiple calls return different nodes. Returning the original node, however, is not allowed, except as an optimization when the processor can determine that this is equivalent.

Note:

One case where such optimization might be possible is when the copy is immediately atomized.

Notes

The copy-of function is available for use (and is primarily intended for use) when a source document is processed using streaming. It can also be used when not streaming. The effect, when applied to element and document nodes, is to take a copy of the subtree rooted at the current node, and to make this available as a normal tree: one that can be processed without any of the restrictions that apply while streaming, for example only being able to process children once. The copy, of course, does not include siblings or ancestors of the context node, so any attempt to navigate to siblings or ancestors will result in an empty sequence being returned.

All nodes in the result sequence will be parentless.

If atomic items or functions (including maps and arrays) are present in the input sequence, they will be included unchanged at the corresponding position of the result sequence.

Accumulator values are taken from the copied document as described in 19.10 Copying Accumulator Values.

Examples

Using copy-of() while streaming:

This example copies from the source document all employees who work in marketing and are based in Dubai. Because there are two accesses using the child axis, it is not possible to do this without buffering each employee in memory, which can be achieved using the copy-of function.

<xsl:source-document streamable="yes" href="employees.xml">
  <xsl:sequence select="copy-of(employees/employee)
                          [department='Marketing' and location='Dubai']"/>
</xsl:source-document>

22 Arrays

Arrays are defined in the XDM Data Model: see [XDM 4.0] section 8.3 Array Items.

22.2 Arrays and Streaming

As with maps (see 12.1 Maps and Streaming???SG) arrays cannot contain references to streamed nodes, because all expressions, instructions, and functions that construct arrays are defined to have operand usage .

Unlike maps, array constructors have no special rules allowing the members of the array to be constructed using multiple consuming subexpressions.