XSL Transformations (XSLT) Specification (original) (raw)
Abstract
XSLT is a language for transforming XML documents into other XML documents.
XSLT is designed for use as part of XSL, which is a stylesheet language for XML. In addition to XSLT, XSL includes an XML vocabulary for specifying formatting. XSL specifies the styling of an XML document by using XSLT to describe how the document is transformed into another XML document that uses the formatting vocabulary.
XSLT is also designed to be used independently of XSL. However, XSLT is not intended as a completely general-purpose XML transformation language. Rather it is designed primarily for the kinds of transformation that are needed when XSLT is used as part of XSL.
Status of this document
This is a W3C Working Draft for review by W3C members and other interested parties. It is a draft document and may be updated, replaced, or obsoleted by other documents at any time. The material in this draft was previously part of the XSL Working Draft. The XSL Working Group will not allow early implementation to constrain its ability to make changes to this specification prior to final release. It is inappropriate to use W3C Working Drafts as reference material or to cite them as other than "work in progress". A list of current W3C working drafts can be found at http://www.w3.org/TR.
This draft is intended to be "feature complete". The Working Group plans to use future drafts to stabilize the current functionality; it does not intend to add any new functionality in version 1.0.
The XSL WG and the XML Linking WG have agreed to unify XSLT expressions and XPointers [XPointer]. A common core semantic model for querying has been agreed upon, and this draft follows this model (see [6.1 Location Paths]). However, further changes particularily in the syntax will probably be necessary.
This is part of the Style activity.
Comments may be sent to xsl-editors@w3.org;archivesof the comments are available. Public discussion of XSL, including XSL Transformations, takes place on the XSL-Listmailing list.
Table of contents
1. Introduction
2. [Stylesheet Structure](#Stylesheet Structure)
3. Forwards-compatible Processing
4. Data Model
4.1 Root Node
4.2 Element Nodes
4.2.1 Unique IDs
4.2.2 Base URI
4.3 Attribute Nodes
4.4 Namespace Nodes
4.5 [Processing Instruction Nodes](#Processing Instruction Nodes)
4.6 [Comment Nodes](#Comment Nodes)
4.7 [Text Nodes](#Text Nodes)
4.8 Whitespace Stripping
5. [Using the Result Tree](#Using the Result Tree)
6. Expressions and Patterns
6.1 Location Paths
6.1.1 Axes
6.1.2 [Node Tests](#Node Tests)
6.1.3 Predicates
6.1.4 Abbreviated Syntax
6.2 Expressions
6.2.1 Basics
6.2.2 Node-sets
6.2.3 Booleans
6.2.4 Numbers
6.2.5 Strings
6.2.6 [Result Tree Fragments](#Result Tree Fragments)
6.2.7 [Extension Functions](#Extension Functions)
6.2.8 System Functions
6.2.9 Lexical Structure
6.3 Patterns
6.4 Declarations
6.4.1 Declaring Keys
6.4.2 Declaring Extension Functions
6.4.3 Declaring Locales
7. [Template Rules](#Template Rules)
7.1 [Processing Model](#Processing Model)
7.2 [Defining Template Rules](#Defining Template Rules)
7.3 [Applying Template Rules](#Applying Template Rules)
7.4 Conflict Resolution for Template Rules
7.5 [Built-in Template Rules](#Built-in Template Rules)
7.6 Modes
8. Named Templates
9. [Creating the Result Tree](#Creating the Result Tree)
9.1 [Creating Elements and Attributes](#Creating Elements and Attributes)
9.1.1 [Literal Result Elements](#Literal Result Elements)
9.1.2 [Creating Elements with xsl:element](#Creating Elements with xsl:element)
9.1.3 Creating Attributes with xsl:attribute
9.1.4 [Named Attribute Sets](#Named Attribute Sets)
9.2 [Creating Text](#Creating Text)
9.3 [Creating Processing Instructions](#Creating Processing Instructions)
9.4 [Creating Comments](#Creating Comments)
9.5 Copying
9.6 [Computing Generated Text](#Computing Generated Text)
9.6.1 [Generating Text with xsl:value-of](#Generating Text with xsl:value-of)
9.6.2 Attribute Value Templates
9.7 Numbering
9.7.1 Number to String Conversion Attributes
10. Repetition
11. [Conditional Processing](#Conditional Processing)
11.1 [Conditional Processing with xsl:if](#Conditional Processing with xsl:if)
11.2 [Conditional Processing with xsl:choose](#Conditional Processing with xsl:choose)
12. Sorting
13. Variables and Parameters
14. Messages
15. [Combining Stylesheets](#Combining Stylesheets)
15.1 Stylesheet Import
15.2 [Stylesheet Inclusion](#Stylesheet Inclusion)
15.3 [Embedding Stylesheets](#Embedding Stylesheets)
Appendices
A. DTD Fragment for XSLT Stylesheets
B. References
B.1 [Normative References](#Normative References)
B.2 [Other References](#Other References)
C. Examples
A [Formatting Objects Example](#Formatting Objects Example)
B [XHTML Example](#XHTML Example)
D. Acknowledgements
E. [Changes from Previous Public Working Draft](#Changes from Previous Public Working Draft)
1. Introduction
A transformation expressed in XSLT describes rules for transforming a source tree into a result tree. The transformation is achieved by associating patterns with templates. A pattern is matched against elements in the source tree. A template is instantiated to create part of the result tree. The result tree is separate from the source tree. The structure of the result tree can be completely different from the structure of the source tree. In constructing the result tree, elements from the source tree can be filtered and reordered, and arbitrary structure can be added.
A transformation expressed in XSLT is called a stylesheet. This is because, in the case when XSLT is transforming into the XSL formatting vocabulary, the transformation functions as a stylesheet.
This document does not specify how an XSLT stylesheet is associated with an XML document. It is recommended that XSL processors support the mechanism described in [XML Stylesheet].
A stylesheet contains a set of template rules. A template rule has two parts: a pattern which is matched against nodes in the source tree and a template which can be instantiated to form part of the result tree. This allows a stylesheet to be applicable to a wide class of documents that have similar source tree structures.
A template is instantiated for a particular source element to create part of the result tree. A template can contain elements that specify literal result element structure. A template can also contain elements that are instructions for creating result tree fragments. When a template is instantiated, each instruction is executed and replaced by the result tree fragment that it creates. Instructions can select and process descendant source elements. Processing a descendant element creates a result tree fragment by finding the applicable template rule and instantiating its template. Note that elements are only processed when they have been selected by the execution of an instruction. The result tree is constructed by finding the template rule for the root node and instantiating its template.
In the process of finding the applicable template rule, more than one template rule may have a pattern that matches a given element. However, only one template rule will be applied. The method for deciding which template rule to apply is described in [7.4 Conflict Resolution for Template Rules].
XSLT uses XML namespaces [XML Names] to distinguish elements that are instructions to the XSLT processor from elements that specify literal result tree structure. Instruction elements all belong to the XSLT namespace. The examples in this document use a prefix of xsl:
for elements in the XSLT namespace.
XSLT includes an expression language (see [6 Expressions and Patterns]) that is used for selecting elements for processing, for conditional processing and for generating text. The expression language is not a complete programming language. XSLT provides an extension mechanism to allow access from the expression language to a complete programming language such as ECMAScript or Java. XSLT does not require support for any programming language. Therefore XSLT stylesheets that must be portable across all XSLT implementations cannot depend on this extension mechanism.
2. Stylesheet Structure
A stylesheet is represented by an xsl:stylesheet
element in an XML document. xsl:transform
is allowed as a synonym for xsl:stylesheet
.
XSLT processors must use the XML namespaces mechanism [XML Names] for both source documents and stylesheets. All XSLT defined elements, that is those specified in this document with a prefix of xsl:
, will only be recognized by the XSLT processor if they belong to a namespace with the URIhttp://www.w3.org/XSL/Transform/1.0
; XSLT defined elements are recognized only in the stylesheet not in the source document.
The xsl:stylesheet
element may contain the following types of elements:
xsl:import
xsl:include
xsl:strip-space
xsl:preserve-space
xsl:key
xsl:functions
xsl:locale
xsl:attribute-set
xsl:variable
xsl:param-variable
xsl:template
This example shows the structure of a stylesheet. Ellipses (...
) indicate where attribute values or content have been omitted. Although this example shows one of each type of allowed element, stylesheets may contain zero or more of each of these elements.
<xsl:stylesheet xmlns:xsl="" title="undefined" rel="noopener noreferrer">http://www.w3.org/XSL/Transform/1.0"> <xsl:import href="..."/>
<xsl:include href="..."/>
<xsl:strip-space elements="..."/>
<xsl:preserve-space elements="..."/>
<xsl:key name="..." match="..." use="..."/>
<xsl:functions ns="..."> ...
<xsl:locale name="..."> ...
<xsl:attribute-set name="..."> ...
<xsl:variable name="...">...
<xsl:param-variable name="...">...
<xsl:template match="..."> ...
<xsl:template name="..."> ...
The order in which the children of the xsl:stylesheet
element occur is not significant except for xsl:import
elements and for error recovery. Users are free to order the elements as they prefer, and stylesheet creation tools need not provide control over the order in which the elements occur.
3. Forwards-compatible Processing
An XSLT processor must treat any namespace whose URI starts with the http://www.w3.org/XSL/Transform/
in the same way as the XSLT 1.0 namespace (http://www.w3.org/XSL/Transform/1.0
) except that it must recover from errors as follows:
- Unrecognized attributes on elements in the XSLT namespace must be ignored
- Unrecognized top-level XSLT elements must be ignored along with their content
- Error reporting for unrecognized XSLT elements in templates must be lazy: in other words it's not an error to have an unrecognized XSLT element unless the element is actually instantiated
- Similarly error reporting for bad expression syntax must be lazy: it's not an error to have bad expression syntax in an attribute on some element unless the element containing the bad syntax is instantiated
Ed. Note: What happens with stylesheets that mix XSLT namespaces with different versions?
Thus any XSLT 1.0 processor must be able to process the following stylesheet without error:
<xsl:stylesheet xmlns:xsl="" title="undefined" rel="noopener noreferrer">http://www.w3.org/XSL/Transform/1.1"> <xsl:template name="/"> xsl:choose <xsl:when test="system-property('xsl:version') >= 1.1"> xsl:exciting-new-1.1-feature/ xsl:otherwise
Sorry this stylesheet requires XSLT 1.1.
4. Data Model
XSLT operates on an XML document, whether a stylesheet or a source document, as a tree. Any two stylesheets or source documents that have the same tree will be processed the same by XSLT. The XML document resulting from the tree construction process is also a tree. This section describes how XSLT models an XML document as a tree. This model is conceptual only and does not mandate any particular implementation.
XML documents operated on by XSLT must conform to the XML namespaces specification [XML Names].
The tree contains nodes. There are seven kinds of node:
- root nodes
- element nodes
- text nodes
- attribute nodes
- namespace nodes
- processing instruction nodes
- comment nodes
Neither processing instruction nodes nor comment nodes are included in the tree for the stylesheet.
For every type of node there is a way of determining a stringvalue for a node of that type. For some types of node, the value is part of the node; for other types of node, the value is computed from the value of descendant nodes.
Issue (data-entity): Should XSLT provide support for external data entities and notations?
Issue (entity-ref): Should XSLT provide support for entity references?
Issue (dtd): Should XSLT provide support for DTDs in the data model?
4.1 Root Node
The root node is the root of the tree. It does not occur anywhere else in the tree. It has a single child which is the element node for the document element of the document.
The value of the root node is the value of the document element.
4.2 Element Nodes
There is an element node for every element in the document. An element has an expanded name consisting of a local name and a possibly null URI reference (see [XML Names]); the URI reference will be null if the element type name has no prefix and there is no default namespace in scope. A relative URI reference should be resolved into an absolute URI during namespace processing.
The children of an element node are the element nodes, comment nodes, processing instruction nodes and text nodes for its content. Entity references to both internal and external entities are expanded. Character references are resolved.
Thedescendants of an element node are the children of the element node and the descendants of the children that are element nodes.
The value of an element node is the string that results from concatenating all characters that are descendants of the element node in the order in which they occur in the document.
The set of all element nodes in a document can be ordered according to the order of the start-tags of the elements in the document; this is known asdocument order.
Ed. Note: Need a definition of document order that handles arbitrary node types, including attributes.
4.2.1 Unique IDs
An element object may have a unique identifier (ID). This is the value of the attribute which is declared in the DTD as typeID
. No two elements in a document may have the same unique ID. If an XML processor reports two elements in a document as having the same unique ID (which is possible only if the document is invalid) then the second element must be treated as not having a unique ID.
NOTE: If a document does not have a DTD, then no element in the document will have a unique ID.
4.2.2 Base URI
An element node also has an associated URI called its base URI which is used for resolving attribute values that represent relative URIs into absolute URIs. If an element occurs in an external entity, the base URI of that element is the URI of the external entity. Otherwise the base URI is the base URI of the document.
4.3 Attribute Nodes
Each element node has an associated set of attribute nodes. A defaulted attribute is treated the same as a specified attribute. If an attribute was declared for the element type in the DTD, but the default was declared as #IMPLIED
, and the attribute was not specified on the element, then the element's attribute set does not contain a node for the attribute.
An attribute node has an expanded name and has a string value. The expanded name consists of a local name and a possibly null URI (see[XML Names]); the URI will be null if the specified attribute name did not have a prefix. The value is the normalized value as specified by the XML Recommendation [XML]. An attribute whose normalized value is a zero-length string is not treated specially: it results in an attribute node whose value is a zero-length string.
There are no attribute nodes for attributes that declare namespaces (see [XML Names]).
Issue (external-dtd): Should we specify something about how we expect XSLT processors to process external DTDs and parameter entities? For example, what happens if an attribute default is declared in an external DTD?
4.4 Namespace Nodes
Each element has an associated set of namespace nodes, one for each namespace prefix that is in scope for the element and one for the default namespace if one is in scope for the element. This means that an element will have a namespace node:
- for every attribute on the element whose name starts with
xmlns:
; - for every attribute on an ancestor element whose name starts
xmlns:
unless the element itself or a nearer ancestor redeclares the prefix; - for an
xmlns
attribute, unless its value is the empty string.NOTE: An attribute
xmlns=""
"undeclares" the default namespace (see [XML Names]).
A namespace node has a name which is a string giving the prefix. This is empty if the namespace node is for the default namespace. A namespace node also has a value which is the namespace URI. If the namespace declaration specifies a relative URI, then the resolved absolute URI is used as the value.
When writing an element node in the result tree out as XML, an XSLT processor must add sufficient namespace-declaring attributes to the start-tag to ensure that if a tree were recreated from the XML, then the set of namespace nodes on the element node in the recreated tree would be equal to or a superset of the set of namespace nodes of the element node in the result tree.
NOTE: The semantics of a document type may treat parts of attribute values or data content as namespace prefixes. The presence of namespace nodes ensures that the semantics can be preserved when the tree is written out as XML.
4.5 Processing Instruction Nodes
There is a processing instruction node for every processing instruction.
Ed. Note: What about processing instructions in the internal subset or elsewhere in the DTD?
A processing instruction has a name. This is a string equal to the processing instruction's target. It also has a value. This is a string equal to the part of the processing instruction following the target and any whitespace. It does not include the terminating?>
.
4.6 Comment Nodes
There is a comment node for every comment.
Ed. Note: What about comments in the internal subset or elsewhere in the DTD?
A comment has a value. This is a string equal to the text of the comment not including the opening <!--
or the closing-->
.
4.7 Text Nodes
Character data is grouped into text nodes. As much character data as possible is grouped into each text node: a text node never has an immediately following or preceding sibling that is a text node. The value of a text node is the character data.
Each character within a CDATA section is treated as character data. Thus <![CDATA[<]]>
in the source document will treated the same as <
. Both will result in a single <
character in a text node in the tree.
NOTE: When a text node that contains a
<
character is written out as XML, the<
character must be escaped by, for example, using<
, or including it in a CDATA section.
Characters inside comments or processing instructions are not character data. Line-endings in external entities are normalized to #xA as specified in the XML Recommendation [XML].
4.8 Whitespace Stripping
After the tree has been constructed, but before it is otherwise processed by XSLT, some text nodes may be stripped. The stripping process takes as input a set of element types for which whitespace must be preserved. The stripping process is applied to both stylesheets and source documents, but the set of whitespace-preserving element types is determined differently for stylesheets and for source documents.
A text node is preserved if any of the following apply:
- The element type of the parent of the text node is in the set of whitespace-preserving element types.
- The text node contains at least one non-whitespace character. As in XML, a whitespace character is #x20, #x9, #xD or #xA.
- An ancestor element of the text node has an
xml:space
attribute with a value ofpreserve
, and no closer ancestor element hasxml:space
with a value ofdefault
.
Otherwise the text node is stripped.
The xml:space
attributes are not stripped from the tree.
NOTE: This implies that if an
xml:space
attribute is specified on a literal result element, it will be included in the result.
For stylesheets, the set of whitespace-preserving element types consists of just xsl:text
.
For source documents, the set of whitespace-preserving element types is determined using the stylesheet as follows:
- If the
xsl:stylesheet
element specifies adefault-space
attribute with a value ofstrip
, then the set is initially empty. Otherwise the set initially contains all element types that occur in the document. - The
xsl:strip-space
element causes element types to be removed from the set of whitespace-preserving element types. Theelements
attribute gives a white-space separated list of the names of the element types. - The
xsl:preserve-space
element causes element types to be added to the set of whitespace-preserving element types. Theelements
attribute gives a white-space separated list of the names of the element types.
Ed. Note: Clarify how these declarations interact with each other and with xsl:import.
5. Using the Result Tree
The xsl:stylesheet
element has an optionalresult-ns
attribute; the value must be a namespace prefix. If there is a namespace declared as the default namespace, then an empty string may be used as the value to specify that the default namespace is the result namespace.
The result-ns
attribute is a hint to the XSLT processor that it should do something with the result tree other than simply output it as XML. XSLT processors are not required to pay attention to the hint and may simply output the result tree as XML. If the result-ns
attribute is not specified, then the result tree must be output as XML. If the result-ns
attribute is specified, all elements in the result tree must belong to the namespace identified by this prefix (the result namespace).
When an XSLT processor outputs the result tree as a sequence of bytes that represents the result tree in XML, it must do so in such a way that the sequence of bytes is a well-formed XML document conforming to the XML Namespaces Recommendation [XML Names] and that if a new tree was constructed from the sequence of bytes as specified in [4 Data Model], the new tree would be the same as the result tree, with the following possible exceptions:
- The order of attributes in the two trees may be different.
- The new tree may contain namespace nodes that were not present in the result tree.
NOTE: An XSLT processor may need to add namespace declarations in the course of outputting the result tree as XML.
A result namespace of http://www.w3.org/XSL/Format/1.0
indicates that the result tree should be interpreted according to the semantics defined in [XSL]. XSL requires that XSL processors respect this hint. The examples in this document use thefo:
prefix for this namespace.
A result namespace of http://www.w3.org/TR/REC-html40
indicates that the result tree should be output as HTML that conforms to the HTML 4.0 Recommendation rather than as XML; for example,
<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0" xmlns="http://www.w3.org/TR/REC-html40" result-ns="">
<xsl:template match="/"> xsl:apply-templates/
...
The xsl:stylesheet
element can include anindent-result
attribute with values yes
orno
. If the stylesheet specifiesindent-result="yes"
, then the XSLT processor may add whitespace to the result tree (possibly based on whitespace stripped from either the source document or the stylesheet) in order to indent the result nicely; if indent-result="no"
, it must not add any whitespace to the result. When adding whitespace withindent-result="yes"
, the XSLT processor can use any algorithm provided that the result is the same as the result withindent-result="no"
after whitespace is stripped from both using the process described with the set of whitespace-preserving element types consisting of just xsl:text
.
6. Expressions and Patterns
Ed. Note: The XSL WG and the XML Linking WG have agreed to unify XSLT expressions and XPointers. A common core semantic model for querying has been agreed upon, and this draft follows this model. However, further changes particularily in the syntax will probably be necessary.
Expressions are used in XSLT for a variety of purposes including:
- selecting nodes for processing;
- specifying conditions for different ways of processing a node;
- generating text to be inserted in the result tree.
An expression is evaluated to yield an object which has one of the following types:
- boolean (true or false)
- number (a floating point number)
- string (a sequence of UCS characters)
- node-set (a set of nodes from source trees)
- result tree fragment
Expression evaluation occurs with respect to a context, which consists of:
- a node (the context node)
- a node list (the context node list)
- a set of variable bindings
- a node key function
- a set of implementations of extension functions
- the set of namespace declarations in scope for the expression
The context node is always a member of the context node list. The variable bindings consist of a mapping from variable names to variable values. The value of a variable is an object which can have any of the types which are possible for the value of an expression.
The variable bindings, node key function, extension functions and namespace declarations used to evaluate a subexpression are always the same as those used to evaluate the containing expression. The context node and context node list used to evaluate a subexpression is sometimes different from the context node and context node list used to evaluate the containing expression. When the evaluation of a kind of expression is described, it will always be explicitly stated if the context node and node list change for the evaluation of subexpressions; if nothing is said about the context node and context node list, they remain unchanged for the evaluation of subexpressions of that kind of expression.
The node key function takes a pair of strings (a key name and a key value) and a document and returns a set of nodes (the nodes in the document that have a key with the specified name and value).
In XSLT, expressions occur in attribute values. The grammar specified in this section applies to the attribute value after XML 1.0 normalization. So, for example, if the grammar uses the character<
this must not appear in the XML source for the stylesheet as <
but must be quoted according to XML 1.0 rules by, for example, entering it as <
.
A top-level expression (an expression not occurring within an expression) gets its context as follows:
- the context node comes from the current node
- the context node list comes from the current node list
- the variable bindings are the bindings in scope on the element which has the attribute in which the expression occurs (see[13 Variables and Parameters])
- the node key function is specified by top-level
xsl:key
elements (see [6.4.1 Declaring Keys]) - the implementations of extension functions are provided by top-level
xsl:functions
elements (see [6.4.2 Declaring Extension Functions]), and may also be provided externally to the stylesheet by means not specified by XSLT - the set of namespace declarations are those in scope on the element which has the attribute in which the expression occurs; the default namespace (as declared by
xmlns
) is not part of this set
One important kind of expression is a location path. A location path selects a set of nodes relative to the context node. The result of evaluating an expression that is a location path is the node-set containing the nodes selected by the location path. Location paths can recursively contain expressions which are used to filter lists of nodes.
Certain contexts in XSLT make use of a pattern. A pattern specifies a set of conditions on a node. A node that satisfies the conditions matches the pattern; a node that does not satisfy the conditions does not match the pattern. The syntax for patterns is a subset of the syntax for expressions. In particular location paths that meet certain restrictions can be used as patterns. An expression that is also a pattern always evaluates to an object of type node-set. A node matches a pattern if the node is a member of the result of evaluating the pattern as an expression with respect to some possible context; the possible contexts are those whose context node is the node being matched or one of its ancestors.
In the following grammar, the nonterminals QName and NCName are defined in [XML Names], and S is defined in[XML].
Expressions (including patterns and location paths) are parsed by first dividing up the character string to be parsed into tokens and then parsing the resulting sequence of tokens. Whitespace can be freely used between tokens. The tokenization process is described in[6.2.9 Lexical Structure].
6.1 Location Paths
Every location path can be expressed using a straightforward but rather verbose syntax. There are also a number of syntactic abbreviations that allow common cases to be expressed concisely. This section will explain the semantics of location paths using the unabbreviated syntax. The abbreviated syntax will then be explained by showing how it expands into the unabbreviated syntax (see [6.1.4 Abbreviated Syntax]).
Here are some examples of location paths using the unabbreviated syntax:
from-children(para)
selects thepara
element children of the context nodefrom-children(*)
selects all element children of the context nodefrom-children(text())
selects all text node children of the context nodefrom-children(node())
selects all the children of the context node, whatever their node typefrom-attributes(name)
selects thename
attribute of the context nodefrom-attributes(*)
selects all the attributes of the context nodefrom-descendants(para)
selects thepara
element descendants of the context nodefrom-ancestors(div)
selects alldiv
ancestors of the context nodefrom-ancestors-or-self(div)
selects thediv
ancestors of the context node and, if the context node is adiv
element, the context node as wellfrom-descendants-or-self(para)
selects thepara
element descendants of the context node and, if the context node is apara
element, the context node as wellfrom-self(para)
selects the context node if it is apara
element, and otherwise selects nothingfrom-children(chapter)/from-descendants(para)
selects thepara
element descendants of thechapter
element children of the context nodefrom-children(*)/from-children(para)
selects allpara
grandchildren of the context node/
selects the document root (which is always the parent of the document element)/from-descendants(para)
selects all thepara
elements in the same document as the context node/from-descendants(olist)/from-children(item)
selects all theitem
elements in the same document as the context node that have anolist
parentfrom-children(para[position()=1])
selects the firstpara
child of the context nodefrom-children(para[position()=last()])
selects the lastpara
child of the context nodefrom-children(para[position()=last()-1])
selects the last but onepara
child of the context nodefrom-children(para[position()>1])
selects all thepara
children of the context node other than the firstpara
child of the context nodefrom-following-siblings(chapter[position()=1])
selects the nextchapter
sibling of the context nodefrom-preceding-siblings(chapter[position()=1])
selects the previouschapter
sibling of the context node/from-descendants(figure[position()=42])
selects the forty-secondfigure
element in the document/from-children(doc)/from-children(chapter[position()=5])/from-children(section[position()=2])
selects the secondsection
of the fifthchapter
of thedoc
document elementfrom-children(para[from-attributes(type)="warning"])
selects allpara
children of the context node that have atype
attribute with valuewarning
from-children(para[from-attributes(type)="warning"][position()=5])
selects the fifthpara
child of the context node that has atype
attribute with valuewarning
from-children(para[position()=5][from-attributes(type)="warning"])
selects the fifthpara
child of the context node if that child has atype
attribute with valuewarning
from-children(chapter[from-children(title)="Introduction"])
selects thechapter
children of the context node whose firsttitle
child has value equal toIntroduction
from-children(chapter[from-children(title)])
selects thechapter
children of the context node that have one or moretitle
childrenfrom-children(chapter[from-children(title[from-self(*)="Introduction"])])
selects thechapter
children of the context node any of whosetitle
children has value equal toIntroduction
from-children(*[from-self(chapter) or from-self(appendix)])
selects thechapter
andappendix
children of the context nodefrom-children(*[from-self(chapter) or from-self(appendix)][position()=last()])
selects the lastchapter
orappendix
child of the context node
There are two kinds of location path: relative location paths and absolute location paths.
A relative location path consists of a sequence of one or more location steps separated by /
. The steps in a relative location path are composed together from left to right. Each step in turn selects a set of nodes relative to a context node. An initial sequence of steps is composed together with a following step as follows. The initial sequence of steps selects a set of nodes relative to a context node. Each node in that set is used as a context node for the following step. The sets of nodes identified by the second step are unioned together. The set of nodes identified by the composition of the steps is this union. For example,from-children(div)/from-children(para)
selects thepara
element children of the div
element children of the context node, or, in other words, thepara
element grandchildren that have div
parents.
An absolute location path consists of /
optionally followed by a relative location path. A /
by itself selects the root node of the document containing the context node. If it is followed by a relative location path, then the location path selects the set of nodes that would be selected by the relative location path relative to the root node of the document containing the context node.
A location step consists of
- an axis identifier;
- a node test;
- zero or more predicates.
The axis identifier selects an initial list of nodes relative to the context node. The initial list of nodes is filtered first by the node test; the result of filtering by the node test is then filtered by the first predicate; the result of that is then filtered by the next predicate and so on. The node test selects nodes from the initial list based on the node type and node name. Each predicate selects nodes that satisfy a condition specified by an arbitrary expression. The result of the location step is the set of nodes that are members of the list that results from filtering the initial list by the node test and all the predicates. Note that although a location step selects a_set_ of nodes, an axis selects a list of nodes and the predicates operate on a list of nodes.
The axis identifier is followed by the node test and predicates in parentheses. For example, from-descendants(para)
selects the descendants of the context node that are para
elements:from-descendants
specifies the axis, and para
is a test that is true for elements with name para
. Each predicate is specified as an expression in square brackets.
Location Paths
| [1] | LocationPath | ::= | RelativeLocationPath | | | ----- | -------------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | | | | | | | AbsoluteLocationPath | | | | [2] | AbsoluteLocationPath | ::= | '/' RelativeLocationPath? | | | | | | | AbbreviatedAbsoluteLocationPath | | | | [3] | RelativeLocationPath | ::= | Step | | | | | | | RelativeLocationPath '/' Step | | | | | | | | AbbreviatedRelativeLocationPath | | | | [4] | Step | ::= | AxisIdentifier '(' NodeTest Predicate* ')' | | | | | | | AbbreviatedStep | | |
6.1.1 Axes
An axis identifies a list of nodes based on the kind of tree relationship that the nodes have to the context node. For example, the children of the context node are one axis, the ancestors of the context node are another axis. Note that an axis identifies an ordered list, not a set. The order of nodes in an axis is in the direction away from the context node.
The following axes are defined:
- the
children
axis contains the children of the context node in document order - the
descendants
axis contains the descendants of the context node in document order - the
parent
axis contains the parent of the context node, if there is oneEd. Note: Is the parent of an attribute node the element that the attribute is on?
- the
following-siblings
axis contains the following siblings of the context node in document order - the
preceding-siblings
axis contains the preceding siblings of the context node in reverse document order; the first preceding sibling is first on the axis; the sibling preceding that node is the second on the axis and so on. - the
following
axis contains all nodes in the same document as the context node that are after the context node in document order; the nodes are ordered in document orderIssue (following-axis): Is the
following
axis needed?
Issue (following-start): Should thefollowing
axis include the descendants of the context node? - the
preceding
axis contains all nodes in the same document as the context node that are before the context node in document order; the nodes are ordered in reverse document orderIssue (preceding-axis): Is the
preceding
axis needed? - the
ancestors
axis contains the ancestors of the context node; the nodes are ordered in reverse document order; thus the parent is the first node on the axis, and the parent's parent is the second node on the axis - the
attributes
axis contains the attributes of the context node; the order of nodes on this axis is implementation-defined - the
self
axis contains just the context node itself - the
ancestors-or-self
axis contains the context node and ancestors of the context node in reverse document order; thus the context node is the first node on the axis, and the context node's parent the second - the
descendants-or-self
axis contains the context node and the descendants of the context node in document order; thus the context node is the first node on the axis, and the first child of the context node is the second node on the axis
In an axis identifier the name of the axis is preceded byfrom-
to distinguish it from a function name.
Axes
| [5] | AxisIdentifier | ::= | 'from-ancestors' | | | ----- | -------------- | ----------------------------- | ---------------- | | | | | | | 'from-ancestors-or-self' | | | | | | | | 'from-attributes' | | | | | | | | 'from-children' | | | | | | | | 'from-descendants' | | | | | | | | 'from-descendants-or-self' | | | | | | | | 'from-following' | | | | | | | | 'from-following-siblings' | | | | | | | | 'from-parent' | | | | | | | | 'from-preceding' | | | | | | | | 'from-preceding-siblings' | | | | | | | | 'from-self' | | |
6.1.2 Node Tests
A node test that is a QName tests whether the node is an element or attribute with the specified name. For example,from-attributes(href)
selects the href
attribute of the context node; if the context node has no href
attribute, it will select an empty set of nodes.
A QName in the node test is expanded into a local name and a possibly null URI. This expansion is done using the namespace declarations from the expression context. This is the same way expansion is done for element type names in start and end-tags except that the default namespace declared withxmlns
is not used: if the QName does not have a prefix, then the URI is null (this is the same way attribute names are expanded). The expanded names are then compared for equality. Two expanded names are equal if they have the same local part, and either both have no URI or both have the same URI.
A node test *
is true for any element or attribute node. For example, from-children(*)
will select all element children of the context node, andfrom-attributes(*)
will select all attributes of the context node.
A node test can have the form NCName:*
. In this case the prefix is expanded in the same way as with a QName using the context namespace declarations. The node test will be true for an element or attribute whose expanded name has the URI to which the prefix expands, whatever the local part of the name.
The node test text()
is true for any text node. For example from-children(text())
will select the text node children of the context node. Similarly, the node testcomment()
is true for any comment node, and the node testpi()
is true for any processing instruction. Thepi()
test may have an argument that is Literal; in this case it is true for any processing instruction that has a name equal to the value of the Literal.
A node test node()
is true for any node.
| [6] | NodeTest | ::= | WildcardName | | | ----- | -------- | -------------------------------------- | -------------------------------- | | | | | | | NodeType '(' ')' | | | | | | | | 'pi' '(' Literal ')' | | |
6.1.3 Predicates
A predicate filters a list of nodes to produce a new list of nodes. For each node in the list to be filtered, the PredicateExpr is evaluated with that node as the context node and with the complete list of nodes to be filtered as the context node list; if PredicateExpr evaluates to true for that node, the node is included in the new list; otherwise it is not included.
A PredicateExpr is evaluated by evaluating the Expr and converting the result to a boolean. If the result is a number, the result will be converted to true if the number is equal to the position of the context node in the context node list and will be converted to false otherwise; if the result is not a number, then the result will be converted as if by a call to the boolean()
function. Thus a location pathpara[3]
is equivalent to para[position()=3]
.
Predicates
| [7] | Predicate | ::= | '[' PredicateExpr ']' | | | ----- | ------------- | --- | -------------------------------------------- | | | [8] | PredicateExpr | ::= | Expr | |
6.1.4 Abbreviated Syntax
Here are some examples of location paths using abbreviated syntax:
para
selects thepara
element children of the context node*
selects all element children of the context nodetext()
selects all text node children of the context node@name
selects thename
attribute of the context node@*
selects all the attributes of the context nodepara[1]
selects the firstpara
child of the context nodepara[last()]
selects the lastpara
child of the context node*/para
selects allpara
grandchildren of the context node/doc/chapter[5]/section[2]
selects the secondsection
of the fifthchapter
of thedoc
chapter//para
selects thepara
element descendants of thechapter
element children of the context node//para
selects all thepara
descendants of the document root and thus selects allpara
elements in the same document as the context node//olist/item
selects all theitem
elements in the same document as the context node that have anolist
parent.
selects the context node.//para
selects thepara
element descendants of the context node..
selects the parent of the context node../@lang
selects thelang
attribute of the parent of the context nodepara[@type="warning"]
selects allpara
children of the context node that have atype
attribute with valuewarning
para[@type="warning"][5]
selects the fifthpara
child of the context node that has atype
attribute with valuewarning
para[5][@type="warning"]
selects the fifthpara
child of the context node if that child has atype
attribute with valuewarning
chapter[title="Introduction"]
selects thechapter
children of the context node whose firsttitle
child has value equal toIntroduction
chapter[title]
selects thechapter
children of the context node that have one or moretitle
childrenchapter[title[.="Introduction"]]
selects thechapter
children of the context node any of whosetitle
children has value equal toIntroduction
employee[@secretary and @assistant]
selects all theemployee
children of the context node that have both asecretary
attribute and anassistant
attribute
The most important abbreviation is that when the axis is the children axis, the from-children
and surrounding parentheses can be omitted. In effect the children
axis is the default axis. For example, a location path div/para
is short for from-children(div)/from-children(para)
.
There's also an abbreviation for the attributes axis. Instead of using from-attributes
and parentheses around the node test, the node test can be preceded by @
to indicate the attributes axis. For example, a location pathpara[@type="warning"]
is short forfrom-children(para[from-attributes(type)="warning"])
and so selects para
children with a type
attribute with value equal to warning
.
//
is short for/from-descendants-or-self(node())/
. For example,//para
is short for/from-descendants-or-self(node())/from-children(para)
and so will select any para
element in the document (even apara
element that is a document element will be selected by//para
since the document element node is a child of the root node); div//para
is short fordiv/from-descendants-or-self(node())/from-children(para)
and so will select all para
descendants of div
children.
A location step of .
is short forfrom-self(node())
. This is particularly useful in conjunction with //
. For example, the location path.//para
is short for
from-self(node())/from-descendants-or-self(node())/from-children(para)
and so will select all para
descendant elements of the context node.
Similarly a location step of ..
is short forfrom-parent(node())
. For example, ../title
is short for from-parent(node())/from-children(title)
and so will select the title
children of the parent of the context node.
Abbreviations
| [9] | AbbreviatedAbsoluteLocationPath | ::= | '//' RelativeLocationPath | | | ------ | ------------------------------- | ------- | ---------------------------------------------------------------------- | | | [10] | AbbreviatedRelativeLocationPath | ::= | RelativeLocationPath '//' Step | | | [11] | AbbreviatedStep | ::= | AbbreviatedNodeTestStep | | | | | | | '.' | | | | | | | | '..' | | | | [12] | AbbreviatedNodeTestStep | ::= | '@'? NodeTest Predicate* | |
6.2 Expressions
6.2.1 Basics
A VariableReference evaluates to the value to which the variable name is bound in the set of variable bindings in the context.
Parentheses may be used for grouping.
| [13] | Expr | ::= | OrExpr | | | ------ | ------------ | ----------------------------------------------------- | ---------------------------------------------- | | | [14] | PrimaryExpr | ::= | VariableReference | | | | | | | '(' Expr ')' | | | | | | | | Literal | | | | | | | | Number | | | | | | | | FunctionCall | | | | [15] | FunctionCall | ::= | NodeSetFunctionCall | | | | | | | BooleanFunctionCall | | | | | | | | StringFunctionCall | | | | | | | | NumberFunctionCall | | | | | | | | SystemFunctionCall | | | | | | | | ExtensionFunctionCall | | |
6.2.2 Node-sets
A location path can be used as an expression. The expression returns the set of nodes selected by the path.
The |
operator computes the union of its operands which must be node-sets.
Square brackets are used to filter expressions in the same way that they are used in location paths. It is an error if the expression to be filtered does not evaluate to a node-set. The context node list used for evaluating the expression in square brackets is the node-set to be filtered listed in document order.
The /
operator and //
operators combine an arbitrary expression and a relative location path. It is an error if the expression does not evaluate to a node-set. The /
operator does composition in the same way as when /
is used in a location path. As in location paths, //
is short for /from-descendants-or-self(node())/
.
There are no types of objects that can be converted to node-sets. It is an error if evaluating a NodeSetExpr yields an object that is not a node-set.
The last()
function returns the number of nodes in the context node list. The position()
function returns the position of the context node in the context node list. The first position is 1, and so the last position will be equal tolast()
.
The count()
function returns the number of nodes in the argument node-set.
The id()
and idref()
functions select elements by their unique ID (see [4.2.1 Unique IDs]).id()
converts its argument to a string and returns a node-set containing the element in the same document as the context node with unique ID equal to that string, if there is such an element, and otherwise returns an empty node-set. idref()
requires that its argument be a node-set; for each node in the node-set, the value is split into a whitespace-separated list of tokens; idref()
returns a node-set containing the elements in the same document as the context node that have a unique ID equal to any of the tokens in the value of any of the nodes in the node-set. For example,
id("foo")
selects the element with unique IDfoo
id("foo")/from-children(para[position()=5])
selects the fifthpara
child of the element with unique IDfoo
Ed. Note: No way to get an ID in another document. Can workaround with xsl:for-each. Maybe add optional second argument which gives document.
Issue (id-inverse): Should there be a way to get back from an element to the elements that reference it (eg by IDREF attributes)?
The key()
and keyref()
functions select a set of nodes using the node key function in the expression evaluation context. Both functions have a string as the first argument that specifies the name of the key and have an expression as the second argument. key()
has a second argument that is a string and returns a node-set containing the nodes in the same document as the context node that have a value for the named key equal to this string. keyref()
has a second argument that is a node-set and returns a node-set containing the nodes in the same document as the context node that have a value for the named key equal to the value of any of the nodes in the argument node-set. See [6.4.1 Declaring Keys] for how to declare a key.
The doc()
and docref()
functions allow access to XML documents other than the initial source document. They both rely on the ability to treat a string as a URI reference that is mapped to a node-set; this mapping always takes places relative to a node that can be used to resolve a relative URI into an absolute URI. If the URI reference does not contain a fragment identifier, then it will be mapped to a node-set containing the root node in a tree representing the XML document whose document entity is the resource identified by the URI. If the URI reference contains a fragment identifier, then it will first map the URI to a tree representing the XML document whose document entity is the resource identified by the URI and then use the fragment identifier to select a set of nodes in that tree; the semantics of the fragment identifier is dependant on media type of the result of retrieving the URI. doc()
takes a string argument which it treats as a URI reference which is mapped to a node-set relative to the element in the stylesheet containing the expression. Note that a zero-length URI reference is a reference to the document relative to which the URI reference is being resolved; thus doc("")
refers to the root node of the stylesheet; the tree representation of the stylesheet is exactly the same as if the XML document containing the stylesheet was the initial source document. docref()
takes a node-set argument; for each node in the node-set, docref()
treats the value of the node as a URI reference that is mapped to a node-set relative to that same node; docref()
returns the union of the resulting node-sets.
Ed. Note: What if the fragment identifier identifies something that isn't a set of nodes (eg a span or a substring within a text node)? What are the allowed media types for the returned data? What is document order for node sets including nodes from multiple documents?
The local-part()
function returns a string containing the local part of the name of the first node in the argument node-set. If the node-set is empty or the first node has no name, an empty string is returned. If the argument is omitted it defaults to the context node.
The namespace()
function returns a string containing namespace of the name of the first node in the argument node-set. If the node-set is empty or the first node has no name or the name has no namespace, an empty string is returned. If the argument is omitted it defaults to the context node.
The qname()
function returns a string containing aQName representing the name of the first node in the argument. The QName must represent the name with respect to the namespace declarations in effect on the node whose name is being represented. Typically this will be the form in which the name occurred in the XML source. This need not be the case if there are namespace declarations in effect on the node that associate multiple prefixes with the same namespace. However, an implementation may include information about the original prefix in its representation of nodes; in this case an implementation can ensure that the returned string is always the same as the QName used in the XML source. If the argument it omitted it defaults to the context node.
The generate-id()
function returns a string that can be used as a unique identifier for the first node in the argument node-set. The unique identifier must consist of ASCII alphanumeric characters and must start with an alphabetic character. An implementation is free to generate an identifier in any convenient way provided that it always generates the same identifier for the same node and that different identifiers are always generated from different nodes. An implementation is under no obligation to generate the same identifiers each time a a document is transformed. If the argument node-set is empty, the empty string is returned. If the argument is omitted, it defaults to the context node.
| [16] | NodeSetExpr | ::= | Expr | | | ------ | ------------------- | ------------------------------------------------------------------------------------- | -------------------------------- | | | [17] | UnionExpr | ::= | PathExpr | | | | | | | UnionExpr '|' PathExpr | | | | [18] | PathExpr | ::= | LocationPath | | | | | | | FilterExpr | | | | | | | | FilterExpr '/' RelativeLocationPath | | | | | | | | FilterExpr '//' RelativeLocationPath | | | | [19] | FilterExpr | ::= | PrimaryExpr | | | | | | | FilterExpr Predicate | | | | [20] | NodeSetFunctionCall | ::= | 'last' '(' ')' | | | | | | | 'position' '(' ')' | | | | | | | | 'count' '(' NodeSetExpr ')' | | | | | | | | 'id' '(' StringExpr ')' | | | | | | | | 'idref' '(' NodeSetExpr ')' | | | | | | | | 'key' '(' StringExpr ',' StringExpr ')' | | | | | | | | 'keyref' '(' StringExpr ',' NodeSetExpr ')' | | | | | | | | 'doc' '(' StringExpr ')' | | | | | | | | 'docref' '(' NodeSetExpr ')' | | | | | | | | 'local-part' '(' NodeSetExpr? ')' | | | | | | | | 'namespace' '(' NodeSetExpr? ')' | | | | | | | | 'qname' '(' NodeSetExpr? ')' | | | | | | | | 'generate-id' '(' NodeSetExpr? ')' | | |
6.2.3 Booleans
An object of type boolean can have two values, true and false.
The boolean()
function converts its argument to a boolean as follows:
- a number is true if and only if it is neither positive or negative zero nor NaN
- a node-list is true if and only if it is non-empty
- a result fragment is true if and only if it is non-empty
- a string is true if and only if its length is non-zero
If the argument is omitted, it defaults to the context node.
A BooleanExpr is evaluated by converting the result of evaluating the Expr to a boolean as if by a call to the boolean()
function.
An =
expression is evaluated as follows. If at least one operand is a boolean, then each operand is converted to a boolean as if by applying the boolean()
function and the operands are compared as booleans. Otherwise, if at least one operand is a number, then each operand is converted to a number as if by applying the number()
function and the operands are compared as numbers; positive and negative zero compare equal. Otherwise both operands are converted to strings as if by applying thestring()
function and the operands are compared as strings; two strings are equal if they contain the same sequence of UCS characters.
A <
, >
, <=
or>=
expression is evaluated by first converting each operand to a number as if by a call to the number()
function and then comparing the two numbers.
Issue (node-set-comparision): What should the semantics of comparison operators be when either or both of the operands are node-sets? Should there be an "any" or "all" semantic?
An or
expression is evaluated by evaluating each operand and converting its value to a boolean. The result is true if either value is true and false otherwise.
An and
expression is evaluated by evaluating each operand and converting its value to a boolean. The result is true if both values are true and false otherwise.
The not()
function returns true if its argument is false, and false otherwise.
The true()
function returns true.
The false()
function returns false.
The lang()
function returns true or false depending on whether the language of the context node as specified byxml:lang
attributes is the same as or is a sublanguage of the language specified by the argument string. The language of the context node is determined by the value of the xml:lang
attribute on the context node, or, if the context node has noxml:lang
attribute, by the value of thexml:lang
attribute on the nearest ancestor of the context node that has an xml:lang
attribute. If there is no such attribute, then lang()
returns false. If there is such an attribute, then lang()
returns true if the attribute value is equal to the argument ignoring case, or if there is some suffix starting with -
such that the attribute value is equal to the argument ignoring that suffix of the attribute value and ignoring case. For example, lang("en")
would return true if the context node is any of these five elements:
| [21] | BooleanExpr | ::= | Expr | | | ------ | ------------------- | ----------------------------------------------------------------------------- | -------------------------------------------- | | | [22] | OrExpr | ::= | AndExpr | | | | | | | OrExpr 'or' AndExpr | | | | [23] | AndExpr | ::= | EqualityExpr | | | | | | | AndExpr 'and' EqualityExpr | | | | [24] | EqualityExpr | ::= | RelationalExpr | | | | | | | EqualityExpr '=' RelationalExpr | | | | [25] | RelationalExpr | ::= | AdditiveExpr | | | | | | | RelationalExpr '<' AdditiveExpr | | | | | | | | RelationalExpr '>' AdditiveExpr | | | | | | | | RelationalExpr '<=' AdditiveExpr | | | | | | | | RelationalExpr '>=' AdditiveExpr | | | | [26] | BooleanFunctionCall | ::= | 'not' '(' BooleanExpr ')' | | | | | | | 'true' '(' ')' | | | | | | | | 'false' '(' ')' | | | | | | | | 'boolean' '(' Expr? ')' | | | | | | | | 'lang' '(' StringExpr ')' | | |
6.2.4 Numbers
A number represents a floating point number. A number can have any double-precision 64-bit format IEEE 754 value. These include a special "Not-a-Number" (NaN) value, positive and negative infinity, and positive and negative zero.
A NumberExpr is evaluated by converting the result of evaluating the Expr to a number as if by a call to the number()
function.
The number()
function converts its argument to a number as follows:
- if a string parses as Number possibly preceded or followed by whitespace, then it is converted to that number; otherwise it is converted to the number 0
Ed. Note: Would NaN be better than 0 here?
- boolean true is converted to 1; boolean false is converted to 0
- a node-set is first converted to a string as if by a call to the
string()
function and then converted in the same way as a string argumentEd. Note: Should we take advantage of xml:lang here?
- a result tree fragment is first converted to a string as if by a call to the
string()
function and then converted in the same way as a string argument
If the argument is omitted, it defaults to the context node.
The div
operator performs floating point division according to IEEE 754.
The quo
operator performs a floating point division and then truncates the result to an integer. For example,
5 quo 2
returns2
5 quo -2
returns-2
-5 quo 2
returns-2
-5 quo -2
returns2
The mod
operator returns the remainder from thequo
operation. For example,
5 mod 2
returns1
5 mod -2
returns1
-5 mod 2
returns-1
-5 mod -2
returns-1
NOTE: This is the same as the
%
operator in Java and ECMAScript.
NOTE: This is not the same as the IEEE remainder operation which returns the remainder from a rounding division.
The sum()
function returns the sum of the values of the nodes in the argument node-set.
The floor()
function returns the largest (closest to positive infinity) number that is not greater than the argument and that is an integer.
The ceiling()
function returns the smallest (closest to negative infinity) number that is not less than the argument and that is an integer.
The round()
function returns the number that is closest to the argument and that is an integer. If there are two such numbers, then the one that is even is returned.
Numeric Expressions
| [27] | AdditiveExpr | ::= | MultiplicativeExpr | | | ------ | ------------------ | ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | | | | | | | AdditiveExpr '+' MultiplicativeExpr | | | | | | | | AdditiveExpr '-' MultiplicativeExpr | | | | [28] | MultiplicativeExpr | ::= | UnaryExpr | | | | | | | MultiplicativeExpr MultiplyOperator UnaryExpr | | | | | | | | MultiplicativeExpr 'div' UnaryExpr | | | | | | | | MultiplicativeExpr 'mod' UnaryExpr | | | | | | | | MultiplicativeExpr 'quo' UnaryExpr | | | | [29] | UnaryExpr | ::= | UnionExpr | | | | | | | '-' UnaryExpr | | | | [30] | NumberExpr | ::= | Expr | | | [31] | NumberFunctionCall | ::= | 'number' '(' Expr? ')' | | | | | | | 'floor' '(' NumberExpr ')' | | | | | | | | 'ceiling' '(' NumberExpr ')' | | | | | | | | 'round' '(' NumberExpr ')' | | | | | | | | 'sum' '(' NodeSetExpr ')' | | |
6.2.5 Strings
A string consists of a sequence of UCS characters.
A StringExpr is evaluated by converting the result of evaluating the Expr to a string as if by a call to the string()
function.
The string()
function converts an object to a string as follows:
- A node-set is converted to a string by returning the value of the node in the node-set that is first in document order. If the node-set is empty, an empty string is returned.
- A result tree fragment is converted to a string by treating it as a single document fragment node that contains the nodes of the fragment, and then converting that document fragment node to a string in the same was as if the document fragment node were a source tree node.
- A number is converted to a string by returning a string in the form of a Number, preceded by a
-
character if the number is negative.Ed. Note: What about positive zero, negative zero, NaN and infinities?
- The boolean false value is converted to the string
false
. The boolean true value is converted to the stringtrue
.
If the argument is omitted, it defaults to the context node.
The concat()
function returns the concatenation of its arguments.
The starts-with()
function returns true if the first argument string starts with the second argument string, and otherwise returns false.
The contains()
function returns true if the first argument string contains the second argument string, and otherwise returns false.
The substring-before()
function returns the substring of the first argument string that precedes the first occurrence of the second argument string in the first argument string, or the empty string if the first argument string does not contain the second argument string. For example,substring-before("1999/04/01","/")
returns1999
.
The substring-after()
function returns the substring of the first argument string that follows the first occurrence of the second argument string in the first argument string, or the empty string if the first argument string does not contain the second argument string. For example,substring-after("1999/04/01","/")
returns04/01
.
Ed. Note: Should the first argument of the above functions default to the value of the current node?
The normalize()
function returns the argument string with white space normalized by stripping leading and trailing whitespace and replacing sequences of whitespace characters by a single space. Whitespace characters are the same allowed by the S production in XML. If the argument is omitted, it defaults to the context node converted to a string, in other words the value of the context node.
The translate()
function returns the first argument string with occurrences of characters in the second argument string replaced by the corresponding characters from the third argument string. For example, translate("bar","abc","ABC")
returns the string BAr
.
The format-number()
function converts its first argument to a string using the format pattern string specified by the second argument and the locale named by the third argument, or the default locale, if there is no third argument. The format pattern string is in the syntax specified by the JDK 1.1 DecimalFormat class. The format pattern string is in a localized notation: the locale determines what characters have a special meaning in the pattern (with the exception of the quote character, which is not localized). The format pattern must not contain the currency sign (#x00A4); support for this feature was added after the initial release of JDK 1.1. See [6.4.3 Declaring Locales]for how to declare a locale.
| [32] | StringExpr | ::= | Expr | | | ------ | -------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | | | [33] | StringFunction | ::= | 'string' '(' Expr? ')' | | | | | | | 'starts-with' '(' StringExpr ',' StringExpr ')' | | | | | | | | 'contains' '(' StringExpr ',' StringExpr ')' | | | | | | | | 'substring-before '(' StringExpr ',' StringExpr ')' | | | | | | | | 'substring-after '(' StringExpr ',' StringExpr ')' | | | | | | | | 'normalize' '(' StringExpr? ')' | | | | | | | | 'translate' '(' StringExpr ',' StringExpr ',' StringExpr ')' | | | | | | | | 'concat' '(' StringExpr (',' StringExpr)+ ')' | | | | | | | | 'format-number' '(' NumberExpr ',' StringExpr (',' StringExpr)? ')' | | |
Issue (regex): Should XSLT support regular expressions for matching against any or all of pcdata content, attribute values, attribute names, element type names?
Issue (equality-case): Do we need to be able to do comparisons in a case insensitive way?
Issue (equality-normalize): Do we need to normalize strings before comparison? Does the stylesheet need to specify what kinds of normalization are required (eg compatibility character normalization)?
Issue (resolve-expr): Do we need a
resolve(NodeSetExpr)
string expression that treats the characters as a relative URI and turns it into an absolute URI using the base URI of the addressed node?
6.2.6 Result Tree Fragments
Ed. Note: Add explanation of what a result tree fragment is.
The only operations that can be performed on a result tree fragment are to convert it to a string or a boolean. In particular, it is not permitted to use the /
, //
, and[]
on result tree fragments.
Expressions can only return values of type result tree fragment by referencing variables of type result tree fragment or calling extension functions that return a result tree fragment.
6.2.7 Extension Functions
| [34] | ExtensionFunctionCall | ::= | CName '(' ( Expr ( ',' Expr)*)? ')' | | | ------ | --------------------- | --- | ------------------------------------------------------------------------- | |
The CName is expanded to a name using the namespace declarations from the evaluation context. The XSLT processor attempts to locate an implementation of the extension function with the specified name that it can use. The implementation may be provided by an xsl:functions
element (see [6.4.2 Declaring Extension Functions]) or the XSLT processor may be able to locate an implementation by other means not specified by XSLT. If the XSLT processor cannot locate such a function, then evaluating the expression is an error. Otherwise the implementation is called passing it the values of the expressions and the value returned by the function is the value of the expression. Thefunction-available()
function can be used to test whether an implementation of a particular function is available (see [6.2.8 System Functions]). A XSLT processor is allowed always to give an error when evaluating an ExtensionFunctionCall (with such an XSLT processor the function-available()
function would always return false). Therefore if an XSLT stylesheet includes an ExtensionFunctionCall and does not use the function-available()
function to test for and handle the possibility that an implementation of the function is not available, then it may not be portable across all XSLT implementations.
6.2.8 System Functions
| [35] | SystemFunctionCall | ::= | 'system-property' '(' StringExpr ')' | | | ------ | ------------------ | ------------------------------------------------------------ | ------------------------------------------------------ | | | | | | | 'function-available' '(' StringExpr ')' | | |
For both these functions, the StringExpr must evaluate to a string that is a QName. The QName is expanded into a name using the namespace declarations in scope for the expression.
The system-property()
function returns an object representing the value of the system property identified by the name. If the name has no namespace, then the system-property()
function must return the string value of the operating system environment variable whose name is equal to the local part of the name. If there is no such system property, the empty string should be returned.
Implementations must provide the following system properties which are all in the XSLT namespace:
xsl:version
, a number giving the version of XSLT implemented by the processor
The function-available()
function returns true if an implementation of the named extension function is available. For example:
<xsl:if test="function-available('jjc:currentDate')"> <xsl:value-of select="jjc:currentDate()"/>
6.2.9 Lexical Structure
When tokenizing, the longest possible token is always returned.
For readability, whitespace may be used in patterns even though not explicitly allowed by the grammar: ExprWhitespace may be freely added within patterns before or after any ExprToken.
A NodeType, FunctionName, CNameor AxisIdentifier token is recognized only when the following token is (
. An OperatorName token or MultiplyOperator token is recognized as such only when there is a preceding token and the preceding token is not one of @
, (
, [
,,
or an Operator.
Expression Lexical Structure
| [36] | ExprToken | ::= | '(' | ')' | '[' | ']' | '.' | '..' | '@' | ',' | | | | ------ | ----------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ----- | ----- | ---- | --------- | --- | ---- | | | | | | | WildcardName | | | | | | | | | | | | | | | NodeType | | | | | | | | | | | | | | | Operator | | | | | | | | | | | | | | | FunctionName | | | | | | | | | | | | | | | AxisIdentifier | | | | | | | | | | | | | | | Literal | | | | | | | | | | | | | | | Number | | | | | | | | | | | | | | | CName | | | | | | | | | | | | | | | VariableReference | | | | | | | | | | | [37] | Literal | ::= | '"' [^"]* '"' | | | | | | | | | | | | | | "'" [^']* "'" | | | | | | | | | | | [38] | Number | ::= | [0-9]+ ('.' [0-9]+)? | | | | | | | | | | | | | | '.' [0-9]+ | | | | | | | | | | | [39] | Operator | ::= | OperatorName | | | | | | | | | | | | | | MultiplyOperator | | | | | | | | | | | | | | | '/' | '//' | '|' | '+' | '-' | '=' | '<'| '<=' | '>' | '>=' | | | [40] | OperatorName | ::= | 'and' | 'or' | 'mod' | 'div' | 'quo' | | | | | | | [41] | MultiplyOperator | ::= | '*' | | | | | | | | | | [42] | FunctionName | ::= | 'boolean' | | | | | | | | | | | | | | 'ceiling' | | | | | | | | | | | | | | | 'concat' | | | | | | | | | | | | | | | 'contains' | | | | | | | | | | | | | | | 'count' | | | | | | | | | | | | | | | 'doc' | | | | | | | | | | | | | | | 'docref' | | | | | | | | | | | | | | | 'false' | | | | | | | | | | | | | | | 'floor' | | | | | | | | | | | | | | | 'format-number' | | | | | | | | | | | | | | | 'function-available' | | | | | | | | | | | | | | | 'generate-id' | | | | | | | | | | | | | | | 'id' | | | | | | | | | | | | | | | 'idref' | | | | | | | | | | | | | | | 'key' | | | | | | | | | | | | | | | 'keyref' | | | | | | | | | | | | | | | 'lang' | | | | | | | | | | | | | | | 'last' | | | | | | | | | | | | | | | 'local-part' | | | | | | | | | | | | | | | 'namespace' | | | | | | | | | | | | | | | 'normalize' | | | | | | | | | | | | | | | 'not' | | | | | | | | | | | | | | | 'number' | | | | | | | | | | | | | | | 'position' | | | | | | | | | | | | | | | 'qname' | | | | | | | | | | | | | | | 'round' | | | | | | | | | | | | | | | 'starts-with' | | | | | | | | | | | | | | | 'string' | | | | | | | | | | | | | | | 'substring-after' | | | | | | | | | | | | | | | 'substring-before' | | | | | | | | | | | | | | | 'sum' | | | | | | | | | | | | | | | 'system-property' | | | | | | | | | | | | | | | 'translate' | | | | | | | | | | | | | | | 'true' | | | | | | | | | | | [43] | CName | ::= | NCName ':' NCName | | | | | | | | | | [44] | VariableReference | ::= | '$' NCName | | | | | | | | | | [45] | WildcardName | ::= | '*' | | | | | | | | | | | | | | NCName ':' '*' | | | | | | | | | | | | | | | QName | | | | | | | | | | | [46] | NodeType | ::= | 'comment' | | | | | | | | | | | | | | 'text' | | | | | | | | | | | | | | | 'pi' | | | | | | | | | | | | | | | 'node' | | | | | | | | | | | [47] | ExprWhitespace | ::= | S | | | | | | | | |
6.3 Patterns
This section explains what expressions are allowed as patterns and what the semantics of matching a pattern are.
Here are some examples of patterns:
para
matches anypara
element*
matches any elementchapter|appendix
matches anychapter
element and anyappendix
elementolist/item
matches anyitem
element with anolist
parentappendix//para
matches anypara
element with anappendix
ancestor element/
matches the root nodetext()
matches any text nodepi()
matches any processing instructionid("W11")
matches the element with unique IDW11
para[1]
matches anypara
element that is the firstpara
child element of its parent*[position()=1 and from-self(para)]
matches anypara
element that is the first child element of its parentpara[last()=1]
matches anypara
element that is the only child element of its parentitems/item[position()>1]
matches anyitem
element that has aitems
parent and that is not the firstitem
child of its parentitem[position() mod 2 = 1]
would be true for anyitem
element that is an odd-numbereditem
child of its parent.div[@class="appendix"]//p
matches anyp
element with adiv
ancestor element that has aclass
attribute with valueappendix
@class
matches anyclass
attribute (not any element that has aclass
attribute)@*
matches any attribute
A pattern must match the grammar for Pattern. A Pattern is set of location path patterns separated by |
. A location path pattern is a location path none of the steps of which use eitherAxisIdentifiers or .
or..
. Location path patterns can also start with anid()
or key()
function call with a literal argument (see [6.2.2 Node-sets]). Predicates in a pattern can use arbitrary expressions just like predicates in a location path.
Patterns
| [48] | Pattern | ::= | LocationPathPattern | | | ------ | ------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------ | | | | | | | Pattern '|' LocationPathPattern | | | | [49] | LocationPathPattern | ::= | '/' RelativePathPattern? | | | | | | | IdKeyPattern (('/' | '//') RelativePathPattern)? | | | | | | | '//'? RelativePathPattern | | | | [50] | IdKeyPattern | ::= | 'id' '(' Literal ')' | | | | | | | 'key' '(' Literal ',' Literal ')' | | | | [51] | RelativePathPattern | ::= | StepPattern | | | | | | | RelativePathPattern '/' StepPattern | | | | | | | | RelativePathPattern '//' StepPattern | | | | [52] | StepPattern | ::= | AbbreviatedNodeTestStep | |
A pattern is defined to match a node if and only if there is possible context such that when the pattern is evaluated as an expression with that context, the node is a member of the resulting node-set. When a node is being matched the possible contexts have a context node that is the node being matched or any ancestor of that node, and a context node list containing just the context node.
For example, p
matches any p
element, because for any p
if the expression p
is evaluated with the parent of the p
element as context the resulting node-set will contain that p
element as one of its members.
NOTE: This matches even a
p
element that is the document element, since the document root is the parent of the document element.
Although the semantics of patterns are specified indirectly in terms of expression evaluation, it is easy to understand the meaning of a pattern directly without thinking in terms of expression evaluation. In a pattern, |
indicates alternatives; a pattern with one or more |
separated alternatives matches if any one of the alternative matches. A pattern that consists of a sequence of StepPatterns separated by/
or //
is matched from right to left. The pattern only matches if the rightmost StepPattern matches and a suitable element matches the rest of the pattern; if the separator is /
then only the parent is a suitable element; if the separator is//
, then any ancestor is a suitable element. A StepPattern that's a NodeTest matches if the NodeTest is true for the node and the node is not an attribute node. A StepPatternthat starts with @
matches if the node is an attribute node and the WildcardName matches the name of the attribute. When []
is present, then the first PredicateExpr in a StepPattern is evaluated with the element being matched as the context node and the siblings of the elements that match the NodeTest as the context node list, unless the node being matched is an attribute node, in which case the context node list is all the attributes that have the same parent as the attribute being matched and that match the WildcardName.
For example
appendix//ulist/item[position()=1]
matches a node if and only if all of the following are true:
- the NodeTest
item
is true for the node and the node is not an attribute; in other words the node is anitem
element - evaluating the PredicateExpr
position()=1
with the node as context node and the siblings of the node that areitem
elements as the context node list yields true - the node has a parent that matches
appendix//ulist
; this will be true if the parent is aulist
element that has anappendix
ancestor element.
Ed. Note: Need to revise above paragraph if we decide not to call the element to which an attribute is attached the parent of the attribute.
6.4 Declarations
6.4.1 Declaring Keys
The xsl:key
element is used to declare keys. Thename
specifies the name of the key. Thematch
attribute is a Pattern; axsl:key
element gives information about the keys of any node that match the pattern specified in the match attribute. Theuse
attribute is a NodeSetExpr, which specifies the set of values for which the node has a key of the specified name. A node_x_ has a key with name y and value_z_ if and only if there is a xsl:key
element such that:
- x matches the pattern specified in the
match
attribute of thexsl:key
element; - the value of the
name
attribute of thexsl:key
element is equal to y; and - z is the value of one or more of the nodes in the node-set that results from evaluating the NodeSetExpr specified in the
use
attribute of thexsl:key
element with_x_ as the current node and with a node list containing just x as the current node list.
Note that the NodeSetExpr may return a node-set with more than one node; all of the returned nodes serve as a key value. Note also that there may be more than onexsl:key
element that matches a given node; all of the matching xsl:key
elements are used.
Ed. Note: Add some examples.
6.4.2 Declaring Extension Functions
Implementations of the extension functions in a namespace can be provided using the xsl:functions
element. The requiredns
attribute specifies the namespace for which an implementation is being provided. The value of the ns
attribute is a namespace prefix which is expanded to a namespace URI using the namespace declarations in effect on thexsl:functions
element.
The implementation may be provided in two ways. If thecode
attribute is present, then its value is a URI that identifies a resource containing an implementation of the functions in the namespace; in this case a type
attribute giving the MIME media type of the data providing the implementation may also be provided, so as to allow the XSLT processor to avoid fetching resources of types that it is unable to make use of. If thecode
attribute is not present, then the content of thexsl:functions
element contains the implementation of the functions; in this case the type
attribute_must_ be present.
Multiple alternative implementations may be provided for the same namespace. For example,
<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0" xmlns:jjc="" title="undefined" rel="noopener noreferrer">http://www.jclark.com">
<xsl:template match="/"> <xsl:value-of select="jjc:currentDate()"/>
<xsl:functions ns="jjc" type="text/javascript">
function currentDate() { return Date().toString() }
When multiple alternative implementations are provided, it is up to the XSLT processor to determine which to use.
<xsl:functions ns="jjc" code="clsid:9A447990-E64D-11D2-8C29-00A0CC2428DA"/>
The xsl:functions
element may also have anarchive
attribute that specifies a whitespace-separated list of URIs of resources relevant to the provided implementation.
An XSLT processor is not required to be able to make use of implementations provided by xsl:functions
elements. The MIME media types that an XSLT processor is able to make use of and the way the XSLT processor interfaces with implementations is dependent on the particular XSLT processor. Therefore if an XSLT stylesheet includes an ExtensionFunctionCall of an extension function in a namespace for which an implementation is provided by an xsl:functions
element, then it may not be portable across all XSLT implementations.
6.4.3 Declaring Locales
The xsl:locale
element declares a locale which controls the interpretation of a format pattern used by theformat-number()
function. If there is aname
attribute then the element declares a named locale, otherwise it declares the default locale.
The other attributes on xsl:locale
correspond to the methods on the JDK 1.1 DecimalFormatSymbols class. For eachget
/set
method pair there is an attribute defined for the xsl:locale
element. The default values are given in the XSLT DTD (see [A DTD Fragment for XSLT Stylesheets]).
The following attributes specify characters that may appear in the result of formatting the number and also control the interpretation of characters in the format pattern:
decimal-separator
specifies the character used for the decimal signgrouping-separator
specifies the character used as a grouping (eg thousands) separatorpercent
specifies the character used as a percent signper-mill
specifies the character used as a per mille signzero-digit
specifies the character used as the digit zero
The following attributes control the interpretation of characters in the format pattern:
digit
specifies the character used for a digit in the format patternpattern-separator
specifies the character used to separate positive and negative subpatterns in a pattern
The following attributes specify strings that may appear in the result of formatting the number:
infinity
specifies the string used to represent infinityNaN
specifies the string used to represent the NaN valueminus-sign
specifies the string used as the default minus sign
7. Template Rules
7.1 Processing Model
A list of source nodes is processed to create a result tree fragment. The result tree is constructed by processing a list containing just the root node. A list of source nodes is processed by appending the result tree structure created by processing each of the members of the list in order. A node is processed by finding all the template rules with patterns that match the node, and choosing the best amongst them. The chosen rule's template is then instantiated for the node. During the instantiation of a template, the node for which the template is being instantiated is called the current node; the list of source nodes that is being processed is called the current node list. The current node is always a member of the current node list. A template typically contains instructions that select an additional list of source nodes for processing. The process of matching, instantiation and selection is continued recursively until no new source nodes are selected for processing.
Implementations are free to process the source document in any way that produces the same result as if it were processed using this processing model.
7.2 Defining Template Rules
A template rule is specified with the xsl:template
element. The match
attribute is a Pattern that identifies the source node or nodes to which the rule applies. The match
attribute is required unless the xsl:template
element has aname
attribute (see [8 Named Templates]). The content of the xsl:template
element is the template.
Issue (template-match-default): Should the
match
attribute have a default? Any node? Any child node? The root node?
For example, an XML document might contain:
This is an important point.
The following template rule matches emph
elements and has a template which produces a fo:inline-sequence
formatting object with a font-weight
property ofbold
.
<xsl:template match="emph"> <fo:inline-sequence font-weight="bold"> xsl:apply-templates/
As described later, the xsl:apply-templates
element recursively processes the children of the source element.
7.3 Applying Template Rules
This example creates a block for a chapter
element and then processes its immediate children.
<xsl:template match="chapter"> fo:block xsl:apply-templates/
In the absence of a select
attribute, thexsl:apply-templates
instruction processes all of the children of the current node, including text nodes. However, text nodes that have been stripped as specified in [4.8 Whitespace Stripping]will not be processed.
Ed. Note: There is no WG consensus on the use of xsl:apply-templates without a select attribute to process all children of a node.
A select
attribute can be used to process nodes selected by an expression instead of all children. The value of theselect
attribute is a NodeSetExpr. The selected set of nodes are processed in document order, unless a sorting specification is present (see[12 Sorting]). The following example processes all of theauthor
children of the author-group
:
<xsl:template match="author-group"> fo:inline-sequence <xsl:apply-templates select="author"/>
The following example processes all of the first-name
s of the author
s that are children ofauthor-group
:
<xsl:template match="author-group"> fo:inline-sequence <xsl:apply-templates select="author/first-name"/>
This example processes all of the heading
elements contained in the book
element.
<xsl:template match="book"> fo:block <xsl:apply-templates select=".//heading"/>
It is also possible to process elements that are not descendants of the current node. This example assumes that a department
element contains group
and employee
elements (at some level). It finds an employee's department and then processes the group
children of the department
.
<xsl:template match="employee"> fo:block Employee <xsl:apply-templates select="name"/> belongs to group <xsl:apply-templates select="from-ancestors(department)/group"/>
Multiple xsl:apply-templates
elements can be used within a single template to do simple reordering. The following example creates two HTML tables. The first table is filled with domestic sales while the second table is filled with foreign sales.
<xsl:template match="product">
NOTE: It is possible for there to be two matching descendants where one is a descendant of the other. This case is not treated specially: both descendants will be processed as usual. For example, given a source document
the rule
<xsl:template match="doc"> <xsl:apply-templates select=".//div"/>
will process both the outer
div
and innerdiv
elements.
Use of expressions in xsl:apply-templates
can lead to infinite loops. It is an error if, during the invocation of a rule for a node, that same rule is invoked again for that node. An XSLT processor may signal the error; if it does not signal the error, it must recover by creating an empty result tree structure for the nested invocation.
Ed. Note: This isn't right with parameters.
Ed. Note: Also doesn't apply to built-in rules because they can be invoked in multiple modes.
7.4 Conflict Resolution for Template Rules
It is possible for a source node to match more than one template rule. The template rule to be used is determined as follows:
- First, all matching template rules that are lessimportant than the most important matching template rule or rules are eliminated from consideration.
- Next, all matching template rules that have a lower priority than the matching template rule or rules with the highest priority are eliminated from consideration. The priority of a template rule is specified by the
priority
attribute on the template rule. The value of this must be a real number (positive or negative). The default priority is computed as follows:- If the pattern contains multiple alternatives separated by
|
, then it is treated equivalently to a set of template rules one for each alternative. - If the pattern has the form of a QName optionally preceded by an
@
character, then the priority is 0. - Otherwise if the pattern consists of just a NodeTest, then the priority is -1.
- Otherwise the priority is 1.
The idea is that the most common kind of pattern (a pattern that just tests for an element with a specific name) has priority 0; a pattern more specific than this has priority 1; a pattern less specific than this has priority -1.Ed. Note: Say exactly what syntax is allowed for real numbers.
- If the pattern contains multiple alternatives separated by
It is an error if this leaves more than one matching template rule. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing, from amongst the matching template rules that are left, the one that occurs last in the stylesheet.
7.5 Built-in Template Rules
There is a built-in template rule to allow recursive processing to continue in the absence of a successful pattern match by an explicit rule in the stylesheet. This rule applies to both element nodes and the root node. The following shows the equivalent of the built-in template rule:
<xsl:template match="*|/"> xsl:apply-templates/
There is also a built-in template rule for text nodes that copies text through:
<xsl:template match="text()"> <xsl:value-of select="."/>
The built-in rule does not apply to processing instructions and comments. When a comment or processing instruction is processed, and no rule is matched, nothing is created.
The built-in template rules are treated as if they were imported implicitly before the stylesheet and so are considered less important than all other template rules. Thus the author can override a built-in rule by including an explicit rule with match="*|/"
ormatch="text()"
.
7.6 Modes
Modes allow an element to be processed multiple times, each time producing a different result.
Both xsl:template
and xsl:apply-templates
have an optional mode
attribute whose value is a name. If xsl:template
does not have a match
attribute it must not have a mode
attribute. If anxsl:apply-templates
element has a mode
attribute, then it applies only to those template rules fromxsl:template
elements that have a mode
attribute with the same value; if an xsl:apply-templates
element does not have a mode
attribute, then it applies only to those template rules from xsl:template
elements that do not have a mode
attribute.
If there is no matching template, then the built-in template rules are applied, even if a mode
attribute was specified inxsl:apply-templates
.
Ed. Note: Add some examples.
8. Named Templates
Templates can be invoked by name. An xsl:template
element with a name
attribute specifies a named template. If a xsl:template
element has a name
attribute, it may, but need not, also have a match
attribute. An xsl:call-template
element invokes a template by name; it has a required name
attribute that identifies the template to be invoked. Unlikexsl:apply-templates
, xsl:call-template
does not change the current node or the current node list.
Ed. Note: Expand this.
It is an error if a stylesheet contains more than one template with the same name and same importance. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing from amongst the templates with highest importance the one that occurs last in the stylesheet.
9. Creating the Result Tree
This section describes instructions that directly create nodes in the result tree.
Issue (multiple-results): Should it be possible to create multiple result trees?
9.1 Creating Elements and Attributes
9.1.1 Literal Result Elements
In a template an element in the stylesheet that does not belong to the XSLT namespace is instantiated to create an element node of the same type. The created element node will have the attribute nodes that were present on the element node in the stylesheet tree. The created element node will also have the namespace nodes that were present on the element node in the stylesheet tree with the exception of any namespace node whose value is the XSLT namespace URI (http://www.w3.org/XSL/Transform/1.0
).
The value of an attribute of a literal result element is interpreted as an attribute value template: it can contain string expressions contained in curly braces ({}
).
Namespace URIs that occur literally in the stylesheet and that are being used to create nodes in the result tree can be quoted. This applies to:
- the namespace URI in the expanded name of a literal result element in the stylesheet
- the namespace URI in the expanded name of an attribute specified on a literal result element in the stylesheet
- the value of a namespace node on a literal result element in the stylesheet
A namespace URI is quoted by prefixing it with the stringquote:
. This prefix will be removed when the template is instantiated to create the result element node with its associated attribute nodes and namespace nodes.
When literal result elements are being used to create element, attribute, or namespace nodes that use the XSLT namespace URI, the namespace must be quoted to avoid misinterpretation by the XSLT processor.
NOTE: It may be necessary also to quote other namespaces. For example, literal result elements belonging to a namespace dealing with digital signatures might cause XSLT stylesheets to be mishandled by general purpose security software; quoting the namespace would avoid the possibility of such mishandling.
For example, the stylesheet
<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0" xmlns:fo="http://www.w3.org/XSL/Format/1.0" xmlns:qxsl="quote:" title="undefined" rel="noopener noreferrer">http://www.w3.org/XSL/Transform/1.0">
<xsl:template match="/"> <qxsl:stylesheet result-ns="fo"> xsl:apply-templates/
<xsl:template match="block"> <qxsl:template match="{.}"> fo:blockqxsl:apply-templates/
will generate an XSLT stylesheet from a document of the form:
p h1 h2 h3 h49.1.2 Creating Elements with xsl:element
The xsl:element
element allows an element to be created with a computed name. The name of the element to be created is specified by a required name
attribute and an optionalnamespace
attribute. The content of thexsl:element
element is a template for the attributes and children of the created element.
The name
attribute is interpreted as an attribute value template; the string value from instantiating it must be a QName. If the namespace
attribute is not present, then the QName is expanded into a name using the namespace declarations in effect for the xsl:element
element, including any default namespace declaration.
Ed. Note: What should happen if the name is not a valid QName?
If the namespace
attribute is present, then it also interpreted as an attribute value template; the string value from instantiating it should be a URI reference. This is used as the namespace of the name of the element to be created. The local part of the QName specified by thename
attribute is used as the local part of the name of the element to be created.
Ed. Note: What should happen if the namespace is not a syntactically legal URI reference? Should URI escaping automatically be done?
XSLT processors may make use of the prefix of the QName specified in thename
attribute when selecting the prefix used for outputting the created element as XML. They are not however required to do so.
9.1.3 Creating Attributes with xsl:attribute
The xsl:attribute
element can be used to add attributes to result elements whether created by literal result elements in the stylesheet or by instructions such asxsl:element
. The name of the attribute to be created is specified by a required name
attribute and an optionalnamespace
attribute. Instantiating anxsl:attribute
element adds an attribute node to the containing result element node. The content of thexsl:attribute
element is a template for the value of the created attribute.
The name
attribute is interpreted as an attribute value template; the string value from instantiating it must be a QName. If the namespace
attribute is not present, then the QName is expanded into a name using the namespace declarations in effect for thexsl:attribute
element, not including any default namespace declaration.
Ed. Note: What should happen if the name is not a valid QName?
If the namespace
attribute is present, then it also interpreted as an attribute value template; the string value from instantiating it should be a URI reference. This is used as the namespace of the name of the attribute to be created. The local part of the QName specified by thename
attribute is used as the local part of the name of the attribute to be created.
Ed. Note: What should happen if the namespace is not a syntactically legal URI reference? Should URI escaping automatically be done?
XSLT processors may make use of the prefix of the QName specified in thename
attribute when selecting the prefix used for outputting the created attribute as XML. They are not however required to do so.
The following are all errors:
- Adding an attribute to an element after children have been added to it; implementations may either signal the error or ignore the attribute.
- Adding an attribute that has the same name as an attribute already added; implementations may either signal the error or ignore the duplicate attribute.
- Adding an attribute to a node that is not an element; implementations may either signal the error or ignore the attribute.
- Creating anything other than characters during the instantiation of the content of the
xsl:attribute
element; implementations may either signal the error or ignore the offending nodes.
9.1.4 Named Attribute Sets
The xsl:attribute-set
element defines a named set of attributes. The name
attribute specifies the name of the attribute set. The xsl:use
element adds a named set of attributes to an element. It has a requiredattribute-set
attribute that specifies the name of the attribute set. xsl:use
is allowed in the same places asxsl:attribute
. The content of thexsl:attribute-set
consists of xsl:attribute
elements that specify attributes; it may also containxsl:use
elements. The value of attributes in an attribute set is determined when the attribute set is used rather than when the attribute set is defined.
The following example creates a named attribute settitle-style
and uses it in a template rule.
<xsl:attribute-set name="title-style"> <xsl:attribute name="font-size">12pt <xsl:attribute name="font-weight">bold
<xsl:template match="chapter/heading"> <fo:block quadding="start"> <xsl:use attribute-set="title-style"/> xsl:apply-templates/
Any attribute in a named attribute set specified byxsl:use
is not added to an element if the element already has an attribute of that name.
Multiple definitions of an attribute set with the same name are merged. An attribute from a definition that is more important takes precedence over an attribute from a definition that is less important. It is an error if there are two attribute sets with the same name that are equally important and that both contain the same attribute unless there is a more important definition of the attribute set that also contains the attribute. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing from amongst the most important definitions that specify the attribute the one that was specified last in the stylesheet.
9.2 Creating Text
A template can also contain text nodes. Each text node in a template remaining after whitespace has been stripped as specified in[4.8 Whitespace Stripping] will create a text node with the same value in the result tree. Adjacent text nodes in the result tree are automatically merged.
Note that text is processed at the tree level. Thus, markup of<
in a template will be represented in the stylesheet tree by a text node that includes the character<
. This will create a text node in the result tree that contains a <
character, which will be represented by the markup <
(or an equivalent character reference) when the result tree is externalized as an XML document.
Literal data characters may also be wrapped in anxsl:text
element. This wrapping may change what whitespace characters are stripped (see [4.8 Whitespace Stripping]) but does not affect how the characters are handled by the XSLT processor thereafter.
9.3 Creating Processing Instructions
The xsl:pi
element is instantiated to create a processing instruction node. The content of the xsl:pi
element is a template for the value of the processing instruction node. The xsl:pi
element has a requiredname
attribute that specifies the name of the processing instruction node. The value of the name attribute is interpreted as an attribute value template.
For example, this
<xsl:pi name="xml-stylesheet">href="book.css" type="text/css"
would create the processing instruction
It is an error if instantiating the content of xsl:pi
creates anything other than characters. An XSLT processor may signal the error; if it does not signal the error, it must recover by ignoring the offending nodes together with their content.
It is an error if the result of instantiating the content of thexsl:pi
contains the string ?>
. An XSLT processor may signal the error; if it does not signal the error, it must recover by inserting a space after any occurrence of?
that is followed by an >
.
Ed. Note: What should happen if the name is not a valid NCName?
9.4 Creating Comments
The xsl:comment
element is instantiated to create a comment node in the result tree. The content of thexsl:comment
element is a template for the value of the comment node.
For example, this
xsl:commentThis file is automatically generated. Do not edit!
would create the comment
It is an error if instantiating the content ofxsl:comment
creates anything other than characters. An XSLT processor may signal the error; if it does not signal the error, it must recover by ignoring the offending nodes together with their content.
It is an error if the result of instantiating the content of thexsl:comment
contains the string --
or ends with -
. An XSLT processor may signal the error; if it does not signal the error, it must recover by inserting a space after any occurrence of -
that is followed by another-
or that ends the comment.
9.5 Copying
The xsl:copy
element provides an easy way of copying the current node. The xsl:copy
element is replaced by a copy of the current node. The namespace nodes of the current node are automatically copied as well, but the attributes and children of the node are not automatically copied. The content of thexsl:copy
element is a template for the attributes and children of the created node; the content is not used for nodes of types that do not have attributes or children (attributes, text, comments and processing instructions).
The root node is treated specially because the root node of the result tree is created implicitly. When the current node is the root node, xsl:copy
will not create a root node, but will just use the content template.
For example, the identity transformation can be written usingxsl:copy
as follows:
<xsl:template match="*|@*|comment()|pi()|text()"> xsl:copy <xsl:apply-templates select="*|@*|comment()|pi()|text()"/>
The xsl:copy-of
element copies a list of nodes specified by an expression. The required select
attribute contains an expression. The result of evaluating the expression must be a node-set or a result tree fragment. When it is node-set, all the nodes in the set together with their content are copied in document order over into the result tree; when it is a result tree fragment; the complete fragment is copied over into the result tree.
When the current node is an attribute, then if it would be an error to use xsl:attribute
to create an attribute with the same name as the current node, then it is also an error to usexsl:copy
(see [9.1.3 Creating Attributes with xsl:attribute]).
9.6 Computing Generated Text
Within a template, the xsl:value-of
element can be used to compute generated text, for example by extracting text from the source tree or by inserting the value of a variable. Thexsl:value-of
element does this with an expression that is specified as the value of the select
attribute. String expressions can also be used inside attribute values of literal result elements by enclosing the string expression in curly brace ({}
).
9.6.1 Generating Text with xsl:value-of
The xsl:value-of
element is replaced by the result of evaluating the expression specified by the select
attribute. The select
attribute is required. The expression is a StringExpr, which means the result of evaluating the expression is converted to a string. The element is called xsl:value-of
because a node-set is converted to a string by returning the value of the first node.
Issue (value-of-select-default): Should the
select
attribute have a default value of.
?
For example, the following creates an HTML paragraph from aperson
element with first-name
andsurname
attributes. The paragraph will contain the value of the first-name
attribute of the current node followed by a space and the value of the surname
attribute of the current node.
<xsl:template match="person">
<xsl:value-of select="@first-name"/> xsl:text <xsl:value-of select="@surname"/>
For example, the following creates an HTML paragraph from aperson
element with first-name
andsurname
children elements. The paragraph will contain the value of the first first-name
child element of the current node followed by a space and the value of the firstsurname
child element of the current node.
<xsl:template match="person">
<xsl:value-of select="first-name"/> xsl:text <xsl:value-of select="surname"/>
The following precedes each procedure
element with a paragraph containing the security level of the procedure. It assumes that the security level that applies to a procedure is determined by asecurity
attribute on the procedure element or on an ancestor element of the procedure. It also assumes that if more than one such element has a security
attribute then the security level is determined by the element that is closest to the procedure.
<xsl:template match="procedure"> fo:block <xsl:value-of select="from-ancestors-or-self(*[@security][1])/@security"/> xsl:apply-templates/
9.6.2 Attribute Value Templates
In an attribute value that is interpreted as anattribute value template, such as an attribute of a literal result element, a StringExpr can be used by surrounding the StringExprwith curly braces ({}
). The attribute value template is instantiated by replacing the string expression together with surrounding curly braces by the result of evaluating the string expression. Curly braces are not recognized in an attribute value in an XSLT stylesheet unless the attribute is specifically stated to be one which is interpreted as an attribute value template.
NOTE: Not all attributes are interpreted as attribute value templates. Attributes whose value is an expression or pattern, attributes of top-level elements (children of a
xsl:stylesheet
element) and attributes that refer to named XSLT objects are not interpreted as attribute value templates. Alsoxmlns
attributes are not interpreted as attribute value templates: it would not be conformant with the XML Namespaces Recommendation to do this.
The following example creates an img
result element from a photograph
element in the source; the value of theSRC
attribute of the img
element is computed from the value of the image-dir
constant and the content of the href
child of the photograph
element; the value of the width
attribute of the img
element is computed from the value of the width
attribute of the size
child of thephotograph
element:
<xsl:variable name="image-dir">/images
<xsl:template match="photograph">
With this source
headquarters.jpgthe result would be
When an attribute value template is instantiated, a double left or right curly brace outside a string expression will be replaced by a single curly brace. It is an error if a right curly brace occurs in an attribute value template outside a string expression without being followed by a second right curly brace; an XSLT processor may signal the error or recover by treating the right curly brace as if it had been doubled. A right curly brace inside a Literal in a string expression is not recognized as terminating the string expression.
Curly braces are not recognized recursively inside string expressions. For example:
is not allowed. Instead use simply:
9.7 Numbering
The xsl:number
element is used to insert a formatted number into the result tree. The number to be inserted may be specified by an expression. The expr
attribute contains aNumberExpr. The value of the NumberExpr is rounded to an integer and then converted to a string using the attributes specified in [9.7.1 Number to String Conversion Attributes]; when used with xsl:number
the value of each of these attributes is interpreted as an attribute value template. After conversion, the resulting string is inserted in the result tree. For example, the following example numbers a sorted list:
<xsl:template match="items"> <xsl:for-each select="item"> <xsl:sort select="."/>
<xsl:number expr="position()" format="1. "/> <xsl:value-of select="."/>
If no expr
attribute is specified, then thexsl:number
element inserts a number based on the position of the current node in the source tree. The following attributes control how the current node is to be numbered:
- The
level
attribute specifies what levels of the source tree should be considered; it has the valuessingle
,multi
orany
. The default issingle
. - The
count
attribute is a pattern that specifies what elements should be counted at those levels. Thecount
attribute defaults to the element type name of the current node. - The
from
attribute is a pattern that specifies where counting starts from.
In addition the xsl:number
element has the attributes specified in [9.7.1 Number to String Conversion Attributes] for number to string conversion.
The xsl:number
element first constructs a list of positive integers using the level
, count
andfrom
attributes:
- When
level="single"
, it goes up to the nearest ancestor (including the current node as its own ancestor) that matches thecount
pattern, and constructs a list of length one containing one plus the number of preceding siblings of that ancestor that match thecount
pattern. If there is no such ancestor, it constructs an empty list. If thefrom
attribute is specified, then the only ancestors that are searched are those that are descendants of the nearest ancestor that matches thefrom
pattern. - When
level="multi"
, it constructs a list of all ancestors of the current node in document order followed by the element itself; it then selects from the list those elements that match thecount
pattern; it then maps each element of the list to one plus the number of preceding siblings of that element that match thecount
pattern. If thefrom
attribute is specified, then the only ancestors that are searched are those that are descendants of the nearest ancestor that matches thefrom
pattern. - When
level="any"
, it constructs a list of length one containing one plus the number of elements at any level of the document that start before this node and that match thecount
pattern. If thefrom
attribute is specified, then only elements after the first element before this element that match thefrom
pattern are considered.Ed. Note: Would it be better to return the number of nodes that match the pattern from the set consisting of the node itself and the nodes starting before the node? This would mean that when the node does not match the pattern, the number of the previous matching node would be returned rather than the number of the next matching node.
The list of numbers is then converted into a string using the attributes specified in [9.7.1 Number to String Conversion Attributes]; when used withxsl:number
the value of each of these attributes is interpreted as an attribute value template. After conversion, the resulting string is inserted in the result tree.
Ed. Note: Allowing them to be attribute value templates isn't consistent with the current DTD: the declared values would all have to be CDATA, and we couldn't use xml:lang because the XML spec doesn't allow the value to be expressed as a template.
The following would number the items in an ordered list:
<xsl:template match="ol/item"> fo:block xsl:number/xsl:text. xsl:apply-templates/ xsl:template
The following two rules would number title
elements. This is intended for a document that contains a sequence of chapters followed by a sequence of appendices, where both chapters and appendices contain sections which in turn contain subsections. Chapters are numbered 1, 2, 3; appendices are numbered A, B, C; sections in chapters are numbered 1.1, 1.2, 1.3; sections in appendices are numbered A.1, A.2, A.3.
<xsl:template match="title"> fo:block <xsl:number level="multi" count="chapter|section|subsection" format="1.1. "/> xsl:apply-templates/
<xsl:template match="appendix//title" priority="1"> fo:block <xsl:number level="multi" count="appendix|section|subsection" format="A.1. "/> xsl:apply-templates/
The following example numbers notes sequentially within a chapter:
<xsl:template match="note"> fo:block <xsl:number level="any" from="chapter" format="(1) "/> xsl:apply-templates/
The following example would number H4
elements in HTML with a three-part label:
<xsl:template match="H4"> fo:block <xsl:number level="any" from="H1" count="H2"/> xsl:text. <xsl:number level="any" from="H2" count="H3"/> xsl:text. <xsl:number level="any" from="H3" count="H4"/> xsl:text xsl:apply-templates/
9.7.1 Number to String Conversion Attributes
The following attributes are used to control conversion of a list of numbers into a string. The numbers are integers greater than 0. The attributes are all optional.
The main attribute is format
. The default value for the format
attribute is 1
. Theformat
attribute is split into a sequence of tokens where each token is a maximal sequence of alphanumeric characters or a maximal sequence of non-alphanumeric characters. Alphanumeric means any character that has a Unicode category of Nd, Nl, No, Lu, Ll, Lt, Lm or Lo. The alphanumeric tokens (format tokens) specify the format to be used for each number in the list. If the first token is a non-alphanumeric token, then the constructed string will start with that token; if the last token is non-alphanumeric token, then the constructed string will end with that token. Non-alphanumeric tokens that occur between two format tokens are separator tokens that are used to join numbers in the list. The n-th format token will be used to format the n-th number in the list. If there are more numbers than format tokens, then the last format token will be used to format remaining numbers. If there are no format tokens, then a format token of 1
is used to format all numbers. The format token specifies the string to be used to represent the number 1. Each number after the first will be separated from the preceding number by the separator token preceding the format token used to format that number, or, if there are no separator tokens, then by.
.
Format tokens are a superset of the allowed values for thetype
attribute for the OL
element in HTML 4.0 and are interpreted as follows:
- Any token where the last character has a decimal digit value of 1 (as specified in the Unicode 2.0 character property database), and the Unicode value of preceding characters is one less than the Unicode value of the last character. This generates a decimal representation of the number where each number is at least as long as the format token. Thus a format token
1
generates the sequence1 2 ... 10 11 12 ...
, and a format token01
generates the sequence01 02 ... 09 10 11 12 ... 99 100 101
. - A format token
A
generates the sequenceA B C ... Z AA AB AC...
. - A format token
a
generates the sequencea b c ... z aa ab ac...
. - A format token
i
generates the sequencei ii iii iv v vi vii vii ix x ...
. - A format token
I
generates the sequenceI II III IV V VI VII VII IX X ...
. - Any other format token indicates a numbering sequence that starts with that token. If an implementation does not support a numbering system that starts with that token, it must use a format token of
1
.
When numbering with an alphabetic sequence, thexml:lang
attribute specifies which language's alphabet is to be used.
NOTE: This can be considered as specifying the language of the value of the
format
attribute and hence is consistent with the semantics ofxml:lang
.
The letter-value
attribute disambiguates between numbering schemes that use letters. In many languages there are two commonly used numbering schemes that use letters. One numbering scheme assigns numeric values to letters in alphabetic sequence, and the other assigns numeric values to each letter in some other manner. In English, these would correspond to the numbering sequences specified by the format tokens a
and i
. In some languages the first member of each sequence is the same, and so the format token alone would be ambiguous. A value ofalphabetic
specifies the alphabetic sequence; a value ofother
specifies the other sequence.
The digit-group-sep
attribute gives the separator between groups of digits, and the optionaln-digits-per-group
specifies the number of digits per group. For example, digit-group-sep=","
andn-digits-per-group="3"
would produce numbers of the form1,000,000
.
The sequence-src
attribute gives the URI of a text resource that contains a whitespace separated list of the members of the numbering sequence.
Ed. Note: Specify what should happen when the sequence runs out.
Here are some examples of conversion specifications:
format="ア"
specifies Katakana numberingformat="イ"
specifies Katakana numbering in the "iroha" orderformat="๑"
specifies numbering with Thai digitsformat="א" letter-value="other"
specifies "traditional" Hebrew numberingformat="ა" letter-value="other"
specifies Georgian numberingformat="α" letter-value="other"
specifies "classical" Greek numberingformat="а" letter-value="other"
specifies Old Slavic numbering
10. Repetition
When the result has a known regular structure, it is useful to be able to specify directly the template for selected nodes. Thexsl:for-each
instruction contains a template which is instantiated for each node selected by the NodeSetExpr specified by theselect
attribute, which is required. The template is instantiated with the selected node as the current node, and with a list of all of the selected nodes as the current node list. The nodes are processed in document order, unless a sorting specification is present (see[12 Sorting]).
For example, given an XML document with this structure
... ... ... ... ... ...the following would create an HTML document containing a table with a row for each customer
element
<xsl:template match="/"> Customers
<xsl:apply-templates select="name"/> | <xsl:for-each select="order">xsl:apply-templates/ |
---|
11. Conditional Processing
There are two instructions in XSLT which support conditional processing in a template: xsl:if
andxsl:choose
. The xsl:if
instruction provides simple if-then conditionality; the xsl:choose
instruction supports selection of one choice when there are several possibilities.
11.1 Conditional Processing with xsl:if
The xsl:if
element has a single attribute,test
which specifies a BooleanExpr. The content is a template. If the expression evaluates to true, then the content is instantiated; otherwise nothing is created. In the following example, the names in a group of names are formatted as a comma separated list:
<xsl:template match="namelist/name"> xsl:apply-templates/ <xsl:if test="not(position()=last())">,
The following colors every other table row yellow:
<xsl:template match="item">
11.2 Conditional Processing with xsl:choose
The xsl:choose
element selects one among a number of possible alternatives. It consists of a series ofxsl:when
elements followed by an optionalxsl:otherwise
element. Each xsl:when
element has a single attribute, test
, which specifies aBooleanExpr. The content of thexsl:when
and xsl:otherwise
elements is a template. When an xsl:choose
element is processed, each of the xsl:when
elements is tested in turn. The content of the first, and only the first, xsl:when
element whose test is true is instantiated. If no xsl:when
is true, the content of the xsl:otherwise
element is instantiated. If no xsl:when
element is true, and noxsl:otherwise
element is present, nothing is created.
The following example enumerates items in an ordered list using arabic numerals, letters, or roman numerals depending on the depth to which the ordered lists are nested.
<xsl:template match="orderedlist/listitem"> <fo:list-item indent-start='2pi'> fo:list-item-label <xsl:variable name="level" expr="size(from-ancestors(orderedlist)) mod 3"/> xsl:choose <xsl:when test='$level=1'> <xsl:number format="i"/> <xsl:when test='$level=2'> <xsl:number format="a"/> xsl:otherwise <xsl:number format="1"/> xsl:text. fo:list-item-body xsl:apply-templates/
12. Sorting
Sorting is specified by adding xsl:sort
elements as children of xsl:apply-templates
orxsl:for-each
. The first xsl:sort
child specifies the primary sort key, the second xsl:sort
child specifies the secondary sort key and so on. Whenxsl:apply-templates
or xsl:for-each
has one or more xsl:sort
children, then instead of processing the selected elements in document order, it sorts the elements according to the specified sort keys and then processes them in sorted order. When used in xsl:for-each
, xsl:sort
elements must occur first.
Ed. Note: Say that the current node list is in sorted order.
xsl:sort
has a select
attribute whose value is a StringExpr. For each node to be processed, the StringExpr is evaluated with that node as the current node. The string that results from evaluating the expression is used as the sort key for that node. The default value of the select
attribute is .
, which, as a StringExpr, returns the value of the current node.
This string serves as a sort key for the node. The following optional attributes on xsl:sort
control how the list of sort keys are sorted:
order
specifies whether the strings should be sorted in ascending or descending order;ascending
specifies ascending order;descending
specifies descending order; the default isascending
lang
specifies the language of the sort keys; it has the same range of values asxml:lang
[XML]; if nolang
value is specified, the language should be determined from the system environmentdata-type
specifies the data type of the strings; the following values are allowedtext
specifies that the sort keys should be sorted lexicographically in the culturally correct manner for the language specified bylang
number
specifies that the sort keys should be converted to numbers and then sorted according to the numeric value; the value specified bylang
can be used to assist in the conversion to numbers
The default value istext
.Ed. Note: We plan to leverage the work on XML schemas to define further values in the future.
case-order
has the valueupper-first
orlower-first
; this applies whendata-type="text"
, and specifies that upper-case letters should sort before lower-case letters or vice-versa respectively. For example, iflang="en"
thenA a B b
are sorted withcase-order="upper-first"
anda A b B
are sorted withcase-order="lower-first"
. The default value is language dependent.
Ed. Note: We plan also to add an attribute whose value is a label identifying the sorting scheme, to be specified by the I18N WG.
The values of all of the above attributes are interpreted asattribute value templates.
NOTE: It is recommended that implementors consult [UNICODE TR10] for information on internationalized sorting.
The sort must be stable: in the sorted list of nodes, any sublist that has sort keys that all compare equal must be in document order.
For example, suppose an employee database has the form
James Clark ...Then a list of employees sorted by name could be generated using:
<xsl:template match="employees">
-
<xsl:apply-templates select="employee">
<xsl:sort select="name/last"/>
<xsl:sort select="name/first"/>
<xsl:template match="employee">
13. Variables and Parameters
A variable is a name that may be bound to a value. The value to which a variable is bound (the value of the variable) can be an object of any of the types that can be returned by expressions. There are two elements that can be used to bind variables:xsl:variable
and xsl:param-variable
. The difference is that the value specified on thexsl:param-variable
variable is only a default value for the binding; when the template or stylesheet within which thexsl:param-variable
element occurs is invoked, parameters may be passed that are used in place of the default values.
For any use of these variable binding elements, there is a region of the stylesheet tree within which the binding is visible; within this region any binding of the variable that was visible on the variable binding element itself is hidden. Thus only the innermost binding of a variable is visible. The set of variable bindings in scope for an expression consists of those bindings that are visible at the point in the stylesheet where the expression occurs.
A variable binding element can specify the value of the variable in two ways. It can have a expr
attribute whose value is an expression, which is evaluated to give the value of the variable. If there is no expr
attribute, then the contents of the variable binding element specifies the value. The contents is a template which is instantiated to give the value. In this case the value is a result tree fragment.
Both xsl:variable
and xsl:param-variable
are allowed at the top-level. A top-level variable binding element declares a global variable that is visible everywhere. A top-levelxsl:param-variable
element declares a parameter to the stylesheet; XSLT does not define the mechanism by which parameters are passed to the stylesheet. It is an error if a stylesheet contains more than one binding of a top-level variable the same name and sameimportance. An XSLT processor may signal the error; if it does not signal the error, it must recover by choosing from amongst the bindings with highest importance the one that occurs last in the stylesheet. At the top-level, the expression or template specifying the variable value is evaluated with the same context as that used to process the root node of the source document: the current node is the root node of the source document and the current node list is a list containing just the root node of the source document. If the template or expression specifying the value of a global variable x references a global variable_y_, then the value for y must be computed before the value of x. It is an error if it is impossible to do this for all global variable definitions, in other words it is an error if the definitions are circular.
This example declares a global variable para-font-size
which it references in an attribute value template.
<xsl:variable name="para-font-size">12pt
<xsl:template match="para"> <fo:block font-size="{$para-font-size}"> xsl:apply-templates/
As well as being allowed at the top-level, bothxsl:variable
and xsl:param-variable
are also allowed in templates. xsl:variable
is allowed anywhere within a template that an instruction is allowed. In this case the binding is visible for all following siblings and their descendants. Note that the binding is not visible for the xsl:variable
element itself. xsl:param-variable
is allowed as a child at the beginning of an xsl:template
element. In this context, the binding is visible for all following siblings and their descendants. Note that the binding is not visible for thexsl:param-variable
element itself.
Parameters are passed to templates using the xsl:param
element. The required name
attribute specifies the name of the parameter (the variable the value of whose binding is to be replaced). xsl:param
is allowed within bothxsl:call-template
and xsl:apply-templates
. The value of the parameter is specified in the same way as forxsl:variable
and xsl:param-variable
. The current node and current node list used for computing the value specified by xsl:param
element is the same as that used for the xsl:apply-templates
orxsl:call-template
element within which it occurs. It is not an error to pass a parameter x to a template that does not have a xsl:param-variable
element for_x_; the parameter is simply ignored.
This example defines a named template for anumbered-block
with an argument to control the format of the number.
<xsl:template name="numbered-block"> <xsl:param-variable name="format">1. <xsl:number format="{$format}"/> fo:blockxsl:apply-templates/
<xsl:template match="appendix/title"> <xsl:call-template name="numbered-block"> <xsl:param name="format">A.
14. Messages
The xsl:message
instruction sends a message in a way that is dependent on the XSLT processor. The content of thexsl:message
instruction is a template. Thexsl:message
is instantiated by instantiating the content to create an XML fragment. This XML fragment is the content of the message.
NOTE: An XSLT processor might implement
xsl:message
by popping up an alert box or by writing to a log file.
15. Combining Stylesheets
XSLT provides two mechanisms to combine stylesheets:
- an import mechanism that allows stylesheets to override each other, and
- an inclusion mechanism that allows stylesheets to be textually combined.
15.1 Stylesheet Import
An XSLT stylesheet may contain xsl:import
elements. All the xsl:import
elements must occur at the beginning of the stylesheet. The xsl:import
element has anhref
attribute whose value is the URI of a stylesheet to be imported. A relative URI is resolved relative to the base URI of the xsl:import
element (see [4.2.2 Base URI]).
Ed. Note: Say what importing a stylesheet means.
<xsl:stylesheet xmlns:xsl="" title="undefined" rel="noopener noreferrer">http://www.w3.org/XSL/Transform/1.0"> <xsl:import href="article.xsl"/> <xsl:import href="bigfont.xsl"/> <xsl:attribute-set name="note-style"> <xsl:attribute name="font-style">italic
Definitions and template rules in the importing stylesheet are defined to be moreimportant than definitions and template rules in any imported stylesheets. Also definitions and template rules in one imported stylesheet are defined to be more important than definitions and template rules in previous imported stylesheets.
In general a more important definition or template rule takes precedence over a less important definition or template rule. This is defined in detail for each kind of definition and for template rules.
Ed. Note: Say something about the case where the same stylesheet gets imported twice. This should be treated the same as importing a stylesheet with the same content but different URIs. What about import loops?
xsl:apply-imports
processes the current node using only template rules that were imported into the stylesheet containing the current rule; the node is processed in the current rule's mode.
Ed. Note: Expand this.
15.2 Stylesheet Inclusion
An XSLT stylesheet may include another XSLT stylesheet using anxsl:include
element. The xsl:include
element has an href
attribute whose value is the URI of a stylesheet to be included. A relative URI is resolved relative to the base URI of the xsl:include
element (see [4.2.2 Base URI]). The xsl:include
element can occur as the child of the xsl:stylesheet
element at any point after all xsl:import
elements.
The inclusion works at the XML tree level. The resource located by the href
attribute value is parsed as an XML document, and the children of the xsl:stylesheet
element in this document replace the xsl:include
element in the including document. Also any xsl:import
elements in the included document are moved up in the including document to after any existingxsl:import
elements in the including document. Unlike with xsl:import
, the fact that rules or definitions are included does not affect the way they are processed.
Ed. Note: What happens when a stylesheet directly or indirectly includes itself?
15.3 Embedding Stylesheets
Normally an XSLT stylesheet is a complete XML document with thexsl:stylesheet
element as the document element. However an XSLT stylesheet may also be embedded in another resource. Two forms of embedding are possible:
- the XSLT stylesheet may be textually embedded in a non-XML resource, or
- the
xsl:stylesheet
element may occur in an XML document other than as the document element.
In the second case, the possibility arises of documents with inline style, that is documents that specify their own style. XSLT does not define a specific mechanism for this. This is because this can be done by means of a general purpose mechanism for associating stylesheets with documents provided that:
- the mechanism allows a part of a resource to be specified as the stylesheet, for example by using a URI with a fragment identifier, and
- the mechanism can itself can be embedded in the document, for example as a processing instruction.
It is not in the scope of XSLT to define such a mechanism.
NOTE: This is because the mechanism should be independent of any one stylesheet mechanism.
The xsl:stylesheet
element may have an ID attribute that specifies a unique identifier.
NOTE: In order for such an attribute to be used with the
id
XPointer location term, it must actually be declared in the DTD as being an ID.
The following example shows how inline style can be accomplished using the xml-stylesheet
processing instruction mechanism for associating a stylesheet with an XML document. The URI uses an XPointer in a fragment identifier to locate thexsl:stylesheet
element.
NOTE: The
type
pseudo-attribute in thexml-stylesheet
processing instruction identifies the stylesheet language, not the content type of the resource of which the stylesheet is a part.
A. DTD Fragment for XSLT Stylesheets
The following entity can be used to construct a DTD for XSLT stylesheets that create instances of a particular result DTD. Before referencing the entity, the stylesheet DTD must define aresult-elements
parameter entity listing the allowed result element types. For example:
The use of the xsl:
prefix in this DTD does not imply that XSLT stylesheets are required to use this prefix. Any of the elements declared in this DTD may have attributes whose name starts with xmlns:
or is equal to xmlns
in addition to the attributes declared in this DTD.
B. References
B.1 Normative References
XML
World Wide Web Consortium. Extensible Markup Language (XML) 1.0. W3C Recommendation. See http://www.w3.org/TR/1998/REC-xml-19980210
XML Names
World Wide Web Consortium. Namespaces in XML. W3C Recommendation. Seehttp://www.w3.org/TR/REC-xml-names
B.2 Other References
CSS2
World Wide Web Consortium. Cascading Style Sheets, level 2 (CSS2). W3C Recommendation. See http://www.w3.org/TR/1998/REC-CSS2-19980512
DSSSL
International Organization for Standardization, International Electrotechnical Commission.ISO/IEC 10179:1996. Document Style Semantics and Specification Language (DSSSL). International Standard.
UNICODE TR10
Unicode Consortium. Draft Unicode Technical Report #10. Unicode Collation Algorithm. Draft Unicode Technical Report. See http://www.unicode.org/unicode/reports/tr10/index.html
.
XHTML
World Wide Web Consortium. XHTML 1.0: The Extensible HyperText Markup Language. W3C Working Draft. See http://www.w3.org/TR/WD-html-in-xml
XPointer
World Wide Web Consortium. XML Pointer Language (XPointer). W3C Working Draft. See http://www.w3.org/TR/WD-xptr
XML Stylesheet
World Wide Web Consortium. _Associating stylesheets with XML documents._W3C Working Draft. See http://www.w3.org/TR/WD-xml-stylesheet
XSL
World Wide Web Consortium. Extensible Stylesheet Language (XSL). W3C Working Draft. See http://www.w3.org/TR/WD-xsl
C. Examples
C.1 Formatting Objects Example
The following is a simple but complete stylesheet.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0" xmlns:fo="http://www.w3.org/XSL/Format/1.0" result-ns="fo" indent-result="yes"> <xsl:template match='/'> <fo:basic-page-sequence font-family="serif"> <fo:simple-page-master page-master-name='scrolling'/> <fo:queue queue-name='body'> xsl:apply-templates/
<xsl:template match="title"> <fo:block font-weight="bold"> xsl:apply-templates/
<xsl:template match="p"> fo:block xsl:apply-templates/
<xsl:template match="emph"> <fo:inline-sequence font-style="italic"> xsl:apply-templates/
With the following source document
An exampleThis is a test.
This is another test.
it would produce the following result
<fo:basic-page-sequence xmlns:fo="http://www.w3.org/XSL/Format/1.0" font-family="serif"> <fo:simple-page-master page-master-name="scrolling"/> <fo:queue queue-name="body"> <fo:block font-weight="bold">An example fo:blockThis is a test. fo:blockThis is <fo:inline-sequence font-style="italic">another test.
C.2 XHTML Example
This is an example of using XSLT to create an XHTML document (see[XHTML]). The following stylesheet:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0" xmlns="http://www.w3.org/Profiles/xhtml1-transitional" default-space="strip" indent-result="yes">
<xsl:template match="/">
Sales Results By Division
<body>
<table border="1">
<tr>
<th>Division</th>
<th>Revenue</th>
<th>Growth</th>
<th>Bonus</th>
</tr>
<xsl:apply-templates/>
</table>
</body>
<xsl:template match="sales">
<xsl:apply-templates match="division">
<!-- order the result by revenue -->
<xsl:sort select="revenue"
data-type="number"
order="descending"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="division">
<tr>
<td><em><xsl:value-of select="@id"/></em></td>
<xsl:apply-templates select="revenue"/>
<xsl:apply-templates select="growth"/>
<xsl:apply-templates select="bonus"/>
</tr>
</xsl:template>
<xsl:template match="revenue | growth | bonus">
<td><xsl:apply-templates/></td>
</xsl:template>
with the following input document
<division id="North">
<revenue>10</revenue>
<growth>9</growth>
<bonus>7</bonus>
</division>
<division id="South">
<revenue>4</revenue>
<growth>3</growth>
<bonus>4</bonus>
</division>
<division id="West">
<revenue>6</revenue>
<growth>-1.5</growth>
<bonus>2</bonus>
</division>
would produce the following result
Sales Results By DivisionDivision | Revenue | Growth | Bonus |
---|---|---|---|
North | 10 | 9 | 7 |
West | 6 | -1.5 | 2 |
South | 4 | 3 | 4 |
D. Acknowledgements
The following have contributed to authoring this draft:
- Daniel Lipkin, Oracle
- Jonathan Marsh, Microsoft
- Henry Thompson, University of Edinburgh
- Norman Walsh, ArborText
- Steve Zilles, Adobe
This specification was developed and approved for publication by the W3C XSL Working Group (WG). WG approval of this specification does not necessarily imply that all WG members voted for its approval. The current members of the XSL WG are:
Sharon Adler, Inso (Co-Chair); Anders Berglund, Inso; Scott Boag, Lotus; Jeff Caruso, Bitstream; James Clark (XSLT Editor); Peter Danielsen, Bell Labs; Don Day, IBM; Stephen Deach, Adobe; Angel Diaz, IBM; Dwayne Dicks, SoftQuad; Andrew Greene, Bitstream; Paul Grosso, ArborText; Eduardo Gutentag, Sun; Mickey Kimchi, Enigma; Chris Lilley, W3C; Daniel Lipkin, Oracle; Chris Maden, O'Reilly; Jonathan Marsh, Microsoft; Alex Milowski, CommerceOne; Boris Moore, RivCom; Steve Muench, Oracle; Carolyn Pampino, Interleaf; Scott Parnell, Xerox; Vincent Quint, W3C; Gregg Reynolds, Datalogics; Jonathan Robie, Software AG; Henry Thompson, University of Edinburgh; Philip Wadler, Bell Labs; Randy Waki, Novell; Norm Walsh, ArborText; Sanjiva Weerawarana, IBM; Umit Yalcinalp, Sun; Steve Zilles, Adobe (Co-Chair)
E. Changes from Previous Public Working Draft
The following is a summary of changes since the previous public working draft.
Select patterns, string expressions and boolean expressions have been combined and generalized into an expression language with multiple data types (see [6 Expressions and Patterns]).
xsl:strip-space
and xsl:preserve-space
have an elements
attribute which specifies a list of element types, rather than a element
attribute specifying a single element type.
The id()
function has been split intoid()
and idref()
.
xsl:id
has been replaced by the xsl:key
element (see [6.4.1 Declaring Keys]), and associated key()
and keyref()
functions.
The doc()
and docref()
have been added to support multiple source documents.
Namespace wildcards (ns:*
) have been added.
ancestor()
and ancestor-or-self()
have been replaced by a more general facility for addressing different axes.
Positional qualifiers (first-of-type()
,first-of-any()
, last-of-type()
,last-of-any()
) have been replaced by theposition()
and last()
functions and numeric expressions inside []
.
Counters have been removed. An expr
attribute has been added to xsl:number
which in conjunction with theposition()
allows numbering of sorted node lists.
Multiple adjacent uses of []
are allowed.
Macros and templates have been unified by allowing templates to be named and have parameters.
xsl:constant
have been replaced byxsl:variable
which allows variables to be typed and local.
The default for priority
on xsl:template
has changed (see [7.4 Conflict Resolution for Template Rules]).
An extension mechanism has been added (see [6.4.2 Declaring Extension Functions]).
The namespace URIs have been changed.
xsl:copy-of
has been added (see [9.5 Copying]).
A error recovery mechanism to allow forwards-compatibility has been added (see [3 Forwards-compatible Processing]).
A namespace
attribute has been added toxsl:element
and xsl:attribute
.