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


6 Template Rules

Template rules define the processing that can be applied to items that match a particular pattern.

6.7 Modes

[Definition:  A mode is a set of template rules; when the xsl:apply-templates instruction selects a set of items for processing, it identifies the rules to be used for processing those items by nominating a mode, explicitly or implicitly.] Modes allow a node in a source tree (for example) to be processed multiple times, each time producing a different result. They also allow different sets of template rules to be active when processing different trees, for example when processing documents loaded using the document function (see 20.1 fn:document).

Modes are identified by an expanded QName; in addition to any named modes, there is always one unnamed mode available. Whether a mode is named or unnamed, its properties may be defined in an xsl:mode declaration. If a mode name is used (for example in an xsl:template declaration or an xsl:apply-templates instruction) and no declaration of that mode appears in the stylesheet, the mode is implicitly declared with default properties.

6.7.4 Declaring the Type of Values Processed by a Mode

Changes in 4.0 (next | previous)

  1. The xsl:mode/@typed attribute has been clarified and expanded to provide better control over the handling of items other than XNodes.

      [Issue 2337 PR 2736 9 January 2026]

Typically the template rules in a particular mode will be designed to process a specific kind of input document. The typed attribute of xsl:mode gives the stylesheet author the opportunity to provide information about this document to the processor. This information may enable the processor to improve diagnostics or to optimize performance.

The allowed values of the attribute are as follows:

  • yes, true, 1: the items processed by this mode must be XNodes, and they must not have a type annotation of xs:untyped or xs:untypedAtomic.

  • no, false, 0: the items processed by this mode must be XNodes, and if they are elements or attributes then they must have a type annotation of xs:untyped or xs:untypedAtomic.

  • The value strict is equivalent to yes, with the additional provision that in the match pattern of any template rule that is applicable to this mode, any NameTest used in the ForwardStepP of the first StepExprP of a RelativePathExprP is interpreted as follows:

    • If the NameTest is an EQNameE, and the principal node kind of the axis of this step is Element, then:

      • It is a static error if the in-scope schema declarations do not include a global element declaration for element name E

      • When matching templates in this mode, the element name E appearing in this step is interpreted as schema-element(E). (Informally, this means that it will only match an element if it has been validated against this element declaration).

    • Otherwise (the NameTest is a wildcard or the principal node kind is Attribute or Namespace), the template matching proceeds as if the typed attribute were absent.

  • The value lax is equivalent to yes, with the additional provision that in the match pattern of any template rule that is applicable to this mode, any NameTest used in the ForwardStepP of the first StepExprP of a RelativePathExprP is interpreted as follows:

    • If the NameTest is an EQNameE, and the principal node kind of the axis of this step is Element, and the in-scope schema declarations include a global element declaration for element name E, then:

      • When matching templates in this mode, the element name E appearing in this step is interpreted as schema-element(E). (Informally, this means that it will only match an element if it has been validated against this element declaration).

    • Otherwise (the NameTest is a wildcard, or the principal node kind is Attribute or Namespace, or there is no element declaration for E), the template matching proceeds as if the typed attribute were absent.

  • If the value is ~ followed by an ItemTypeXP, for example ~xs:anyAtomicType or ~jnode() or ~map(*), this indicates that all items to be processed using template rules in this mode must be of the specified item type.

  • If the value is the string "unspecified", or if it is omitted, this is equivalent to specifying ~item(), indicating that there are no constraints.

[ERR XTTE3100] It is a type error if an xsl:apply-templates instruction in a particular mode selects an item that does not satisfy the constraints imposed by the @typed attribute.

[ERR XTSE3105] It is a static error if a template rule applicable to a mode that is defined with typed="strict" uses a match pattern that contains a RelativePathExprP whose first StepExprP is an AxisStepP whose ForwardStepP uses an axis whose principal node kind is Element and whose NodeTest is an EQName that does not correspond to the name of any global element declaration in the in-scope schema components.

I Changes since XSLT 3.0 (Non-Normative)

I.1 Changes in this specification

  1. If a section of this specification has been updated since version 3.0, an overview of the changes is provided, along with links to navigate to the next or previous change.

    See 1.2 What’s New in XSLT 4.0?

  2. Sections with significant changes are marked with a ✭ symbol 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.4.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.4 Applying Template Rules

  5. New in 4.0

    See 6.7.3.1 fn:apply-templates

  6. 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.5 Declaring the Result Type of a Mode

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

  8. PR 2015 2296 

    A variable-binding with no as or select attribute no longer attempts to create an implicit document node if the sequence constructor contains certain instructions (such as xsl:map, xsl:array, xsl:record, and xsl:select).

    See 9.3 Values of Variables and Parameters

  9. PR 2200 2236 

    Stylesheet functions may now be in no namespace, and may be invoked without use of a namespace prefix, provided they are private to a package.

    See 10.3.1 Function Name and Arity

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

    See 13.1.2 Comparing Sort Key Values

  11. In XSLT 4.0, the function item current-group#0 retains the value of the current group within its captured context.

    See 14.2.1 fn:current-group

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

  13. In XSLT 4.0, the function item current#0 retains the value of the current item within its captured context.

    See 20.5.1 fn:current

  14. 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 24 Extensibility and Fallback

  15. New in 4.0

    See 26.4.1 fn:character-map

  16. 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 24.3 Extension Instructions

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

    See 21.1.2 Handling of duplicate keys

  18. XSLT-specific components of the dynamic context can now be retained in the captured context of a function item, in the same way as XPath-defined components of the dynamic context.

    See 5.3.4 Additional Dynamic Context Components used by XSLT

    In XSLT 4.0, the function item current-grouping-key#0 retains the value of the current grouping key within its captured context.

    See 14.2.2 fn:current-grouping-key

    In XSLT 4.0, the function item current-merge-key#0 retains the value of the current merge-key within its captured context.

    See 15.5.1 fn:current-merge-group

    New in 4.0

    See 15.5.2 fn:current-merge-key-array

    In XSLT 4.0, the function item current-merge-key#0 retains the value of the current group within its captured context.

    See 15.5.3 fn:current-merge-key

    In XSLT 4.0, the function item regex-group#1 retains the value of the current captured substrings within its captured context.

    See 17.2.2 fn:regex-group

    In XSLT 4.0, the function item current-output-uri#0 retains the value of the current output URI within its captured context.

    See 25.3.1 fn:current-output-uri

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

  20. User-defined functions can now have names that are in no namespace. An unprefixed name appearing in a function call is resolved to a no-namespace function with matching local name in preference to a function in the standard fn namespace.

    See 10.3 Stylesheet Functions

  21. A new attribute xsl:result-document/@canonical is available to give control over serialization of XML, XHTML, and JSON.

    See 25.1 Creating Secondary Results

    A new attribute xsl:output/@canonical is available to give control over serialization of XML, XHTML, and JSON.

    See 26.1 The xsl:output declaration

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

    See 3.10.2 Stylesheet Inclusion

  23. Named record types are introduced.

    See 5.4.2 Named Record Types

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

    See 26.4 The character-map function

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

    See 8.4 Try/Catch

  26. 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 25.1 Creating Secondary Results

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

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

    See 26.2 Serialization parameters

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

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

    See 13.1.2 Comparing Sort Key Values

  31. The xsl:mode declaration acquires an attribute copy-namespaces which determines whether or not the built-in template rule copies unused namespace bindings.

    See 6.7.1 Declaring Modes

  32. The default priority for a template rule using a union pattern has changed. This change may cause incompatible behavior.

    See 6.3.3 Default Priority for Patterns

  33. The xsl:apply-imports and xsl:next-match instructions automatically pass supplied parameters to the overridden template rule.

    See 6.9 Overriding Template Rules

  34. A new attribute xsl:for-each-group/@merge-when is available to give applications control to create groups based on clustering, overlap, and networks.

    See 14 Grouping

  35. The conformance requirements for extension attributes have been relaxed: the requirement to maintain strict conformance to the specification in the presence of extension attributes is now a should rather than a must, and extension attributes are allowed to modify the form of serialized output without limitation.

    See 24.1 Extension Attributes

  36. The outermost element of a simplified stylesheet need no longer be a literal result element, it can now be any instruction (including xsl:result-document). This allows a simplified stylesheet to produce JSON output as well as XML or HTML.

    See 3.7 Simplified Stylesheet Modules

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

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

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

  40. 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.6 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.12.2 The xsl:note element

  41. 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 6.3.2.2 Type Patterns

  42. PR 406 

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

    See 22.1 Array Construction

  43. 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.6.1 The fixed-namespaces Attribute

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

  45. PR 534 

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

    See 25.1 Creating Secondary Results

    See 26.1 The xsl:output declaration

  46. 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.6 Enclosing Modes

  47. 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.7 Simplified Stylesheet Modules

  48. 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.14 Importing Schema Components

    See 25.4 Validation

  49. 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 19.9 Capturing Accumulators

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

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

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

  53. 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.5 Defining a Decimal Format

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

  55. PR 1306 

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

    See 10.4.1 The xsl:sequence Instruction

  56. PR 1361 

    The term atomic value has been replaced by atomic item.

    See 2.1 Terminology

  57. 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 6.3.2.3 GNode Patterns

  58. PR 1442 

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

    See 6.3.3 Default Priority for Patterns

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

  60. PR 1689 

    Composite merge keys are now allowed.

    See 15 Merging

  61. PR 1703 

    Ordered maps are introduced.

    See 21.1 Map Instructions

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

    See 3.3 Standard Attributes

    Different parts of a stylesheet may now use different imported schemas.

    See 3.14 Importing Schema Components

    A stylesheet can import multiple schemas with different schema role names.

    See 3.14.1 Multiple Schemas

  63. PR 1856 

    The rules for xsl:analyze-string have been adjusted to allow for new capabilities in regular expressions, such as zero-width assertions.

    See 17.1 The xsl:analyze-string Instruction

  64. PR 1858 

    The xsl:record instruction is introduced to make construction of record maps simpler.

    See 21.1.1 Record Instruction

    Attribute xsl:record/@xsl:duplicates is added to control duplicate keys handling in the xsl:record instruction.

    See 21.1.2 Handling of duplicate keys

  65. PR 1888 

    A new XSLT element, xsl:package-location is provide to indicate to the processor where the required package is to be found.

    See 3.4.3 Locating Packages

  66. PR 2006 

    A new function fn:apply-templates is introduced.

    See 6.7.3 The apply-templates Function

  67. PR 2008 

    The xsl:select instruction is new in 4.0.

    See 10.4.2 The xsl:select Instruction

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

  69. PR 2213 

    A new attribute trusted=yes|no is added to xsl:evaluate to indicate whether the XPath expression to be evaluated is trusted to access external resources. The default value is no, which may cause backwards incompatibility. Dynamic evaluation using xsl:evaluate is no longer an optional feature of the XSLT language.

    See 10.5 Dynamic XPath Evaluation

    The dynamic evaluation feature no longer exists; processor are now required to support the xsl:evaluate instruction.

    See 27 Conformance

  70. PR 2251 

    The xsl:text instruction can now have a select attribute, and it can take a sequence constructor as its content. The only remaining distinction between the xsl:text and xsl:value-of instructions is that whitespace text node children of xsl:text are treated as significant, rather than being stripped during stylesheet preprocessing.

    See 11.4 Creating Text Nodes

    The rules for xsl:text and xsl:value-of are integrated, allowing xsl:text to be used to construct all text nodes, whether the content is fixed or variable.

    See 11.4.2 The xsl:text and xsl:value-of instructions

  71. PR 2301 

    The attribute cdata is added to xsl:text and xsl:value-of to request serialization of a text node as a CDATA section.

    See 11.4.2 The xsl:text and xsl:value-of instructions

    See 11.4.3 Generating CDATA Sections

  72. PR 2736 

    The xsl:mode/@typed attribute has been clarified and expanded to provide better control over the handling of items other than XNodes.

    See 6.7.4 Declaring the Type of Values Processed by a Mode