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.

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 3.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.

Status of this Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.

This document has no official standing. It is produced by the editor as a proposal for community review. Insofar as it copies large amounts of text from the W3C XSLT 3.0 Recommendation, W3C copyright and similar provisions apply.

Dedication

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


5 Features of the XSLT Language

5.4 Patterns

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 three kinds of pattern: predicate patterns, type patterns, and node patterns:

  • [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.]

    A predicate pattern .[P1][P2]... can be regarded as an abbreviation for the type pattern type(item())[P1][P2]....

    The detailed semantics are given in 5.4.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 can be written as type(T) (where T is an ItemTypeXP followed by zero or more predicates in square brackets, and it matches any item of type T which each of the predicates evaluates to true.]

    The parameter T can also be a list of item types, separated by "|". For example, type(array(*) | map(*)) matches arrays and maps, while type(text() | comment()) matches text nodes and comment nodes.

    The most commonly used type patterns can be abbreviated. For example, match="type(record(F1, F2, *))" can be abbrevated to match="record(F1, F2, *)", and match="type(array(xs:string))" can be abbreviated to match="array(xs:string)". The main case where such abbreviation is not possible is with atomic items: match="type(xs:date)" cannot be abbreviated because a bare QName is interpreted as a node pattern, matching elements named xs:date. The pattern match="type(text() | comment())" has almost the same effect as match="text() | comment()", except that the rules for calculating a default priority are different.

  • [Definition: A node pattern uses a subset of the syntax for path expressions, and is defined to match a node if the corresponding path expression would select the node. Node patterns may also be formed by combining other patterns using union, intersection, and difference operators.]

    The syntax for node patterns (UnionExprP in the grammar: see 5.4.2 Syntax of Patterns) is a subset of the syntax for expressions. Node patterns are used only for matching nodes; an item other than a node will never match a node pattern. As explained in detail below, a node matches a node pattern if the node can be selected by deriving an equivalent expression, and evaluating this expression with respect to some possible 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.

5.4.2 Syntax of Patterns

[ERR XTSE0340] Where an attribute is defined to contain a pattern, it is a static error if the pattern does not match the production Pattern40.

The complete grammar for patterns is listed in F Pattern Syntax Summary. It uses the notation defined in Section A.1.1 NotationXP.

The lexical rules for patterns are the same as the lexical rules for XPath expressions, as defined in Section A.3 Lexical structureXP. Comments are permitted between tokens, using the syntax (: ... :). All other provisions of the XPath grammar apply where relevant, for example the rules for whitespace handling and extra-grammatical constraints.

Pattern40::=PredicatePattern | TypePattern | NodePattern
PredicatePattern::="." PredicateXP*
TypePattern::=(WrappedItemTest | AnyItemTestXP | FunctionTypeXP | MapTypeXP | ArrayTypeXP | RecordTypeXP | EnumerationTypeXP) PredicateXP*
NodePattern::=UnionExprP

Patterns fall into three groups:

  • A PredicatePattern matches items according to conditions that the item must satisfy: for example .[. castable as xs:integer] matches any value (it might be an atomic item, a node, or an array) that is castable as an integer.

  • A TypePattern matches items according to their type. For example type(xs:integer) matches an atomic item that is an instance of xs:integer, while record(longitude, latitude) matches a map that has exactly two entries, with keys "longitude" and "latitude"

  • A NodePattern matches nodes in a tree, typically by specifying a path that can be used to locate the nodes: for example order matches an element node named order, while billing-address/city matches an element named city whose parent node is an element named billing-address.

The following sections define the rules for each of these groups.

5.4.2.3 Node Patterns

Changes in 4.0  

  1. A function call at the outermost level can now be named using any valid EQName (for example fn:doc) provided it binds to one of the permitted functions fn:doc, fn:id, fn:element-with-id, fn:key, or fn:root. If two functions are called, for example doc('a.xml')/id('abc'), it is no longer necessary to put the second call in parentheses.   [Issues 1375 1522 PR 1378 15 October 2024]

  2. The semantics of patterns using the intersect and except operators have been changed to reflect the intuitive meaning: for example a node now matches A except B if it matches A and does not match B.   [Issue 402 ]

NodePattern::=UnionExprP
UnionExprP::=IntersectExceptExprP (("union" | "|") IntersectExceptExprP)*
IntersectExceptExprP::=PathExprP (("intersect" | "except") PathExprP)*
PathExprP::=RootedPath
| ("/" RelativePathExprP?)
| ("//" RelativePathExprP)
| RelativePathExprP
/* xgs: leading-lone-slash */
RootedPath::=VarRefXPPredicateXP* (("/" | "//") RelativePathExprP)?
VarRef::="$" EQNameXP
Predicate::="[" ExprXP "]"
RelativePathExprP::=StepExprP (("/" | "//") StepExprP)*
StepExprP::=PostfixExprP | AxisStepP

Node Patterns are used to match XDM nodes.

The names of these constructs are chosen to align with the XPath 3.0 grammar. Constructs whose names are suffixed with P are restricted forms of the corresponding XPath 3.0 construct without the suffix. Constructs labeled with the suffix “XP40” are defined in [XPath 4.0].

In a FunctionCallP, the EQName used for the function name must bind to one of the functions fn:doc#1, fn:id#1, fn:id#2, fn:element-with-id#1, fn:element-with-id#2fn:key#2, fn:key#3 or fn:root#0.

Note:

In the case of a call to the fn:root function, the argument list must be empty: that is, only the zero-arity form of the function is allowed.

Note:

As with XPath expressions, the pattern / union /* can be parsed in two different ways, and the chosen interpretation is to treat union as an element name rather than as an operator. The other interpretation can be achieved by writing (/) union (/*)

5.4.2.4 The Meaning of a Node Pattern

The meaning of a node pattern is defined formally as follows, where “if” is to be read as “if and only if”.

The pattern is converted to an expression, called the equivalent expression. The equivalent expression to a Pattern is the XPath expression that takes the same lexical form as the Pattern as written, with the following adjustment:

  • If any PathExprP in the Pattern is a RelativePathExprP, then the first StepExprPPS of this RelativePathExprP is adjusted to allow it to match a parentless element, attribute, or namespace node. The adjustment depends on the axis used in this step, whether it appears explicitly or implicitly (according to the rules of Section 4.6.7 Abbreviated SyntaxXP), and is made as follows:

    1. If the NodeTest in PS is document-node() (optionally with arguments), and if no explicit axis is specified, then the axis in step PS is taken as self rather than child.

    2. If PS uses the child axis (explicitly or implicitly), and if the NodeTest in PS is not document-node() (optionally with arguments), then the axis in step PS is replaced by child-or-top, which is defined as follows. If the context node is a parentless element, comment, processing-instruction, or text node then the child-or-top axis selects the context node; otherwise it selects the children of the context node. It is a forwards axis whose principal node kind is element.

    3. If PS uses the attribute axis (explicitly or implicitly), then the axis in step PS is replaced by attribute-or-top, which is defined as follows. If the context node is an attribute node with no parent, then the attribute-or-top axis selects the context node; otherwise it selects the attributes of the context node. It is a forwards axis whose principal node kind is attribute.

    4. If PS uses the namespace axis (explicitly or implicitly), then the axis in step PS is replaced by namespace-or-top, which is defined as follows. If the context node is a namespace node with no parent, then the namespace-or-top axis selects the context node; otherwise it selects the namespace nodes of the context node. It is a forwards axis whose principal node kind is namespace.

    The axes child-or-top, attribute-or-top, and namespace-or-top are introduced only for definitional purposes. They cannot be used explicitly in a user-written pattern or expression.

    Note:

    The purpose of this adjustment is to ensure that a pattern such as person matches any element named person, even if it has no parent; and similarly, that the pattern @width matches any attribute named width, even a parentless attribute. The rule also ensures that a pattern using a NodeTest of the form document-node(...) matches a document node. The pattern node() will match any element, text node, comment, or processing instruction, whether or not it has a parent. For backwards compatibility reasons, the pattern node(), when used without an explicit axis, does not match document nodes, attribute nodes, or namespace nodes. The rules are also phrased to ensure that positional patterns of the form para[1] continue to count nodes relative to their parent, if they have one. To match any node at all, XSLT 4.0 allows the pattern .[. instance of node()] to be used.

The meaning of the pattern is then defined in terms of the semantics of the equivalent expression, denoted below as EE.

Specifically, an item N matches a pattern P if the following applies, where EE is the equivalent expression to P:

  1. A node matches a UnionExprPA union B (or equivalently, A | B) if it matches either A or B or both.

  2. A node matches an IntersectExceptExprPA intersect B if it matches both A and B.

  3. A node matches an IntersectExceptExprPA except B if it matches A and does not match B.

  4. N is a node, and the result of evaluating the expression root(.)//(EE) with a singleton focus based on N is a sequence that includes the node N

    A node matches a PathExprP under the following conditions:

    1. If the PathExprP consists in its entirety of a ParenthesizedExprP, then the node matches the ParenthesizedExprP if it matches the UnionExprP enclosed within the parentheses.

    2. Otherwise, the PathExprP pattern is converted to an expression, called the equivalent expression. The equivalent expression to a PathExprP is the XPath expression that takes the same lexical form as the PathExprP as written, with the following adjustment:

      If any PathExprP in the Pattern is a RelativePathExprP, then the first StepExprPPS of this RelativePathExprP is adjusted to allow it to match a parentless element, attribute, or namespace node. The adjustment depends on the axis used in this step, whether it appears explicitly or implicitly (according to the rules of Section 4.6.7 Abbreviated SyntaxXP), and is made as follows:

      1. If the NodeTest in PS is document-node() (optionally with arguments), and if no explicit axis is specified, then the axis in step PS is taken as self rather than child.

      2. If PS uses the child axis (explicitly or implicitly), and if the NodeTest in PS is not document-node() (optionally with arguments), then the axis in step PS is replaced by child-or-top, which is defined as follows. If the context node is a parentless element, comment, processing-instruction, or text node then the child-or-top axis selects the context node; otherwise it selects the children of the context node. It is a forwards axis whose principal node kind is element.

      3. If PS uses the attribute axis (explicitly or implicitly), then the axis in step PS is replaced by attribute-or-top, which is defined as follows. If the context node is an attribute node with no parent, then the attribute-or-top axis selects the context node; otherwise it selects the attributes of the context node. It is a forwards axis whose principal node kind is attribute.

      4. If PS uses the namespace axis (explicitly or implicitly), then the axis in step PS is replaced by namespace-or-top, which is defined as follows. If the context node is a namespace node with no parent, then the namespace-or-top axis selects the context node; otherwise it selects the namespace nodes of the context node. It is a forwards axis whose principal node kind is namespace.

      The axes child-or-top, attribute-or-top, and namespace-or-top are introduced only for definitional purposes. They cannot be used explicitly in a user-written pattern or expression.

      Note:

      The purpose of this adjustment is to ensure that a pattern such as person matches any element named person, even if it has no parent; and similarly, that the pattern @width matches any attribute named width, even a parentless attribute. The rule also ensures that a pattern using a NodeTest of the form document-node(...) matches a document node. The pattern node() will match any element, text node, comment, or processing instruction, whether or not it has a parent. For backwards compatibility reasons, the pattern node(), when used without an explicit axis, does not match document nodes, attribute nodes, or namespace nodes. The rules are also phrased to ensure that positional patterns of the form para[1] continue to count nodes relative to their parent, if they have one. To match any node at all, XSLT 4.0 allows the pattern .[. instance of node()] to be used.

    The meaning of the pattern is then defined in terms of the semantics of the equivalent expression, denoted below as EE.

    Specifically, an item N matches a PathExprP pattern P if the following applies, where EE is the equivalent expression to P:

    • N is a node, and the result of evaluating the expression root(.)//(EE) with a singleton focus based on N is a sequence that includes the node N.

If a pattern appears in an attribute of an element that is processed with XSLT 1.0 behavior (see 3.9 Backwards Compatible Processing), then the semantics of the pattern are defined on the basis that the equivalent XPath expression is evaluated with XPath 1.0 compatibility mode set to true.

Note:

This version of the specification includes an incompatible change to the semantics of patterns using the intersect and except operators. This change is made to eliminate cases where the behavior defined in XSLT 3.0 was counter-intuitive.

Consider the pattern para except appendix//para. In XSLT 4.0 this matches any para element that is not the descendant of an appendix element. In XSLT 3.0 it would match the para element in the XML tree shown below:

<appendix>
  <section>
     <para/>
  </section>
</appendix>

because there is an element $S (specifically, the section element), such that the expression $S//(para except appendix//para) selects this para element.

It is recommended that processors should report a compatibility warning when such constructs are encountered. The problem arises with patterns using intersect or except where one of the branches uses the descendant axis: it does not arise in simple cases like * except A, or @* except @code, where the branches only use the child or attribute axis.

The change does not affect the meaning of patterns that use the intersect or except operators nested within a path expression, for example a pattern such as A[.//C except B//C].

Example: The Semantics of Node Patterns

The node patternp matches any p element, because a p element will always be present in the result of evaluating the expressionroot(.)//(child-or-top::p). Similarly, / matches a document node, and only a document node, because the result of the expressionroot(.)//(/) returns the root node of the tree containing the context node if and only if it is a document node.

The node patternnode() matches all nodes selected by the expression root(.)//(child-or-top::node()), that is, all element, text, comment, and processing instruction nodes, whether or not they have a parent. It does not match attribute or namespace nodes because the expression does not select nodes using the attribute or namespace axes. It does not match document nodes because for backwards compatibility reasons the child-or-top axis does not match a document node.

Note:

The pattern type(node()) matches all nodes.

The node pattern$V matches all nodes selected by the expression root(.)//($V), that is, all nodes in the value of $V (which will typically be a global variable, though when the pattern is used in contexts such as the xsl:number or xsl:for-each-group instructions, it can also be a local variable).

The node patterndoc('product.xml')//product matches all nodes selected by the expression root(.)//(doc('product.xml')//product), that is, all product elements in the document whose URI is product.xml.

The node patternroot(.)/self::E matches an E element that is the root of a tree (that is, an E element with no parent node).

Although the semantics of node patterns are specified formally in terms of expression evaluation, it is possible to understand pattern matching using a different model. A node pattern such as book/chapter/section can be examined from right to left. A node will only match this pattern if it is a section element; and then, only if its parent is a chapter; and then, only if the parent of that chapter is a book. When the pattern uses the // operator, one can still read it from right to left, but this time testing the ancestors of a node rather than its parent. For example appendix//section matches every section element that has an ancestor appendix element.

The formal definition, however, is useful for understanding the meaning of a pattern such as para[1]. This matches any node selected by the expression root(.)//(child-or-top::para[1]): that is, any para element that is the first para child of its parent, or a para element that has no parent.

Note:

An implementation, of course, may use any algorithm it wishes for evaluating patterns, so long as the result corresponds with the formal definition above. An implementation that followed the formal definition by evaluating the equivalent expression and then testing the membership of a specific node in the result would probably be very inefficient.

Note:

Patterns using the intersect and except operators do not always have the intuitive meaning: in particular, it is not always the case that a node matches A except B if it matches A but does not match B.

For example, consider the pattern para except appendix//para. This expands to root(.)/descendant-or-self::node()/(child::para except child::appendix//para). Since for a given parent node, the results of child::para and child::appendix are disjoint, the right-hand operand of except has no effect.

The effect of matching all paragraphs except those within an appendix can be achieved using the pattern para except //appendix//para; alternatively, use para[not(ancestor::appendix)].

Simpler patterns such as @* except @code generally have the expected effect; the complications arise mainly when non-trivial relative paths are used.

J Changes since XSLT 3.0 (Non-Normative)

J.1 Changes in this specification

  1. Use the arrows to browse significant changes since the 3.0 version of this specification.

    See 1.2 What’s New in XSLT 4.0?

  2. Sections with significant changes are marked Δ in the table of contents.

    See 1.2 What’s New in XSLT 4.0?

  3. Named item types can be declared using the new xsl:item-type element. This is designed to avoid repeating lengthy type definitions (for example function types) every time they are used. [This feature was present in the editor's draft presented to the WG when it started work.]

    See 5.5.1 Named Item Types

  4. The xsl:for-each and xsl:apply-templates instructions acquire an attribute separator that can be used to insert content between adjacent items. [This change was in the editor's draft adopted as a baseline when the WG commenced work.]

    See 6.3 Applying Template Rules

  5. PR 751 1386 

    The result type of a mode can be declared using an as attribute. The result type of all template rules in this mode must be consistent with this, as must the values returned by any built-in template rules for the mode.

    See 6.7.4 Declaring the Result Type of a Mode

  6. The xsl:for-each and xsl:apply-templates instructions acquire an attribute separator that can be used to insert content between adjacent items. [This change was in the editor's draft adopted as a baseline when the WG commenced work.]

    See 7.1 The xsl:for-each instruction

  7. Numeric values of type xs:decimal are compared as decimals, without first converting to xs:double.

    See 13.1.2 Comparing Sort Key Values

  8. 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.]

    See 20 Additional Functions

  9. 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.]

    See 25 Extensibility and Fallback

  10. It is possible to invoke a named template using an extension instruction, specifically, an element whose name matches the name of the named template.

    See 10.1.3 Invoking Named Templates using Extension Instructions

    See 25.2 Extension Instructions

  11. A new attribute xsl:map/@on-duplicates is available, allowing control over how duplicate keys are handled by the xsl:map instruction.

    See 21.1.1 Handling of duplicate keys

  12. The semantics of patterns using the intersect and except operators have been changed to reflect the intuitive meaning: for example a node now matches A except B if it matches A and does not match B.

    See 5.4.2.3 Node Patterns

  13. A new attribute xsl:for-each-group/@split-when is available to give applications more complete control over how a sequence is partitioned

    See 14 Grouping

  14. Duplicate xsl:include declarations within a stylesheet level are now ignored, preventing spurious errors caused by the presence of duplicate named components.

    See 3.11.2 Stylesheet Inclusion

  15. Named record types are introduced.

    See 5.5.2 Named Record Types

  16. The contents of a character map declared using xsl:character-map are now available dynamically via a new character-map function.

    See 27.4 The character-map function

  17. New variables err:stack-trace, err:additional, and err:map are available within an xsl:catch clause.

    See 8.4 Try/Catch

  18. The input to the serializer can be defined using the select attribute of xsl:result-document as an alternative to using a sequence constructor.

    See 26.1 Creating Secondary Results

  19. It is no longer an intrinsic error for a global variable to refer to itself; this is now permitted, for example in cases where the value of the global variable is a recursive inline function. Cases where self-reference would not make sense are covered by the existing rules on circularities: see 9.11 Circular Definitions.

    See 9.5 Global Variables and Parameters

  20. The default value for the indent parameter is now defined to be no for all output methods other than html and xhtml.

    See 27.2 Defaults for serialization parameters

  21. The xsl:map instruction allows a select attribute as an alternative to the contained sequence constructor.

    See 21.1 Map Instructions

    The xsl:map-entry instruction, in common with other instructions, now raises error XTSE3185 (rather than XTSE3280) if both a select attribute and a sequence constructor are present.

    See 21.1 Map Instructions

  22. Composite sort keys are allowed in xsl:sort.

    See 13.1.2 Comparing Sort Key Values

  23. PR 159 

    Parameters on functions declared using xsl:function can now be defined as optional, with a default value supplied.

    See 9.2.2 Default Values of Parameters

    See 10.3 Stylesheet Functions

  24. PR 237 

    The xsl:if instruction now allows then and else attributes.

    See 8.1 Conditional Processing with xsl:if

    In xsl:choose, the xsl:when and xsl:otherwise elements can take a select attribute in place of a sequence constructor.

    See 8.2 Conditional Processing with xsl:choose

    A new xsl:switch instruction is introduced.

    See 8.3 Conditional Processing with xsl:switch

  25. PR 326 

    The higher-order-function feature no longer exists; higher-order functions are now a core part of XSLT, no longer an optional extra.

    See 28 Conformance

  26. PR 353 

    A new attribute, main-module, is added to the xsl:stylesheet element. The attribute is provided for the benefit of development tools such as syntax-directed editors to provide information about all the components (variables, functions, etc) visible within a stylesheet module.

    See 3.7 Stylesheet Element

    A new element xsl:note is available for documentation and similar purposes: it can appear anywhere in the stylesheet and is ignored by the XSLT processor.

    See 3.13.2 The xsl:note element

  27. PR 401 

    Patterns (especially those used in template rules) can now be defined by reference to item types, so any item type can be used as a match pattern. For example match="record(longitude, latitude, *)" matches any map that includes the key values "longitude" and "latitude".

    See 5.4.2.2 Type Patterns

  28. PR 406 

    The new instruction xsl:array is introduced to allow construction of arrays.

    See 22.1 Array Construction

  29. PR 470 

    The xsl:stylesheet, xsl:transform, or xsl:package element may have a fixed-namespaces attribute making it easier to have the same namespace declarations in force throughout a stylesheet.

    See 3.7.1 The fixed-namespaces Attribute

  30. PR 489 

    The xsl:matching-substring and xsl:non-matching-substring elements within xsl:analyze-string may now take a select attribute in place of a contained sequence constructor.

    See 17.1 The xsl:analyze-string Instruction

  31. PR 534 

    A new serialization parameter escape-solidus is provided to control whether the character / is escaped as \/ by the JSON serialization method.

    See 26.1 Creating Secondary Results

    See 27.1 The xsl:output declaration

  32. PR 542 

    A mode (called an enclosing mode) can be defined in which all the relevant template rules are children of the xsl:mode element. This is intended to allow a stylesheet design in which it is easier to determine which rules might apply to a given xsl:apply-templates call.

    See 6.7.5 Enclosing Modes

  33. PR 599 

    Simplified stylesheets no longer require an xsl:version attribute (which means they might not need a declaration of the XSLT namespace). Unless otherwise specified, a 4.0 simplified stylesheet defaults expand-text to true.

    See 3.8 Simplified Stylesheet Modules

  34. PR 635 

    The rules concerning the compatibility of schemas imported by different packages have been clarified. It is now explicitly stated that instructions that trigger validation must use the imported schema of the package in which validation is invoked. This differs from the current practice of some XSLT 3.0 processors, which may use (for example) a schema formed from the union of the imported schemas in all packages.

    See 3.15 Importing Schema Components

    See 26.4 Validation

  35. PR 717 

    Capturing accumulators have been added; when streaming with a capturing accumulator, the accumulator-after has full access to a snapshot of the matched element node.

    See 18.2.9 Capturing Accumulators

  36. PR 718 

    To allow recursive-descent transformation on a tree of maps and arrays, a new set of built-in templates rules shallow-copy-all is introduced.

    See 6.8 Built-in Template Rules

  37. PR 751 

    The xsl:mode declaration acquires an attribute as="sequence-type" which declares the return type of all template rules in that mode.

    See 6.7.1 Declaring Modes

  38. PR 1181 

    The [xsl:]xpath-default-namespace attribute can be set to the value ##any, which causes unprefixed element names to match in any namespace or none.

    See 5.1.2 Unprefixed Lexical QNames in Expressions and Patterns

  39. PR 1250 

    The strings used in the formatted number to represent a decimal separator, grouping separator, exponent separator, percent sign, per mille sign, or minus sign, are no longer constrained to be single characters.

    See 5.6 Defining a Decimal Format

  40. PR 1254 

    The rules concerning the interpretation of xsi:schemaLocation and xsi:noNamespaceSchemaLocation attributes have been tightened up.

    See 26.4 Validation

  41. PR 1306 

    An as attribute is available on the xsl:sequence instruction.

    See 11.10 Constructing Sequences

  42. PR 1361 

    The term atomic value has been replaced by atomic item.

    See 2.1 Terminology

  43. PR 1378 

    A function call at the outermost level can now be named using any valid EQName (for example fn:doc) provided it binds to one of the permitted functions fn:doc, fn:id, fn:element-with-id, fn:key, or fn:root. If two functions are called, for example doc('a.xml')/id('abc'), it is no longer necessary to put the second call in parentheses.

    See 5.4.2.3 Node Patterns

  44. PR 1442 

    Default priorities are added for new forms of ElementTest and AttributeTest, for example element(p:*) and element(a|b).

    See 6.6 Default Priority for Template Rules

  45. PR 1622 

    The rules for equality comparison have changed to bring keys into line with maps.

    See 20.2.2 fn:key

    New in 4.0.

    See 20.2.3 fn:map-for-key

  46. PR 1689 

    Composite merge keys are now allowed.

    See 15 Merging

  47. PR 1703 

    Ordered maps are introduced.

    See 21.1 Map Instructions

K Incompatibilities with XSLT 3.0 (Non-Normative)

This section lists all known incompatibilities with XSLT 3.0, that is, situations where a stylesheet that is error-free according to the XSLT 3.0 specification and where all elements have an effective version of 3.0 or less, will produce different results depending on whether it is run under an XSLT 3.0 processor or an XSLT 4.0 processor.

  1. The rules for comparing values in xsl:for-each-group now reference the rules for distinct-values, which have themselves changed to be compatible with fn:atomic-equal. This change eliminates the intransitivity in the previous specification, which meant that in edge cases involving rounding of numeric values of different types, two items in different groups could compare equal. Any change in behavior is confined to this edge case.

  2. The rules for matching nodes against patterns using the intersect and except operators have changed to deliver a more intuitive result.

  3. The rules for comparing values in keys have changed, to align with the rules for maps. The changes affect edge cases involving rounding of numeric values of different types, and the comparison of date/time values with and without timezones.

This specification also corrects a number of errors and omissions in XSLT 3.0, in a way that might create incompatibilities for some processors, depending on how they interpreted the XSLT 3.0 specification:

  1. XSLT 3.0 (and earlier releases) did not fully define the evaluation context for the default values of template parameters. For example, if the default value of a parameter of a template rule invoked xsl:next-match, it was not specified whether the current template rule should be the calling template or the called template. This omission has been corrected.

  2. Where different packages import different schemas, the specification is now more prescriptive about which schema is used for validation. The rules may differ from the conventions adopted by implementations of XSLT 3.0.

  3. XSLT 3.0 failed to specify a default value for the serialization parameter indent where the serialization method is json or adaptive. XSLT 4.0 specifies a default value of no.

See also [XPath 4.0], [Functions and Operators 4.0], and [XSLT and XQuery Serialization 4.0] for incompatibilities in other related specifications that may affect XSLT stylesheets.