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).
Changes in 4.0 (next | previous)
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.] [ 1 January 2022]
This section describes XSLT-specific additions to the XPath function library. Some of these additional functions also make use of information specified by declarations in the stylesheet; this section also describes these declarations.
Provides access to XML documents identified by a URI.
fn:document( | ||
$uri-sequence | as item()*, | |
$base-nodeoptions | as (map(*)|node())? | := ()map{} |
) as node()* | ||
The one-argument form of this function is deterministicFO, focus-independentFO, and context-dependentFO. It depends on static base URI.
The two-argument form of this function is deterministicFO, focus-independentFO, and context-independentFO.
The document function allows access to XML documents identified by a URI.
The first argument contains a sequence of URI references. The second argument, if present, is a node whose base URI is used to resolve any relative URI references contained in the first argument.
The first argument contains a sequence of URI references. These are resolved as described below.
The second argument, if present, may be either a node, or an options map. Supplying a node is allowed for backwards compatibility: the effect of supplying a node $N is the same as supplying the map {"base-uri": fn:base-uri($N)}. The effect is that the base URI of the node is used to resolve any relative URI references contained in the first argument.
If the second argument is supplied as a map, then the option parameter conventionsFO apply. The options available are as follows, and apply to each of the documents constructed by the function:
$base-uri as xs:anyURI, $trusted as xs:boolean, $dtd-validation as xs:boolean, $stable as xs:boolean, $strip-space as xs:boolean?, $xinclude as xs:boolean, $xsd-validation as xs:string, $use-xsi-schema-location as xs:boolean, $schema as xs:NCName</record>| Key | Value | Meaning |
|---|---|---|
| Determines the base URI used to resolve any relative URI supplied in the first argument. This in turn affects the base URI of the constructed document.
| |
| Indicates whether processing the document may cause other external resources to be fetched (including, for example, external entities, an external DTD, or documents referenced using xsi:schemaLocation or XInclude elements).
| |
true | The document may include references to other external resources. | |
false | The document must not include references to other external resources unless access to these resources has been explicitly enabled. | |
| Determines whether DTD validation takes place.
| |
true | The input is parsed using a validating XML parser. The input must contain a DOCTYPE declaration to identify the DTD to be used for validation. The DTD may be internal or external. | |
false | DTD validation does not take place. However, if a DOCTYPE declaration is present, then it is read, for example to perform entity expansion. | |
| Determines whether two calls on the document function, with the same URI, the same options, and the same context, are guaranteed to return the same document node. The default value is true, but this may be overridden by implementation-defined configuration options.
| |
true | Given the same explicit and implicit arguments, multiple calls return the same document node: that is, the function is . | |
false | Multiple calls with the same explicit and implicit arguments may return the same document node or different document nodes at the discretion of the implementation. | |
| Determines whether whitespace-only text nodes are removed from the resulting document.
| |
true | Whitespace stripping is to take place according to the xsl:strip-space and xsl:preserve-space declarations of the containing package: see 4.2.2 Stripping Whitespace from a Source Tree. | |
false | All whitespace-only text nodes are preserved, unless either (a) DTD validation marks them as ignorable, or (b) XSD validation recognizes the containing element as having element-only or empty content. | |
| Determines whether any xi:include elements in the input are to be processed using an XInclude processor.
| |
true | Any xi:include elements are expanded. If there are xi:include elements and no XInclude processor is available then a dynamic error is raised. | |
false | Any xi:include elements are handled as ordinary elements without expansion. | |
| Determines whether XSD validation takes place, using the schema definitions present in the static context. The effect of requesting validation is the same as invoking the document function without validation, and then applying the instruction xsl:copy-of to the result, with corresponding validation and type options, using the schema identified in the schema option if specified.
| |
strict | Strict XSD validation takes place | |
lax | Lax XSD validation takes place | |
skip | No XSD validation takes place | |
type Q{uri}local | XSD validation takes place against the schema-defined type, present in the selected schema, that has the given URI and local name. | |
| When XSD validation takes place, determines whether schema components referenced using xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes within the source document are to be used. The option is ignored if XSD validation does not take place.
| |
true | XSD validation uses the schema components referenced using xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes in addition to the schema components present in the static context; these components must be compatible as described in [XDM 4.0] section 4.1.2 Schema Consistency. | |
false | Any xsi:schemaLocation and xsi:noNamespaceSchemaLocation attributes in the document are ignored. | |
| When XSD validation takes place, identifies the schema to be used for validation. If supplied, the value must match the role attribute of an xsl:import-schema declaration in the containing package. A zero-length string refers to the schema imported using an xsl:import-schema declaration with no role attribute.
| |
A sequence of absolute URI references is obtained as follows.
For an item in $uri-sequence that is an instance of xs:string, xs:anyURI, or xs:untypedAtomic, the value is cast to xs:anyURI. If the resulting URI reference is an absolute URI reference then it is used as is. If it is a relative URI reference R, then it is resolved as follows:
If the second argument $base-nodeoptions is suppliedan (that is, if the argument is present and non-empty)XNode, , then itR is resolved against the base URI of $base-that node.
If $options is supplied as a map and includes a value for the base-uri option, then R is resolved against that URI.
Otherwise itR is resolved against the static base URI from the static context of the expression containing the call to the document function. In cases where the source code of the stylesheet is available at execution time, this will typically be the location of the relevant stylesheet module.
For an item in $uri-sequence that is a node N, the node is atomized. The result must be a sequence whose items are all instances of xs:string, xs:anyURI, or xs:untypedAtomic. Each of these values is cast to xs:anyURI, and if the resulting URI reference is an absolute URI reference then it is used as is. If it is a relative URI reference R, then it is resolved against the base URI of as follows$base-node: if supplied, or against the base URI of the node that contained it otherwise.
If the second argument $options is an XNode, then R is resolved against the base URI of that node.
If $options is supplied as a map and includes a value for the base-uri option, then R is resolved against that URI.
Otherwise R is resolved against the base URI of N.
A relative URI is resolved against a base URI using the rules of the resolve-uri function. A dynamic error occurs (see below) if no base URI is available.
If $uri-sequence (after atomizing any nodes) contains an item other than an atomic item of type xs:string, xs:anyURI, or xs:untypedAtomic then a type error is raised [ERR XPTY0004] XP40.
Each of these absolute URI references is then processed as follows. Any fragment identifier that is present in the URI reference is removed, and the resulting absolute URI is cast to a string and then passed to the doc function defined in [Functions and Operators 4.0]. This returns a document node. If an error occurs during evaluation of the doc function, the processor may either raise this error in the normal way, or may recover by ignoring the failure, in which case the failing URI will not contribute any nodes to the result of the document function.
If the URI reference contained no fragment identifier, then this document node is included in the sequence of nodes returned by the document function.
If the URI reference contained a fragment identifier, then the fragment identifier is interpreted according to the rules for the media type of the resource representation identified by the URI, and is used to select zero or more nodes that are descendant-or-self nodes of the returned document node. As described in 2.3 Initiating a Transformation, the media type is available as part of the evaluation context for a transformation.
The sequence of nodes returned by the function is in document order, with no duplicates. This order has no necessary relationship to the order in which URIs were supplied in the $uri-sequence argument.
[ERR XTDE1160] When a URI reference contains a fragment identifier, it is a dynamic error if the media type is not one that is recognized by the processor, or if the fragment identifier does not conform to the rules for fragment identifiers for that media type, or if the fragment identifier selects something other than a sequence of nodes (for example, if it selects a range of characters within a text node).
A processor may provide an option which, if selected, causes the processor instead of raising this error, to ignore the fragment identifier and return the document node.
The set of media types recognized by a processor is implementation-defined.
[ERR XTDE1162] When a URI reference is a relative reference, it is a dynamic error if no base URI is available to resolve the relative reference. This can arise for example when the URI is contained in a node that has no base URI (for example a parentless text node), or when the second argument to the function is a node that has no base URI, or when the base URI from the static context is undefined.
One effect of these rules is that in an interpreted environment where the source code of the stylesheet is available and its base URI is known, then unless XML entities or xml:base are used, the expression document("") refers to the document node of the containing stylesheet module (the definitive rules are in [RFC3986]). The XML resource containing the stylesheet module is then processed exactly as if it were any other XML document, for example there is no special recognition of xsl:text elements, and no special treatment of comments and processing instructions.
The XPath rules for function calling ensure that it is a type error if the supplied value of the second argument is anything other than a single node. If XPath 1.0 compatibility mode is enabled, then a sequence of nodes may be supplied, and the first node in the sequence will be used.
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.
An options parameter has been added.
See 20.1 fn:document
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 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.