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)
Copyright © 2026 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and document use rules apply.
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.
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.
The publications of this community group are dedicated to our co-chair, Michael Sperberg-McQueen (1954–2024).
Template rules define the processing that can be applied to items that match a particular pattern.
In XSLT 4.0, patterns can match any kind of item: atomic items and function items as well as nodes.
A template rule identifies the items to which it applies by means of a pattern. As well as being used in template rules, patterns are used for numbering (see 12 Numbering), for grouping (see 14 Grouping), and for declaring keys (see 20.2 Keys).
[Definition: A pattern specifies a set of conditions on an item. An item that satisfies the conditions matches the pattern; an item that does not satisfy the conditions does not match the pattern.]
There are several kinds of pattern:
[Definition: A predicate pattern is written as . (dot) followed by zero or more predicates in square brackets, and it matches any item for which each of the predicates evaluates to true.]
The detailed semantics are given in 6.3.2.1 Predicate Patterns. This construct can be used to match items of any kind (nodes, atomic items, and function items). For example, the pattern .[starts-with(., '$')] matches any string that starts with the character $, or a node whose atomized value starts with $. This example shows a predicate pattern with a single predicate, but the grammar allows any number of predicates (zero or more).
[Definition: A type pattern is written as ~T (where T is an ItemTypeXP) followed by zero or more predicates in square brackets, and it matches any item of type T for which each of the predicates evaluates to true.]
The parameter T can also be a [TERMDEF IN XP40], consisting of a parenthesized sequence of item types separated by "|". For example, ~(array(*) | map(*)) matches arrays and maps, while ~(text() | comment()) matches text nodes and comment nodes.
The type pattern match="~(text() | comment())" has almost the same effect as the GNode patternmatch="text() | comment()", but the rules for calculating a default priority are different: see 6.3.3 Default Priority for Patterns.
[Definition: An GNode pattern uses a subset of the syntax for path expressions, and is defined to match a GNode if the corresponding path expression would select the GNode.]
The syntax for GNode patterns (GNodePattern in the grammar: see 6.3.2 Syntax of Patterns) is a subset of the syntax for expressions. GNode patterns are used only for matching nodes, and the same syntax may match either an XNode or a JNode. As explained in detail below, a GNode matches a GNode pattern if the equivalent XPath expression selects the GNode when evaluated with respect to some appropriate context.
Note:
The specification uses the phrases an item matches a pattern and a pattern matches an item interchangeably. They are equivalent: an item matches a pattern if and only if the pattern matches the item.
[Definition: If no priority attribute is specified on an xsl:template element, a default priority is computed, based on the syntactic form of the pattern supplied in the match attribute.] The default priority of a pattern is always greater than or equal to −1 (minus one), and less than 1 (plus one). The rules are as follows.
Unless otherwise specified, the default priority for a pattern is +0.5. For some simple patterns, listed below, there is a lower default priority in the range -1 (minus one) to +0.5.
For a TypePattern with no predicates, the default priority depends on the item type:
For a choice item type[TERMDEF IN XP40]XP, the default priority is the maximum priority of the item types included in the choice, computed according to the rules below.
For the item type item(), the default priority is −1.
For any item type that is a GNodeTypeXP, NodeKindTestXP or JNodeTypeXP (for example jnode(*), element(*) or element(N)), the default priority is the same as that of the corresponding GNode Pattern: see 6.3.3.3 Default Priority for GNode Patterns.
For the item type function(*), the default priority is −0.5.
For the item types array(*), map(*), and record(*), the default priority is −0.25.
For the item type xs:anyAtomicType, the default priority is −0.5.
For the 19 XSD-defined primitive atomic types, and for xs:untypedAtomic, the default priority is 0.
For an atomic type other than a primitive type, the default priority is a value greater than 0 (zero) and less than 0.5 that reflects its depth in the type hierarchy. Specifically, the priority is computed as 0.5 - 2^-N where N is the number of derivation steps from xs:anyAtomicType. This formula also works for primitive types. For example:
| Type | Depth (N) | Priority |
|---|---|---|
xs:decimal | 1 | 0 |
xs:integer | 2 | 0.25 |
xs:long | 3 | 0.375 |
xs:int | 4 | 0.4375 |
For an enum type, the default priority is 0.25.
For any other item type, the default priority is 0.
For a TypePattern having one or more predicates, the default priority is 0.5
If the pattern is a ParenthesizedPattern then the default priority is the default priority of the contained pattern.
If the pattern is a UnionExprP then the default priority is the maximum of the default priorities of the alternatives.
Note:
This is a backwards incompatible change from XSLT 3.0 and earlier versions, which treated the template rule as equivalent to multiple template rules with different priorities.
The change is made because of the increasing complexity of extending the rule to patterns like @(a|b), or attribute(a|b, xs:integer) which are defined to be semantically identical to equivalent union patterns; and to prevent confusion with type patterns such as type(element(a)|element(b)), where different rules apply.
The change affects any template rule with a union pattern that (a) has no explicit priority attribute, and (b) has multiple branches with different default priority. It is recommended that processors should output a compatibility warning when such template rules are encountered.
The change has two effects. Firstly, if two alternatives in a union pattern have different priority (for example in a pattern such as a | b/c, the priority of one of the branches will be raised to that of the other branch. Secondly, in cases where the same item matches both branches, a call on xsl:next-match will never cause the same template rule to be evaluated repeatedly.
If the pattern is an IntersectExceptExprP then the default priority of the pattern is that of the first operand pattern.
If the pattern is a PathExprP taking the form /, then the priority is −0.5.
If the pattern is a PathExprP taking the form of an EQName optionally preceded by a ForwardAxisP or has the form processing-instruction(StringLiteralXP) or processing-instruction(NCNameNames) optionally preceded by a ForwardAxisP, then the priority is 0.
If the pattern is a PathExprP taking the form of an ElementTestXP or AttributeTestXP, optionally preceded by a ForwardAxisP, then the priority is as shown in the table below. In this table:
The symbols E, A, and T represent an arbitrary element name, attribute name, and type name respectively;
The symbol W represents a WildcardXP other than * (for example prefix:* or *:local);
The symbol * represents itself.
The presence or absence of the symbol ? following a type name does not affect the priority.
Note:
The default priority of a pattern is always less than one, which means that user-allocated priorities greater than or equal to one will always rank higher than a defaulted priority.
| Format | Priority | Notes |
|---|---|---|
element() | −0.5 | (equivalent to *) |
element(*) | −0.5 | (equivalent to *) |
attribute() | −0.5 | (equivalent to @*) |
attribute(*) | −0.5 | (equivalent to @*) |
element(W) | −0.25 | |
attribute(W) | −0.25 | |
element(E) | 0 | (equivalent to E) |
element(*, T) | 0 | (matches by type only) |
attribute(A) | 0 | (equivalent to @A) |
attribute(*, T) | 0 | (matches by type only) |
element(W, T) | 0.125 | |
element(E, T) | 0.25 | (matches by name and type) |
schema-element(E) | 0.25 | (matches by substitution group and type) |
attribute(W, T) | 0.125 | |
attribute(A, T) | 0.25 | (matches by name and type) |
schema-attribute(A) | 0.25 | (matches by name and type) |
For a pattern such as element(A|B) or attribute(A|B) (more specifically, for any ElementTest or AttributeTest whose NameTestUnion contains more than one NameTest) the default priority is the highest of the priorities obtained by considering each of the NameTests individually.
For example, the default priority of element(x|y) is 0, and the default priority of element(p:*|q:*, t) is 0.125.
Note:
The effect of this rule is to make the pattern element(A|B) equivalent to element(A)|element(B).
If the pattern is a PathExprP taking the form of a DocumentTestXP, then if it includes no ElementTestXP or SchemaElementTestXP the priority is −0.5. If it does include an ElementTestXP or SchemaElementTestXP, then the priority is the same as the priority of that ElementTestXP or SchemaElementTestXP, computed according to the table above.
#any, and the pattern includes an unprefixed element name E, then the default priority is calculated as if this had been written *:E.If the pattern is a PathExprP taking the form of an NCNameNames:*, BracedURILiteralXP*, or *:NCNameNames, optionally preceded by a ForwardAxisP, then the priority is −0.25.
If the pattern is a PathExprP taking the form of any other NodeTestXP, optionally preceded by a ForwardAxisP, then the priority is −0.5.
The default priority of the pattern jnode(*, *) is -0.5.
The default priority of the equivalent pattern jnode(*, item()*) is also -0.5.
The default priority of the pattern jnode(S, *), where S is any constant, is 0 (zero).
The default priority of the equivalent pattern jnode(S, item()*), where S is any constant, is also 0 (zero).
The default priority of the pattern jnode(*, T), where T is any sequence type other than item()*, is 0 (zero).
The default priority of the pattern jnode(S, T), where S is any constant, and T is any sequence type other than item()*, is +0.25.
In all other cases, the default priority is +0.5.
Note:
In many cases this means that highly selective patterns have higher priority than less selective patterns. The most common kind of pattern (a pattern that tests for a node of a particular kind, with a particular expanded QName or a particular type) has priority 0. The next less specific kind of pattern (a pattern that tests for a node of a particular kind and an expanded QName with a particular namespace URI) has priority −0.25. Patterns less specific than this (patterns that just test for nodes of a given kind) have priority −0.5. Patterns that specify both the name and the required type have a priority of +0.25, putting them above patterns that only specify the name or the type. Patterns more specific than this, for example patterns that include predicates or that specify the ancestry of the required node, have priority 0.5.
However, it is not invariably true that a more selective pattern has higher priority than a less selective pattern. For example, the priority of the pattern node()[self::*] is higher than that of the pattern salary. Similarly, the patterns attribute(*, xs:decimal) and attribute(*, xs:short) have the same priority, despite the fact that the latter pattern matches a subset of the nodes matched by the former. Therefore, to achieve clarity in a stylesheet it is good practice to allocate explicit priorities.
Note:
The patterns element(N) and element(N, xs:anyType?) have different default priority even though they match exactly the same nodes. Conversely, element(N, xs:anyType) and element(N, xs:anyType?) have the same default priority even though the first is more restrictive (it does not match elements that are nilled).