The following associated resources are available: Specification in XML format, XSD 1.1 Schema for XSLT 4.0 Stylesheets (non-normative), Relax-NG Schema for XSLT 4.0 Stylesheets (non-normative), Stylesheet for XML-to-JSON conversion (non-normative)
Copyright © 2026 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and document use rules apply.
This specification defines the syntax and semantics of XSLT 4.0, a language designed primarily for transforming XML documents into other XML documents.
XSLT 4.0 is a revised version of the XSLT 3.0 Recommendation [XSLT 3.0] published on 8 June 2017. Changes are presented in 1.2 What’s New in XSLT 4.0?.
XSLT 4.0 is designed to be used in conjunction with XPath 4.0, which is defined in [XPath 4.0]. XSLT shares the same data model as XPath 4.0, which is defined in [XDM 3.0], and it uses the library of functions and operators defined in [Functions and Operators 4.0]. XPath 4.0 and the underlying function library introduce a number of enhancements, for example the availability of union and record types.
This document contains hyperlinks to specific sections or definitions within other documents in this family of specifications. These links are indicated visually by a superscript identifying the target specification: for example XP for XPath 4.0, DM for the XDM data model version 4.0, FO for Functions and Operators version 4.0.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
This document has no official standing. It is produced by the editor as a proposal for community review. Insofar as it copies large amounts of text from the W3C XSLT 3.0 Recommendation, W3C copyright and similar provisions apply.
The publications of this community group are dedicated to our co-chair, Michael Sperberg-McQueen (1954–2024).
A processormay output a final result tree as a sequence of octets, although it is not required to be able to do so (see 27 Conformance). This process is described as serialization. Stylesheet authors can use xsl:output declarations to specify how they wish result trees to be serialized. If a processor serializes a final result tree, it must do so as specified by these declarations.
The rules governing the output of the serializer are defined in [XSLT and XQuery Serialization]. The serialization is controlled using a number of serialization parameters. The values of these serialization parameters may be set within the stylesheet, using the xsl:output, xsl:result-document, and xsl:character-map declarations.
[Definition: A character map allows a specific character appearing in a text or attribute node in the final result tree to be substituted by a specified string of characters during serialization.] The effect of character maps is defined in [XSLT and XQuery Serialization].
The character map that is supplied as a parameter to the serializer is determined from the xsl:character-map elements referenced from the xsl:output declaration for the selected output definition.
The xsl:character-map element is a declaration that may appear as a child of the xsl:stylesheet element.
<!-- Category: declaration -->
<xsl:character-map
name = eqname
use-character-maps? = eqnames >
<!-- Content: (xsl:output-character*) -->
</xsl:character-map>
The xsl:character-map declaration declares a character map with a name and a set of character mappings. The character mappings are specified by means of xsl:output-character elements contained either directly within the xsl:character-map element, or in further character maps referenced in the use-character-maps attribute.
The requiredname attribute provides a name for the character map. When a character map is used by an output definition or another character map, the character map with the highest import precedence is used.
The name of a character map is local to the package in which its declaration appears; it may be referenced only from within the same package.
[ERR XTSE1580] It is a static error if a package contains two or more character maps with the same name and the same import precedence, unless it also contains another character map with the same name and higher import precedence.
The optional use-character-maps attribute lists the names of further character maps that are included into this character map.
[ERR XTSE1590] It is a static error if a name in the use-character-maps attribute of the xsl:output or xsl:character-map elements does not match the name attribute of any xsl:character-map in the containing package.
[ERR XTSE1600] It is a static error if a character map references itself, directly or indirectly, via a name in the use-character-maps attribute.
It is not an error if the same character map is referenced more than once, directly or indirectly.
For every xsl:character-map declaration in a package, other than one that is overridden by another of higher import precedence, the static context of the package includes a named character map derived from the xsl:character-map declaration. The name of the named character map is the QName formed by expanding the value of the name attribute, and the content is a map of type map{xs:string, xs:string} that maps characters (represented as xs:string instances of length 1) to their replacement strings.
Recursive expansion of character maps using use-character-maps attributes may produce several mappings for the same character. In this situation, the last character mapping takes precedence. To establish the ordering, the following rules are used:
Within a single xsl:character-map element, the characters defined in character maps referenced in the use-character-maps attribute are considered before the characters defined in the child xsl:output-character elements.
The character maps referenced in a single use-character-maps attribute are considered in the order in which they are listed in that attribute. The expansion is depth-first: each referenced character map is fully expanded before the next one is considered.
Two xsl:output-character elements appearing as children of the same xsl:character-map element are considered in document order.
The xsl:output-character element is defined as follows:
<xsl:output-character
character = char
string = string />
The character map that is passed as a parameter to the serializer contains a mapping for the character specified in the character attribute to the string specified in the string attribute.
Character mapping is not applied to characters for which output escaping has been disabled as described in 26.5 Disabling Output Escaping.
If a character is mapped, then it is not subjected to XML or HTML escaping.
Character maps can be useful when producing serialized output in a format that resembles, but is not strictly conformant to, HTML or XML. For example, when the output is a JSP page, there might be a need to generate the output:
<jsp:setProperty name="user" property="id" value='<%= "id" + idValue %>'/>
Although this output is not well-formed XML or HTML, it is valid in Java Server Pages. This can be achieved by allocating three Unicode characters (which are not needed for any other purpose) to represent the strings <%, %>, and ", for example:
<xsl:character-map name="jsp"> <xsl:output-character character="«" string="<%"/> <xsl:output-character character="»" string="%>"/> <xsl:output-character character="§" string='"'/> </xsl:character-map>
When this character map is referenced in the xsl:output declaration, the required output can be produced by writing the following in the stylesheet:
<jsp:setProperty name="user" property="id" value='«= §id§ + idValue »'/>
This works on the assumption that when an apostrophe or quotation mark is generated as part of an attribute value by the use of character maps, the serializer will (where possible) use the other choice of delimiter around the attribute value.
The following example illustrates a composite character map constructed in a modular fashion:
<xsl:output name="htmlDoc" use-character-maps="htmlDoc"/> <xsl:character-map name="htmlDoc" use-character-maps="html-chars doc-entities windows-format"/> <xsl:character-map name="html-chars" use-character-maps="latin1 ..."/> <xsl:character-map name="latin1"> <xsl:output-character character=" " string="&nbsp;"/> <xsl:output-character character="¡" string="&iexcl;"/> ... </xsl:character-map> <xsl:character-map name="doc-entities"> <xsl:output-character character="" string="&t-and-c;"/> <xsl:output-character character="" string="&chap1;"/> <xsl:output-character character="" string="&chap2;"/> ... </xsl:character-map> <xsl:character-map name="windows-format"> <!-- newlines as CRLF --> <xsl:output-character character="
" string="
"/> <!-- tabs as three spaces --> <xsl:output-character character="	" string=" "/> <!-- images for special characters --> <xsl:output-character character="" string="<img src='special1.gif' />"/> <xsl:output-character character="" string="<img src='special2.gif' />"/> ... </xsl:character-map>
Note:
When character maps are used, there is no guarantee that the serialized output will be well-formed XML (or HTML). Furthermore, the fact that the result tree was validated against a schema gives no guarantee that the serialized output will still be valid against the same schema. Conversely, it is possible to use character maps to produce schema-valid output from a result tree that would fail validation.
Note:
The value of the string attribute must be a literal string; this means it must consist entirely of characters that are valid in XML 1.0 or XML 1.1, depending on the version of XML used for the containing stylesheet module. The string can however be expressed as a shadow attribute (see 3.13.4 Shadow Attributes), and this allows it to be defined using a static expression. For example, the character U+2398 (NEXT PAGE, ⎘) might be mapped to the control character U+000C (FORM FEED) by writing <xsl:output-character char="⎘" _string="{char(0x0C)}"/>. This depends on the processor allowing the form-feed character to appear in strings: the data model allows this, but processors are not required to support it: see Section 2.8.4 XML and XSD VersionsDM.