View Old View New View Both View Only Previous Next

This draft contains only sections that have differences from the version that it modified.

W3C

XSL Transformations (XSLT) Version 4.0

W3C Editor's Draft 23 February 2026

This version:
https://qt4cg.org/specifications/xslt-40/
Latest version:
https://qt4cg.org/specifications/xslt-40/
Most recent Recommendation of XSL Transformations (XSLT):
https://www.w3.org/TR/xslt-30/
Editor:
Michael Kay, Saxonica <http://www.saxonica.com/>

The following associated resources are available: Specification in XML format, XSD 1.1 Schema for XSLT 4.0 Stylesheets (non-normative), Relax-NG Schema for XSLT 4.0 Stylesheets (non-normative), Stylesheet for XML-to-JSON conversion (non-normative)


Abstract

This specification defines the syntax and semantics of XSLT 4.0, a language designed primarily for transforming XML documents into other XML documents.

XSLT 4.0 is a revised version of the XSLT 3.0 Recommendation [XSLT 3.0] published on 8 June 2017. Changes are presented in 1.2 What’s New in XSLT 4.0?.

XSLT 4.0 is designed to be used in conjunction with XPath 4.0, which is defined in [XPath 4.0]. XSLT shares the same data model as XPath 4.0, which is defined in [XDM 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.

Status of this Document

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

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

Dedication

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


10 Callable Components

This section describes three constructs that can be used to provide subroutine-like functionality that can be invoked from anywhere in the stylesheet: named templates (see 10.1 Named Templates), named attribute sets (see 10.2 Named Attribute Sets), and stylesheet functions (see 10.3 Stylesheet Functions).

[Definition: The following constructs are classified as invocation constructs: the instructions xsl:call-template, xsl:apply-templates, xsl:apply-imports, and xsl:next-match; XPath function calls that bind to stylesheet functions; XPath dynamic function calls; the functions accumulator-before and accumulator-after; the [xsl:]use-attribute-sets attribute. These all have the characteristic that they can cause evaluation of constructs that are not lexically contained within the calling construct.]

10.3 Stylesheet Functions

Changes in 4.0  

  1. Parameters on functions declared using xsl:function can now be defined as optional, with a default value supplied.  [Issue 155 PR 159 30 September 2022]

  2. 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.  [Issue 657 ]

[Definition: An xsl:function declaration declares the name, parameters, and implementation of a family of stylesheet functions that can be called from any XPath expression within the stylesheet (subject to visibility rules).]

<!-- Category: declaration -->
<xsl:function
  name = eqname
  as? = sequence-type〔'item()*'〕
  visibility? = "public" | "private" | "final" | "abstract"〔'private'〕
  streamability? = "unclassified" | "absorbing" | "inspection" | "filter" | "shallow-descent" | "deep-descent" | "ascent" | eqname〔'unclassified'〕
  override-extension-function? = boolean〔'yes'〕
  [override]? = boolean〔'yes'〕
  new-each-time? = "yes" | "true" | "1" | "no" | "false" | "0" | "maybe"
  cache? = boolean〔'no'〕 >
  <!-- Content: (xsl:param*, sequence-constructor) -->
</xsl:function>

The effect of an xsl:function declaration is to add a function definition to the static context for all XPath expressions used in the stylesheet (including an XPath expression used within a predicate in a pattern).

The content of the xsl:function element consists of zero or more xsl:param elements that specify the formal parameters of the function, followed by a sequence constructor that defines the value to be returned by the function.

The children and attributes of the xsl:function declaration translate directly into properties of the function definition:

  • The xsl:function/@name attribute defines the function’s name.

  • The xsl:param children define the function’s parameters:

    • The xsl:param/@name attribute defines the name of the parameter.

    • The xsl:param/@required attribute determines whether the parameter is mandatory or optional.

    • The xsl:param/@as attribute determines the required type of the parameter.

    • The xsl:param/@select attribute determines a default value for an optional parameter.

  • The xsl:function/@as attribute defines the return type of the function.

  • The implementation of the function is defined by the sequence constructor content of the xsl:function element.

An xsl:function declaration can only appear as a top-level element in a stylesheet module.

10.3.1 Function Name and Arity

Changes in 4.0  

  1. 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.   [Issues 657 2235 PRs 2200 2236 7 October 2025]

The name of the function is given by the name attribute.

[ERR XTSE0740] It is a static error if a stylesheet function has a name that is in no namespace, unless the visibility of the function is private.

Note:

XSLT 4.0 allows the function name to be unprefixed, provided that its visibility is private. This represents a QName in no namespace. A function call using an unprefixed function name is resolved to a no-namespace function name in preference to a function in the default function namespace, which for XSLT is always the fn namespace.

Note:

To prevent the namespace URI used for the function name appearing in the result document, use the exclude-result-prefixes attribute on the xsl:stylesheet element: see 11.1.3 Namespace Nodes for Literal Result Elements.

The name of the function must not be in a reserved namespace: [see ERR XTSE0080]

The function parameters are defined by child xsl:param elements. The parameters must have distinct names. The list of parameters must contain zero or more required parameters, followed by zero or more optional parameters. A parameter is optional if it has the attribute required="no"; otherwise, it is required.

The default value for an optional parameter can be defined using the select attribute or the contained sequence constructor of the xsl:param element. These must be absent for a required parameter. If an optional parameter has no select attribute and the contained sequence constructor is empty, then the default value will be an empty sequence. This will lead to a type error if the required type of the parameter does not permit an empty sequence.

Note:

When considering function overriding, dynamic function calls, and details such as the function-lookup function, it is useful to think of an xsl:function declaration with optional parameters as a syntactic short-cut for a set of xsl:function declarations of varying arity, each of which calls the function with next-higher arity, supplying the default value of the parameter explicitly in the function call.

This is not an exact equivalence, however, because of the rules allowing default values of function parameters to be context-dependent.

The function definition derived from the xsl:function declaration has an arity range from M to M+N, where M is the number of required parameters and N is the number of optional parameters. The arity range constrains the number of arguments that may appear in a call to this function.

For example, the following xsl:function declaration declares a function, named f:compare, with an arity range of (2 to 3). The effect of calling f:compare($a, $b) is the same as the effect of calling f:compare($a, $b, { "order": "ascending" }).

<xsl:function name="f:compare" as="xs:boolean">
  <xsl:param name="arg1" as="xs:double"/>
  <xsl:param name="arg2" as="xs:double"/>
  <xsl:param name="options" as="map(*)" 
             required="no" 
             select="{ 'order': 'ascending' }"/>
  <xsl:if test="$options?order = 'descending'" 
          then="$arg1 gt $arg2" 
          else="$arg2 gt $arg1"/>
</xsl:function>

Note:

Functions are not polymorphic. Although the XPath function call mechanism allows two functions to have the same name and non-overlapping arity ranges, it does not allow them to be distinguished by the types of their arguments.

I Changes since XSLT 3.0 (Non-Normative)

I.1 Changes in this specification

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

    See 1.2 What’s New in XSLT 4.0?

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

    See 1.2 What’s New in XSLT 4.0?

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

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

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

    See 7.1 The xsl:for-each instruction

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

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

    See 13.1.2 Comparing Sort Key Values

  9. Functions that accept a lexical QName as an argument, such as key, function-available, element-available, type-available, system-property, accumulator-before, and accumulator-after, now have the option of supplying an xs:QName value instead. [This change was in the editor's draft accepted by the WG as its baseline when it started work.]

    See 20 Additional Functions

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

  11. 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.2 Extension Instructions

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

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

    See 6.3.2.3 XNode Patterns

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

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

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

    See 3.11.2 Stylesheet Inclusion

  17. Named record types are introduced.

    See 5.4.2 Named Record Types

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

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

    See 8.4 Try/Catch

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

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

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

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

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

    See 13.1.2 Comparing Sort Key Values

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

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

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

    See 6.9 Overriding Template Rules

  28. The special rule allowing xsl:map to have multiple consumable operands does not apply if duplicate keys are permitted.

    See 19.8.4.23 Streamability of xsl:map

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

  30. JNode Patterns are new in 4.0.

    See 6.3.2.4 JNode Patterns

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

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

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

  34. PR 353 

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

    See 3.7 Stylesheet Element

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

    See 3.13.2 The xsl:note element

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

  36. PR 406 

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

    See 22.1 Array Construction

  37. PR 470 

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

    See 3.7.1 The fixed-namespaces Attribute

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

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

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

  41. PR 599 

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

    See 3.8 Simplified Stylesheet Modules

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

  43. PR 717 

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

    See 18.2.9 Capturing Accumulators

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

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

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

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

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

  49. PR 1306 

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

    See 10.4.1 The xsl:sequence Instruction

  50. PR 1361 

    The term atomic value has been replaced by atomic item.

    See 2.1 Terminology

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

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

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

  54. PR 1689 

    Composite merge keys are now allowed.

    See 15 Merging

  55. PR 1703 

    Ordered maps are introduced.

    See 21.1 Map Instructions

  56. 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.4 Standard Attributes

    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.

    See 3.15.1 Multiple Schemas

  57. PR 1856 

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

    See 17.1 The xsl:analyze-string Instruction

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

  59. 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.5.3 Locating Packages

  60. PR 2006 

    A new function fn:apply-templates is introduced.

    See 6.7.3 The apply-templates Function

  61. PR 2008 

    The xsl:select instruction is new in 4.0.

    See 10.4.2 The xsl:select Instruction

  62. PR 2011 

    The static typing rules have been updated to take account of new constructs in XPath 4.0.

    See 19.1 Determining the Static Type of a Construct

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

    See 9.3 Values of Variables and Parameters

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