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).
The function library for XPath 3.0 defines several functions that make use of regular expressions:
matches returns a boolean result that indicates whether or not a string matches a given regular expression.
replace takes a string as input and returns a string obtained by replacing all substrings that match a given regular expression with a replacement string.
tokenize returns a sequence of strings formed by breaking a supplied input string at any separator that matches a given regular expression.
analyze-string returns a tree of nodes that effectively add markup to a string indicating the parts of the string that matched the regular expression, as well as its captured groups.
These functions are described in [Functions and Operators 4.0].
Supplementing these functions, XSLT provides an instruction xsl:analyze-string, which is defined in this section.
Note:
The xsl:analyze-string instruction predates the analyze-string function, and provides very similar functionality, though in a different way.
The regular expressions used by this instruction, and the flags that control the interpretation of these regular expressions, must conform to the syntax defined in [Functions and Operators 4.0] (see [Functions and Operators 4.0] section 6.1 Regular expression syntax), which is itself based on the syntax defined in [XML Schema Part 2].
As described in [Functions and Operators 4.0] section 6.1 Regular expression syntax, the effect of processing a string using a regular expression is a sequence of non-overlapping matching segments, each of which is associated with a set of captured groups, represented as a map from a group number to a segment of the input string. The term segment here means a contiguous (and possibly empty) subsequence of characters from the input string, characterized by a starting position and ending position within that string.
Two functions are available for processing the values of captured groups associated with a matching segment.
Examples of the use of these functions can be found in 17.3 Examples of Regular Expression Matching.
Returns the set of captured groups associated with a matching segment during evaluation of the xsl:analyze-string instruction.
fn:regex-groups() as map(xs:integer, record(value as xs:string, position as xs:integer)) |
This function is deterministicFO, context-dependentFO, and focus-independentFO.
[Definition: While the xsl:matching-substring instruction is active, a set of current captured groups is available, corresponding to the capturing subexpressions of the regular expression.] These captured groups are accessible using the regex-groups and regex-group functions.
The regex-groups function returns this information as a map.
The Nth captured group (where N > 0) is the segment of the input string matched by the subexpression contained by the Nth left parenthesis in the regex, excluding any non-capturing parenthesized expressions. The zeroth captured substring is the segment of the input string that matches the entire regex. In both cases, a segment is identified by a record containing both the captured string itself (as value) and the start position (1-based) of the captured group within the input string (as position).
Note:
This means that the string value of group zero is the same as the value of . (dot).
The result map contains no entry for a number N if there is no captured group with the number N. This can occur for a number of reasons:
N is negative.
The regular expression contains fewer than N capturing subexpressions.
The Nth capturing subexpression exists, but did not match any part of the input string.
The string value of a captured group may be the empty string.
The set of captured groups is a context variable with dynamic scope. It is initially an empty sequence. During the evaluation of an xsl:matching-substring instruction it is set to the sequence of matched segments for that regex match. During the evaluation of an xsl:non-matching-substring instruction or a pattern or a stylesheet function it is set to an empty sequence. On completion of an instruction that changes the value, the variable reverts to its previous value.
The value of the current captured groups is unaffected through calls of xsl:apply-templates, xsl:call-template, xsl:apply-imports or xsl:next-match, or by expansion of named attribute sets.
The regex-groups function provides additional information that is not available via regex-group:
It distinguishes capturing subexpressions that matched an empty string from capturing subexpressions that did not match anything.
It identifies not just the string that was captured, but its position within the input.
In 4.0 regular expressions may contain capturing subexpressions within a lookahead. In this situation a segment returned in the result of regex-groups may be positioned beyond the end of the corresponding matching segment.
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.
Sections with significant changes are marked with a ✭ symbol in the table of contents.
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.]
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).
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.
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.]
New in 4.0
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.]
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.
PR 1497 1546
A new serialization parameter json-lines is available to enable output as one JSON value per line.
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.14 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 740
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
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 1454
Duplicate xsl:include declarations within a stylesheet level are now ignored, preventing spurious errors caused by the presence of duplicate named components.
PR 1505
New variables err:stack-trace, err:additional, and err:map are available within an xsl:catch clause.
See 8.4 Try/Catch
PR 1530
The contents of a character map declared using xsl:character-map are now available dynamically via a new character-map function.
PR 1544
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.
PR 1549
The input to the serializer can be defined using the select attribute of xsl:result-document as an alternative to using a sequence constructor.
PR 1560
The default value for the indent parameter is now defined to be no for all output methods other than html and xhtml.
PR 1617
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.
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 1674
Composite sort keys are allowed in xsl:sort.
PR 1689
Composite merge keys are now allowed.
See 15 Merging
New in 4.0
PR 1694
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.
PR 1703
Ordered maps are introduced.
PR 1708
Named record types are introduced.
PR 1772
The default priority for a template rule using a union pattern has changed. This change may cause incompatible behavior.
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.14 Importing Schema Components
A stylesheet can import multiple schemas with different schema role names.
PR 1856
The rules for xsl:analyze-string 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 1875
The xsl:apply-imports and xsl:next-match instructions automatically pass supplied parameters to the overridden template rule.
PR 1888
A new XSLT element, xsl:package-location is provide to indicate to the processor where the required package is to be found.
PR 1929
The xsl:mode declaration acquires an attribute copy-namespaces which determines whether or not the built-in template rule copies unused namespace bindings.
PR 2006
A new function fn:apply-templates is introduced.
See 6.7.3 The apply-templates Function
New in 4.0
PR 2008
The xsl:select instruction is new in 4.0.
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
PR 2123
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
PR 2200
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.
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
PR 2218
Numeric values of type xs:decimal are compared as decimals, without first converting to xs:double.
PR 2246
New in 4.0
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.
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.
PR 2259
A new serialization parameter canonical is available to give control over serialization of XML, XHTML, and JSON.
PR 2274
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-group#0 retains the value of the current group within its captured context.
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-group retains the value of the current merge-key within its captured context.
See 15.5.1 fn:current-merge-group
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.
In XSLT 4.0, the function item current#0 retains the value of the current item within its captured context.
In XSLT 4.0, the function item current-output-uri#0 retains the value of the current output URI within its captured context.
PR 2283
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.
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.
PR 2323
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.
PR 2736
The xsl:mode/@typed attribute has been clarified and expanded to provide better control over the handling of items other than XNodes.