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.
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.
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.
The publications of this community group are dedicated to our co-chair, Michael Sperberg-McQueen (1954–2024).
This section contains rules that can be used to determine properties of constructs in the stylesheet — specifically, the posture and sweep of a construct — which enable the streamability of the stylesheet to be assessed.
These properties are used to determine the streamability of:
The xsl:source-document instruction: see 18.1 The xsl:source-document Instruction
Stylesheet functions: see 19.8.5 Classifying Stylesheet Functions
The xsl:merge instruction: see 15.4 Streamable Merging
In each case, the conditions for constructs to be guaranteed-streamable are defined in terms of these properties. The result of this analysis in turn (see 19.10 Streamability Guarantees) imposes rules on how the constructs are handled by processors that implement the streaming feature. The analysis has no effect on the behavior of processors that do not implement this feature.
The analysis is relevant to constructs such as streamable template rules and the xsl:source-document instruction that process a single streamed input document. The xsl:merge instruction, which processes multiple streamed inputs, has its own rules.
The rules in this section operate on the expression tree (more properly, construct tree) that is typically output by the XSLT and XPath parser. For the most part, the rules depend only on identifying the syntactic constructs that are present.
The rules in this section generally consider each component in the stylesheet (and in the case of template rules, each template rule) in isolation. The exception is that where a component contains references to other components (such as global variables, functions, or named templates), then information from the signature of the referenced component is sometimes used. This is invariably information that cannot be changed if a component is overridden in a different package. The analysis thus requires as a pre-condition that function calls and calls on named templates have been resolved to the extent that the corresponding function/template signature is known.
The detailed way in which the construct tree is derived from the lexical form of the stylesheet is not described in this specification. There are many ways in which the tree can be optimized without affecting the result of the rules in this section: for example, a sequence constructor containing a single instruction can be replaced by that instruction, and a parenthesized expression can be replaced by its content.
[Definition: The term construct refers to the union of the following: a sequence constructor, an instruction, an attribute set, a value template, an expression, or a pattern.]
These constructs are classified into construct kinds: in particular, instructions are classified according to the name of the XSLT instruction, and expressions are classified according to the most specific production in the XPath grammar that the expression satisfies. (This means, for example, that 2+2 is classified as an AdditiveExpr, rather than say as a UnionExpr; although it also satisfies the production rule for UnionExpr, AdditiveExpr is more specific.)
[Definition: For every construct kind, there is a set of zero or more operand roles.] For example, an AdditiveExpr has two operand roles, referred to as the left-hand operand and the right-hand operand, while an IfExpr has three, referred to as the condition, the then-clause, and the else-clause. A function call with three arguments has three operand roles, called the first, second, and third arguments. The names of the operand roles for each construct kind are not formally listed, but should be clear from the context.
[Definition: In an actual instance of a construct, there will be a number of operands. Each operand is itself a construct; the construct tree can be defined as the transitive relation between constructs and their operands.] Each operand is associated with exactly one of the operand roles for the construct type. There may be operand roles where the operand is optional (for example, the separator attribute of the xsl:value-of instruction), and there may be operand roles that can be occupied by multiple operands (for example, the xsl:when/@test condition in xsl:choose, or the arguments of the concat function).
Operand roles have a number of properties used in the analysis:
The required type of the operand. This is explicit in the case of function calls (the required type is defined in the function signature of the corresponding function). In other cases it is implicit in the detailed rules for the construct in question. In practice streamability analysis makes only modest use of the required type; the main case where it is relevant is for a function or template call, where knowing that the required type is atomic enables the inference that the operand usage for a supplied node is absorption.
[Definition: The operand usage. This gives information, in the case where the operand value contains nodes, about how those nodes are used. The operand usage takes one of the values absorption, inspection, transmission, or navigation.] The meanings of these terms are explained in 19.3 Operand Roles. If the required type of the operand does not permit nodes to be supplied (for example because the required type is a function item or a map), then the operand usage is inspection, because the only run-time operation on a supplied node will be to inspect it, discover it is a node, and raise a type error.
In the particular case where the required type is atomic, and any supplied nodes are atomized, the operand usage will be absorption, because atomize is a special case of absorption.
[Definition: Whether or not the operand is higher-order. For this purpose an operand O of a construct C is higher-order if the semantics of C potentially require O to be evaluated more than once during a single evaluation of C.] More specifically, O is a higher-order operand of C if any of the following conditions is true:
The context item for evaluation of O is different from the context item for evaluation of C.
C is an instruction and O is a pattern (as with the from and count attributes of xsl:number, and the group-starting-with and group-ending-with attributes of xsl:for-each-group).
C is an XPath for, some, or every expression and O is the expression in its return or satisfies clause.
C is an inline function declaration and O is the expression in its body.
Note:
There is one known case where this definition makes an operand higher-order even though it is only evaluated once: specifically, the sequence constructor contained in the body of an xsl:copy instruction that has a select attribute. See 19.8.4.12 Streamability of xsl:copy for further details.
[Definition: For some construct kinds, one or more operand roles may be defined to form a choice operand group. This concept is used where it is known that operands are mutually exclusive (for example the then and else clauses in a conditional expression).]
[Definition: The combined posture of a choice operand group is determined by the postures of the operands in the group (the operand postures), and is the first of the following that applies:
If any of the operand postures is roaming, then the combined posture is roaming.
If all of the operand postures are grounded, then the combined posture is grounded.
If one or more of the operand postures is climbing and the remainder (if any) are grounded, then the combined posture is climbing.
If one or more of the operand postures is striding and the remainder (if any) are grounded, then the combined posture is striding.
If one or more of the operand postures is crawling and each of the remainder (if any) is either striding or grounded, then the combined posture is crawling.
Otherwise (for example, if the group includes both an operand with climbing posture and one with crawling posture), the combined posture is roaming.
]
[Definition: The type-determined usage of an operand is as follows: if the required type (ignoring occurrence indicator) is fn(*) or a subtype thereof, then inspection; if the required type (ignoring occurrence indicator) is an atomic or union type, then absorption; otherwise navigation.]
[Definition: The type-adjusted posture and sweep of a construct C, with respect to a type T, are the posture and sweep established by applying the general streamability rules to a construct D whose single operand is the construct C, where the operand usage of C in D is the type-determined usage based on the required type T.]
Note:
In effect, the type-adjusted posture and sweep are the posture and sweep of the implicit expression formed to apply the coercion rules to the argument of a function or template call, or to the result of a function or template, given knowledge of the required type. For example, an expression such as discount in the function call abs(discount), which would otherwise be striding and consuming, becomes grounded and consuming because of the implicit atomization triggered by the coercion rules.
The process of determining whether a construct is streamable reduces to determining properties of the constructs in the construct tree. The properties in question (which are described in greater detail in subsequent sections) are:
The static type of the construct. When the construct is evaluated, its value will always be an instance of this type. The value is a U-type; although type inferencing is capable of determining information about the cardinality as well as the item type, the streamability analysis makes no use of this.
The context item type: that is, the static type of the context item potentially used as input to the construct. When the construct is evaluated, the context item used to evaluate the construct (if it is used at all) will be an instance of this type.
[Definition: The posture of the expression. This captures information about the way in which the streamed input document is positioned on return from evaluating the construct. The posture takes one of the values climbing, striding, crawling, roaming, or grounded.] The meanings of these terms are explained in 19.4 Determining the Posture of a Construct.
[Definition: The context posture. This captures information about how the context item used as input to the construct is positioned relative to the streamed input. The context posture of a construct C is the posture of the expression whose value sets the focus for the evaluation of C.] Rules for determining the context posture of any construct are given in 19.5 Determining the Context Posture.
The sweep of the construct. The sweep of a construct gives information about whether and how the evaluation of the construct changes the current position in a streamed input document. The possible values are motionless, consuming, and free-ranging. These terms are explained in 19.6 The Sweep of a Construct.
The values of these properties for a top-level construct such as the body of a template rule determine whether the construct is streamable.
The values of these properties are not independent. For example, if the static type is atomic, then the posture will always be grounded; if the sweep is free-ranging, then the posture will always be roaming.
The posture and sweep of a construct, as defined above, are calculated in relation to a particular streamed input document. If there is more than one streamed input document, then a construct that is motionless with respect to one streamed input might be consuming with respect to another. In practice, though, the streamability analysis is only ever concerned with one particular streamed input at a time; constructs are analyzed in relation to the innermost containing xsl:template, xsl:source-document, xsl:accumulator, or xsl:merge-source element, and this container implicitly defines the streamed input document that is relevant. The streamed input document affecting a construct is always the document that contains the context item for evaluation of that construct.
This section defines the properties of every kind of construct that may appear in a stylesheet. It identifies the operand roles and their usage, and it gives the rules that define the posture and sweep of the construct. In cases where the general streamability rules apply, there is still an entry for the construct in order to define its operands and their usages, since this information is needed by the general rules.
The following sections describe this categorization for each kind of construct:
Sequence constructors: see 19.8.3 Classifying Sequence Constructors
Instructions: see 19.8.4 Classifying Instructions
Stylesheet functions: see 19.8.5 Classifying Stylesheet Functions
Attribute sets: see 19.8.6 Classifying Attribute Sets
Value templates: see 19.8.7 Classifying Value Templates
Expressions: see 19.8.8 Classifying Expressions
Patterns: see 19.8.10 Classifying Patterns
Calls to built-in functions: see 19.8.9 Classifying Calls to Built-In Functions
This section describes how instructions are classified with respect to their streamability. The criteria are given first for literal result elements and extension instructions, then for each XSLT instruction, listed alphabetically.
xsl:mapThe posture and sweep of the xsl:map instruction are determined by the first of the following that applies:
If the sequence constructor within the instruction consists exclusively of xsl:map-entry instructions (and xsl:fallback instructions, which are ignored), and the duplicates attribute is absent, then:
If any of these xsl:map-entry children is roaming or free-ranging, then roaming and free-ranging;
Otherwise, grounded and the widest sweep of the xsl:map-entry children.
Otherwise, the posture and sweep of the xsl:map instruction are the posture and sweep of the contained sequence constructor.
Note:
See discussion in 21.2 Maps and Streaming.
The effect of the rules is that it is possible to compute multiple map entries in a single pass of the streamed input document. For example, the following is streamable:
<xsl:map> <xsl:map-entry key="'authors'" select="copy-of(author)"/> <xsl:map-entry key="'editors'" select="copy-of(editor)"/> </xsl:map>
The call on copy-of is necessary to ensure that the content of the map entry is grounded; it is not possible to create a map whose entries contain references to streamed nodes.
This rule does not apply when duplicate keys are permitted, because in that situation the child xsl:map-entry instructions generally need to be evaluated in the order they are written, rather than in the order their operands are encountered.
Use the arrows to browse significant changes since the 3.0 version of this specification.
Sections with significant changes are marked Δ in the table of contents.
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.]
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.]
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.
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.]
Numeric values of type xs:decimal are compared as decimals, without first converting to xs:double.
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.]
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.]
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
A new attribute xsl:map/@duplicates is available, allowing control over how duplicate keys are handled by the xsl:map instruction.
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.
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
Duplicate xsl:include declarations within a stylesheet level are now ignored, preventing spurious errors caused by the presence of duplicate named components.
Named record types are introduced.
The contents of a character map declared using xsl:character-map are now available dynamically via a new character-map function.
New variables err:stack-trace, err:additional, and err:map are available within an xsl:catch clause.
See 8.4 Try/Catch
The input to the serializer can be defined using the select attribute of xsl:result-document as an alternative to using a sequence constructor.
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.
The default value for the indent parameter is now defined to be no for all output methods other than html and xhtml.
The xsl:map instruction allows a select attribute as an alternative to the contained sequence constructor.
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.
Composite sort keys are allowed in xsl:sort.
The xsl:mode declaration acquires an attribute copy-namespaces which determines whether or not the built-in template rule copies unused namespace bindings.
The default priority for a template rule using a union pattern has changed. This change may cause incompatible behavior.
The xsl:apply-imports and xsl:next-match instructions automatically pass supplied parameters to the overridden template rule.
The xsl:select instruction is new in 4.0.
The special rule allowing xsl:map to have multiple consumable operands does not apply if duplicate keys are permitted.
PR 159
Parameters on functions declared using xsl:function can now be defined as optional, with a default value supplied.
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.
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 27 Conformance
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.
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.
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".
PR 406
The new instruction xsl:array is introduced to allow construction of arrays.
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.
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.
PR 534
A new serialization parameter escape-solidus is provided to control whether the character / is escaped as \/ by the JSON serialization method.
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.
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.
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 25.4 Validation
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.
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.
PR 751
The xsl:mode declaration acquires an attribute as="sequence-type" which declares the return type of all template rules in that mode.
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
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.
PR 1254
The rules concerning the interpretation of xsi:schemaLocation and xsi:noNamespaceSchemaLocation attributes have been tightened up.
See 25.4 Validation
See 25.4 Validation
PR 1306
An as attribute is available on the xsl:sequence instruction.
PR 1361
The term atomic value has been replaced by atomic item.
See 2.1 Terminology
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.
PR 1442
Default priorities are added for new forms of ElementTest and AttributeTest, for example element(p:*) and element(a|b).
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.
PR 1689
Composite merge keys are now allowed.
See 15 Merging
PR 1703
Ordered maps are introduced.
PR 1819
Different parts of a stylesheet may now use different imported schemas.
See 2.10 Stylesheets and XML Schemas
The standard attribute [xsl:]schema-role is introduced, to allow different parts of a stylesheet to use different schemas.
Different parts of a stylesheet may now use different imported schemas.
See 3.15 Importing Schema Components
A stylesheet can import multiple schemas with different schema role names.
PR 1856
The rules have been adjusted to allow for new capabilities in regular expressions, such as zero-width assertions.
PR 1858
The xsl:record instruction is introduced to make construction of record maps simpler.
Attribute xsl:record/@xsl:duplicates is added to control duplicate keys handling in the xsl:record instruction.
PR 2006
A new function fn:apply-templates is introduced.
PR 2015
A variable-binding with no as or select attribute no longer attempts to create an implicit document node if the sequence constructor contains an xsl:map, xsl:array, or xsl:select child instruction.
PR 2030
In order to reduce duplication between the XSLT and XQuery specifications, description of the validation process has been moved to the Functions and Operators specification.
See 25.4 Validation