[This local archive copy is from the official and canonical URL, http://www.w3.org/TR/1999/WD-xslt-19990421; please refer to the canonical source document if possible.]
Copyright © 1998 W3C (MIT, INRIA, Keio ), All Rights Reserved. W3C liability,trademark, document use and software licensing rules apply.
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.
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; archives of the comments are available. Public discussion of XSL, including XSL Transformations, takes place on the XSL-List mailing list.
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.
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 URI
http://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.
<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="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:functions> <xsl:locale name="..."> ... </xsl:locale> <xsl:attribute-set name="..."> ... </xsl:attribute-set> <xsl:variable name="...">...</xsl:variable> <xsl:param-variable name="...">...</xsl:param-variable> <xsl:template match="..."> ... </xsl:template> <xsl:template name="..."> ... </xsl:template> </xsl:stylesheet>
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.
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="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:when> <xsl:otherwise> <p>Sorry this stylesheet requires XSLT 1.1.</p> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
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 string value 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?
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.
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.
The descendants 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 as document order.
Ed. Note: Need a definition of document order that handles arbitrary node types, including attributes.
An element object may have a unique identifier (ID). This is the
value of the attribute which is declared in the DTD as type
ID
. 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.
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.
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?
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.
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
?>
.
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
-->
.
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].
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 of
preserve
, and no closer ancestor element has
xml:space
with a value of
default
.
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 a
default-space
attribute with a value of
strip
, 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.
The elements
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. The elements
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.
The xsl:stylesheet
element has an optional
result-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 the
fo:
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="/"> <html> <xsl:apply-templates/> </html> </xsl:template> ... </xsl:stylesheet>
The xsl:stylesheet
element can include an
indent-result
attribute with values yes
or
no
. If the stylesheet specifies
indent-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 with
indent-result="yes"
, the XSLT processor can use any
algorithm provided that the result is the same as the result with
indent-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
.
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:
An expression is evaluated to yield an object which has one of the following types:
Expression evaluation occurs with respect to a context, which consists of:
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].
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 the
para
element children of the context node
from-children(*)
selects all element
children of the context node
from-children(text())
selects all text
node children of the context node
from-children(node())
selects all the
children of the context node, whatever their node type
from-attributes(name)
selects the
name
attribute of the context node
from-attributes(*)
selects all the
attributes of the context node
from-descendants(para)
selects the
para
element descendants of the context node
from-ancestors(div)
selects all div
ancestors of the context node
from-ancestors-or-self(div)
selects the
div
ancestors of the context node and, if the context node is a
div
element, the context node as well
from-descendants-or-self(para)
selects the
para
element descendants of the context node and, if the context node is
a para
element, the context node as well
from-self(para)
selects the context node if it is a
para
element, and otherwise selects nothing
from-children(chapter)/from-descendants(para)
selects the para
element descendants of the
chapter
element children of the context node
from-children(*)/from-children(para)
selects
all para
grandchildren of the context node
/
selects the document root (which is
always the parent of the document element)
/from-descendants(para)
selects all the
para
elements in the same document as the context node
/from-descendants(olist)/from-children(item)
selects all the item
elements in the same document as the
context node that have an olist
parent
from-children(para[position()=1])
selects the first
para
child of the context node
from-children(para[position()=last()])
selects the last
para
child of the context node
from-children(para[position()=last()-1])
selects
the last but one para
child of the context node
from-children(para[position()>1])
selects all
the para
children of the context node other than the
first para
child of the context node
from-following-siblings(chapter[position()=1])
selects the next chapter
sibling of the context node
from-preceding-siblings(chapter[position()=1])
selects the previous chapter
sibling of the
context node
/from-descendants(figure[position()=42])
selects
the forty-second figure
element in the
document
/from-children(doc)/from-children(chapter[position()=5])/from-children(section[position()=2])
selects the second section
of the fifth
chapter
of the doc
document element
from-children(para[from-attributes(type)="warning"])
selects all para
children of the context node that have a
type
attribute with value warning
from-children(para[from-attributes(type)="warning"][position()=5])
selects the fifth para
child of the context node that has a
type
attribute with value warning
from-children(para[position()=5][from-attributes(type)="warning"])
selects the fifth para
child of the context node if that child has
a type
attribute with value
warning
from-children(chapter[from-children(title)="Introduction"])
selects the chapter
children of the context node whose first
title
child has value equal to
Introduction
from-children(chapter[from-children(title)])
selects the chapter
children of the context node that have one
or more title
children
from-children(chapter[from-children(title[from-self(*)="Introduction"])])
selects the chapter
children of the context node any of whose
title
children has value equal to
Introduction
from-children(*[from-self(chapter) or
from-self(appendix)])
selects the chapter
and
appendix
children of the context node
from-children(*[from-self(chapter) or
from-self(appendix)][position()=last()])
selects the last
chapter
or appendix
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 the
para
element children of the div
element
children of the context node, or, in other words, the
para
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.
[1] | LocationPath | ::= | RelativeLocationPath | |
| AbsoluteLocationPath | ||||
[2] | AbsoluteLocationPath | ::= | '/' RelativeLocationPath? | |
| AbbreviatedAbsoluteLocationPath | ||||
[3] | RelativeLocationPath | ::= | Step | |
| RelativeLocationPath '/' Step | ||||
| AbbreviatedRelativeLocationPath | ||||
[4] | Step | ::= | AxisIdentifier '(' NodeTest Predicate* ')' | |
| AbbreviatedStep |
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 one
Ed. 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 order
Issue (following-axis): Is the
following
axis needed?
Issue (following-start): Should the
following
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 order
Issue (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 by
from-
to distinguish it from a function name.
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 with
xmlns
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, and
from-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 test
comment()
is true for any comment node, and the node test
pi()
is true for any processing instruction. The
pi()
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 ')' |
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 path
para[3]
is equivalent to para[position()=3]
.
[7] | Predicate | ::= | '[' PredicateExpr ']' | |
[8] | PredicateExpr | ::= | Expr |
Here are some examples of location paths using abbreviated syntax:
para
selects the para
element children of
the context node
*
selects all element children of the
context node
text()
selects all text node children of the
context node
@name
selects the name
attribute of
the context node
@*
selects all the attributes of the
context node
para[1]
selects the first para
child of
the context node
para[last()]
selects the last para
child
of the context node
*/para
selects all para
grandchildren of
the context node
/doc/chapter[5]/section[2]
selects the second
section
of the fifth chapter
of the
doc
chapter//para
selects the para
element
descendants of the chapter
element children of the
context node
//para
selects all the para
descendants of
the document root and thus selects all para
elements in the
same document as the context node
//olist/item
selects all the item
elements in the same document as the context node that have an
olist
parent
.
selects the context node
.//para
selects the para
element
descendants of the context node
..
selects the parent of the context node
../@lang
selects the lang
attribute
of the parent of the context node
para[@type="warning"]
selects all para
children of the context node that have a type
attribute with
value warning
para[@type="warning"][5]
selects the fifth
para
child of the context node that has a type
attribute with value warning
para[5][@type="warning"]
selects the fifth
para
child of the context node if that child has a
type
attribute with value warning
chapter[title="Introduction"]
selects the
chapter
children of the context node whose first
title
child has value equal to
Introduction
chapter[title]
selects the chapter
children of the context node that have one or more title
children
chapter[title[.="Introduction"]]
selects the
chapter
children of the context node any of whose
title
children has value equal to
Introduction
employee[@secretary and @assistant]
selects all
the employee
children of the context node that have both a
secretary
attribute and an assistant
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 path
para[@type="warning"]
is short for
from-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 a
para
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 for
div/from-descendants-or-self(node())/from-children(para)
and
so will select all para
descendants of div
children.
A location step of .
is short for
from-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 for
from-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.
[9] | AbbreviatedAbsoluteLocationPath | ::= | '//' RelativeLocationPath | |
[10] | AbbreviatedRelativeLocationPath | ::= | RelativeLocationPath '//' Step | |
[11] | AbbreviatedStep | ::= | AbbreviatedNodeTestStep | |
| '.' | ||||
| '..' | ||||
[12] | AbbreviatedNodeTestStep | ::= | '@'? NodeTest Predicate* |
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 |
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 to
last()
.
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 ID
foo
id("foo")/from-children(para[position()=5])
selects
the fifth para
child of the element with unique ID
foo
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 a
QName 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? ')' |
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 the
string()
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 by
xml: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 no
xml:lang
attribute, by the value of the
xml: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:
<para xml:lang="en"/> <div xml:lang="en"><para/></div> <para xml:lang="EN"/> <para xml:lang="en-us"/>
[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 ')' |
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 argument
Ed. 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
returns 2
5 quo -2
returns -2
-5 quo 2
returns -2
-5 quo -2
returns 2
The mod
operator returns the remainder from the
quo
operation. For example,
5 mod 2
returns 1
5 mod -2
returns 1
-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.
[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 ')' |
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
string true
.
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","/")
returns
1999
.
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","/")
returns
04/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?
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.
[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. The
function-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.
[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 processorThe 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()"/> </xsl:if>
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, CName
or 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.
[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 |
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 any para
element
*
matches any element
chapter|appendix
matches any
chapter
element and any appendix
element
olist/item
matches any item
element with
an olist
parent
appendix//para
matches any para
element with
an appendix
ancestor element
/
matches the root node
text()
matches any text node
pi()
matches any processing instruction
id("W11")
matches the element with unique ID
W11
para[1]
matches any para
element
that is the first para
child element of its
parent
*[position()=1 and from-self(para)]
matches any
para
element that is the first child element of its
parent
para[last()=1]
matches any para
element that is the only child element of its parent
items/item[position()>1]
matches any
item
element that has a items
parent and
that is not the first item
child of its parent
item[position() mod 2 = 1]
would be true for any
item
element that is an odd-numbered item
child of its parent.
div[@class="appendix"]//p
matches any
p
element with a div
ancestor element that
has a class
attribute with value
appendix
@class
matches any class
attribute
(not any element that has a class
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 either
AxisIdentifiers or .
or
..
. Location path patterns can also start with an
id()
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.
[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 StepPattern
that 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 an item
element
evaluating the PredicateExpr
position()=1
with the node as context node and the
siblings of the node that are item
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 a
ulist
element that has an appendix
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.
The xsl:key
element is used to declare keys. The
name
specifies the name of the key. The
match
attribute is a Pattern; a
xsl:key
element gives information about the keys of any
node that match the pattern specified in the match attribute. The
use
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 the xsl:key
element;
the value of the name
attribute of the
xsl: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 the xsl: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 one
xsl:key
element that matches a given node; all of the
matching xsl:key
elements are used.
Ed. Note: Add some examples.
Implementations of the extension functions in a namespace can be
provided using the xsl:functions
element. The required
ns
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 the
xsl:functions
element.
The implementation may be provided in two ways. If the
code
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 the
code
attribute is not present, then the content of the
xsl: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="http://www.jclark.com"> <xsl:template match="/"> <xsl:value-of select="jjc:currentDate()"/> </xsl:template> <xsl:functions ns="jjc" type="text/javascript"> function currentDate() { return Date().toString() } <p>When multiple alternative implementations are provided, it is up to the XSLT processor to determine which to use.</p> </xsl:functions> <xsl:functions ns="jjc" code="clsid:9A447990-E64D-11D2-8C29-00A0CC2428DA"/> </xsl:stylesheet>
The xsl:functions
element may also have an
archive
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.
The xsl:locale
element declares a locale which
controls the interpretation of a format pattern used by the
format-number()
function. If there is a
name
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 each
get
/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 sign
grouping-separator
specifies the character used
as a grouping (eg thousands) separator
percent
specifies the character used as a
percent sign
per-mill
specifies the character used as a per
mille sign
zero-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 pattern
pattern-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
infinity
NaN
specifies the string used to represent the
NaN value
minus-sign
specifies the string used as the
default minus sign
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.
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 a
name
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 <emph>important</emph> 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 of
bold
.
<xsl:template match="emph"> <fo:inline-sequence font-weight="bold"> <xsl:apply-templates/> </fo:inline-sequence> </xsl:template>
As described later, the xsl:apply-templates
element
recursively processes the children of the source element.
This example creates a block for a chapter
element and
then processes its immediate children.
<xsl:template match="chapter"> <fo:block> <xsl:apply-templates/> </fo:block> </xsl:template>
In the absence of a select
attribute, the
xsl: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 the
select
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 the
author
children of the author-group
:
<xsl:template match="author-group"> <fo:inline-sequence> <xsl:apply-templates select="author"/> </fo:inline-sequence> </xsl:template>
The following example processes all of the first-name
s
of the author
s that are children of
author-group
:
<xsl:template match="author-group"> <fo:inline-sequence> <xsl:apply-templates select="author/first-name"/> </fo:inline-sequence> </xsl:template>
This example processes all of the heading
elements
contained in the book
element.
<xsl:template match="book"> <fo:block> <xsl:apply-templates select=".//heading"/> </fo:block> </xsl:template>
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"/> </fo:block> </xsl:template>
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"> <TABLE> <xsl:apply-templates select="sales/domestic"/> </TABLE> <TABLE> <xsl:apply-templates select="sales/foreign"/> </TABLE> </xsl:template>
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<doc><div><div></div></div></doc>the rule<xsl:template match="doc"> <xsl:apply-templates select=".//div"/> </xsl:template>will process both the outerdiv
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.
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 less important 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.
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.
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/> </xsl:template>
There is also a built-in template rule for text nodes that copies text through:
<xsl:template match="text()"> <xsl:value-of select="."/> </xsl:template>
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="*|/"
or
match="text()"
.
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 an
xsl:apply-templates
element has a mode
attribute, then it applies only to those template rules from
xsl: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 in
xsl:apply-templates
.
Ed. Note: Add some examples.
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. Unlike
xsl: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.
This section describes instructions that directly create nodes in the result tree.
Issue (multiple-results): Should it be possible to create multiple result trees?
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 string
quote:
. 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:http://www.w3.org/XSL/Transform/1.0"> <xsl:template match="/"> <qxsl:stylesheet result-ns="fo"> <xsl:apply-templates/> </qxsl:stylesheet> </xsl:template> <xsl:template match="block"> <qxsl:template match="{.}"> <fo:block><qxsl:apply-templates/></fo:block> </qxsl:template> </xsl:template> </xsl:stylesheet>
will generate an XSLT stylesheet from a document of the form:
<elements> <block>p</block> <block>h1</block> <block>h2</block> <block>h3</block> <block>h4</block> </elements>
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 optional
namespace
attribute. The content of the
xsl: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 the
name
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 the
name
attribute when selecting the prefix used for
outputting the created element as XML. They are not however required
to do so.
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 as
xsl:element
. The name of the attribute to be created is
specified by a required name
attribute and an optional
namespace
attribute. Instantiating an
xsl:attribute
element adds an attribute node to the
containing result element node. The content of the
xsl: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 the
xsl: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 the
name
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 the
name
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.
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 required
attribute-set
attribute that specifies the name of the
attribute set. xsl:use
is allowed in the same places as
xsl:attribute
. The content of the
xsl:attribute-set
consists of xsl:attribute
elements that specify attributes; it may also contain
xsl: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 set
title-style
and uses it in a template rule.
<xsl:attribute-set name="title-style"> <xsl:attribute name="font-size">12pt</xsl:attribute> <xsl:attribute name="font-weight">bold</xsl:attribute> </xsl:attribute-set> <xsl:template match="chapter/heading"> <fo:block quadding="start"> <xsl:use attribute-set="title-style"/> <xsl:apply-templates/> </fo:block> </xsl:template>
Any attribute in a named attribute set specified by
xsl: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.
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 an
xsl: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.
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 required
name
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"</xsl:pi>
would create the processing instruction
<?xml-stylesheet href="book.css" type="text/css"?>
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 the
xsl: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?
The xsl:comment
element is instantiated to create a
comment node in the result tree. The content of the
xsl:comment
element is a template for the value of
the comment node.
For example, this
<xsl:comment>This file is automatically generated. Do not edit!</xsl:comment>
would create the comment
<!--This file is automatically generated. Do not edit!-->
It is an error if instantiating the content of
xsl: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 the
xsl: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.
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 the
xsl: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 using
xsl:copy
as follows:
<xsl:template match="*|@*|comment()|pi()|text()"> <xsl:copy> <xsl:apply-templates select="*|@*|comment()|pi()|text()"/> </xsl:copy> </xsl:template>
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 use
xsl:copy
(see [9.1.3 Creating Attributes with xsl:attribute
]).
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. The
xsl: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
({}
).
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 a
person
element with first-name
and
surname
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"> <p> <xsl:value-of select="@first-name"/> <xsl:text> </xsl:text> <xsl:value-of select="@surname"/> </p> </xsl:template>
For example, the following creates an HTML paragraph from a
person
element with first-name
and
surname
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 first
surname
child element of the current node.
<xsl:template match="person"> <p> <xsl:value-of select="first-name"/> <xsl:text> </xsl:text> <xsl:value-of select="surname"/> </p> </xsl:template>
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 a
security
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"/> </fo:block> <xsl:apply-templates/> </xsl:template>
In an attribute value that is interpreted as an
attribute value template, such as an attribute of a
literal result element, a StringExpr can
be used by surrounding the StringExpr
with 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 axsl: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 the
SRC
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 the
photograph
element:
<xsl:variable name="image-dir">/images</xsl:variable> <xsl:template match="photograph"> <img src="{$image-dir}/{href}" width="{size/@width}"/> </xsl:template>
With this source
<photograph> <href>headquarters.jpg</href> <size width="300"/> </photograph>
the result would be
<img src="/images/headquarters.jpg" width="300"/>
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:
<a href="#{id({@ref})/title}">
is not allowed. Instead use simply:
<a href="#{idref(@ref)/title}">
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 a
NumberExpr. 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="."/> <p> <xsl:number expr="position()" format="1. "/> <xsl:value-of select="."/> </p> </xsl:for-each> </xsl:template>
If no expr
attribute is specified, then the
xsl: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 values
single
, multi
or any
. The
default is single
.
The count
attribute is a pattern that specifies
what elements should be counted at those levels. The
count
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
and
from
attributes:
When level="single"
, it goes up to the nearest
ancestor (including the current node as its own ancestor) that
matches the count
pattern, and constructs a list of length one
containing one plus the number of preceding siblings of that ancestor
that match the count
pattern. If there is no such
ancestor, it constructs an empty list. If the from
attribute is specified, then the only ancestors that are searched are
those that are descendants of the nearest ancestor that matches the
from
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 the count
pattern; it then maps each element of the
list to one plus the number of preceding siblings of that element that
match the count
pattern. If the from
attribute is specified, then the only ancestors that are searched are
those that are descendants of the nearest ancestor that matches the
from
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 the
count
pattern. If the from
attribute is
specified, then only elements after the first element before this
element that match the from
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 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.
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:text><xsl:apply-templates/> </fo:block> <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/> </fo:block> </xsl:template> <xsl:template match="appendix//title" priority="1"> <fo:block> <xsl:number level="multi" count="appendix|section|subsection" format="A.1. "/> <xsl:apply-templates/> </fo:block> </xsl:template>
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/> </fo:block> </xsl:template>
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:text> <xsl:number level="any" from="H2" count="H3"/> <xsl:text>.</xsl:text> <xsl:number level="any" from="H3" count="H4"/> <xsl:text> </xsl:text> <xsl:apply-templates/> </fo:block> </xsl:template>
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
. The
format
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 the
type
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
sequence 1 2 ... 10 11 12 ...
, and a format token
01
generates the sequence 01 02 ... 09 10 11 12
... 99 100 101
.
A format token A
generates the sequence A
B C ... Z AA AB AC...
.
A format token a
generates the sequence a
b c ... z aa ab ac...
.
A format token i
generates the sequence i
ii iii iv v vi vii vii ix x ...
.
A format token I
generates the sequence I
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, the
xml:lang
attribute specifies which language's alphabet is
to be used.
NOTE: This can be considered as specifying the language of the value of theformat
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 of
alphabetic
specifies the alphabetic sequence; a value of
other
specifies the other sequence.
The digit-group-sep
attribute gives the separator
between groups of digits, and the optional
n-digits-per-group
specifies the number of digits per
group. For example, digit-group-sep=","
and
n-digits-per-group="3"
would produce numbers of the form
1,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
numbering
format="イ"
specifies Katakana
numbering in the "iroha" order
format="๑"
specifies numbering with
Thai digits
format="א" letter-value="other"
specifies "traditional" Hebrew numbering
format="ა" letter-value="other"
specifies Georgian numbering
format="α" letter-value="other"
specifies "classical" Greek numbering
format="а" letter-value="other"
specifies Old Slavic numbering
When the result has a known regular structure, it is useful to be
able to specify directly the template for selected nodes. The
xsl:for-each
instruction contains a template which is
instantiated for each node selected by the NodeSetExpr specified by the
select
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
<customers> <customer> <name>...</name> <order>...</order> <order>...</order> </customer> <customer> <name>...</name> <order>...</order> <order>...</order> </customer> </customers>
the following would create an HTML document containing a table with
a row for each customer
element
<xsl:template match="/"> <HTML> <HEAD> <TITLE>Customers</TITLE> </HEAD> <BODY> <TABLE> <TBODY> <xsl:for-each select="customers/customer"> <TR> <TH> <xsl:apply-templates select="name"/> </TH> <xsl:for-each select="order"> <TD> <xsl:apply-templates/> </TD> </xsl:for-each> </TR> </xsl:for-each> </TBODY> </TABLE> </BODY> </HTML> </xsl:template>
There are two instructions in XSLT which support conditional
processing in a template: xsl:if
and
xsl:choose
. The xsl:if
instruction provides
simple if-then conditionality; the xsl:choose
instruction
supports selection of one choice when there are several
possibilities.
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())">, </xsl:if> </xsl:template>
The following colors every other table row yellow:
<xsl:template match="item"> <tr> <xsl:if test="position() mod 2 = 0"> <xsl:attribute name="bgcolor">yellow</xsl:attribute> </xsl:if> <xsl:apply-templates/> </tr> </xsl:template>
xsl:choose
The xsl:choose
element selects one among a number of
possible alternatives. It consists of a series of
xsl:when
elements followed by an optional
xsl:otherwise
element. Each xsl:when
element has a single attribute, test
, which specifies a
BooleanExpr. The content of the
xsl: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 no
xsl: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> <xsl:when test='$level=2'> <xsl:number format="a"/> </xsl:when> <xsl:otherwise> <xsl:number format="1"/> </xsl:otherwise> </xsl:choose> <xsl:text>. </xsl:text> </fo:list-item-label> <fo:list-item-body> <xsl:apply-templates/> </fo:list-item-body> </fo:list-item> </xsl:template>
Sorting is specified by adding xsl:sort
elements as
children of xsl:apply-templates
or
xsl: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. When
xsl: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 is ascending
lang
specifies the language of the sort keys; it
has the same range of values as xml:lang
[XML]; if no lang
value is specified, the
language should be determined from the system environment
data-type
specifies the data type of the
strings; the following values are allowed
text
specifies that the sort keys should be
sorted lexicographically in the culturally correct manner for the
language specified by lang
number
specifies that the sort keys should be
converted to numbers and then sorted according to the numeric
value; the value specified by lang
can be used
to assist in the conversion to numbers
The default value is text
.
Ed. Note: We plan to leverage the work on XML schemas to define further values in the future.
case-order
has the value
upper-first
or lower-first
; this applies
when data-type="text"
, and specifies that upper-case
letters should sort before lower-case letters or vice-versa
respectively. For example, if lang="en"
then A a B
b
are sorted with case-order="upper-first"
and
a A b B
are sorted with
case-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 as attribute 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
<employees> <employee> <name> <first>James</first> <last>Clark</last> </name> ... </employee> </employees>
Then a list of employees sorted by name could be generated using:
<xsl:template match="employees"> <ul> <xsl:apply-templates select="employee"> <xsl:sort select="name/last"/> <xsl:sort select="name/first"/> </xsl:apply-templates> </ul> </xsl:template> <xsl:template match="employee"> <li> <xsl:value-of select="name/first"/> <xsl:text> </xsl:text> <xsl:value-of select="name/last"/> </li> </xsl:template>
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 the
xsl:param-variable
variable is only a default value for
the binding; when the template or stylesheet within which the
xsl: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-level
xsl: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 same
importance. 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:variable> <xsl:template match="para"> <fo:block font-size="{$para-font-size}"> <xsl:apply-templates/> </fo:block> </xsl:template>
As well as being allowed at the top-level, both
xsl: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 the
xsl: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 both
xsl:call-template
and xsl:apply-templates
.
The value of the parameter is specified in the same way as for
xsl: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
or
xsl: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 a
numbered-block
with an argument to control the format of
the number.
<xsl:template name="numbered-block"> <xsl:param-variable name="format">1. </xsl:param-variable> <xsl:number format="{$format}"/> <fo:block><xsl:apply-templates/></fo:block> </xsl:template> <xsl:template match="appendix/title"> <xsl:call-template name="numbered-block"> <xsl:param name="format">A. </xsl:param> </xsl:call-template> </xsl:template>
The xsl:message
instruction sends a message in a way
that is dependent on the XSLT processor. The content of the
xsl:message
instruction is a template. The
xsl: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.
XSLT provides two mechanisms to combine stylesheets:
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 an
href
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="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</xsl:attribute> </xsl:attribute-set> </xsl:stylesheet>
Definitions and template rules in the importing stylesheet are defined to be more important 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.
An XSLT stylesheet may include another XSLT stylesheet using an
xsl: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 existing
xsl: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?
Normally an XSLT stylesheet is a complete XML document with the
xsl:stylesheet
element as the document element. However an XSLT
stylesheet may also be embedded in another resource. Two forms of
embedding are possible:
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:
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 the
xsl:stylesheet
element.
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="#id(style1)"?> <!DOCTYPE doc SYSTEM "doc.dtd"> <doc> <head> <xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0" id="style1"> <xsl:import href="doc.xsl"/> <xsl:template match="id(foo)"> <fo:block font-weight="bold"><xsl:apply-templates/></fo:block> </xsl:template> </xsl:stylesheet> </head> <body> <para id="foo"> ... </para> </body> </doc>
NOTE: Thetype
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.
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 a
result-elements
parameter entity listing the allowed
result element types. For example:
<!ENTITY % result-elements " | fo:inline-sequence | fo:block ">
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.
<!ENTITY % char-instructions " | xsl:apply-templates | xsl:call-template | xsl:apply-imports | xsl:for-each | xsl:value-of | xsl:copy-of | xsl:number | xsl:choose | xsl:if | xsl:text | xsl:copy | xsl:variable | xsl:message "> <!ENTITY % instructions " %char-instructions; | xsl:pi | xsl:comment | xsl:element | xsl:attribute | xsl:use "> <!ENTITY % char-template " (#PCDATA %char-instructions;)* "> <!ENTITY % template " (#PCDATA %instructions; %result-elements;)* "> <!-- Used for attribute values that are URIs.--> <!ENTITY % URI "CDATA"> <!-- Used for attribute values that are patterns.--> <!ENTITY % pattern "CDATA"> <!-- Used for attribute values that are expressions.--> <!ENTITY % expr "CDATA"> <!-- Used for an attribute value that consists of a single character.--> <!ENTITY % char "CDATA"> <!-- Used for attribute values that are a priority. --> <!ENTITY % priority "NMTOKEN"> <!ENTITY % space-att "xml:space (default|preserve) #IMPLIED"> <!ENTITY % top-level " (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)*) "> <!ELEMENT xsl:stylesheet %top-level;> <!ELEMENT xsl:transform %top-level;> <!ATTLIST xsl:stylesheet result-ns NMTOKEN #IMPLIED default-space (preserve|strip) "preserve" indent-result (yes|no) "no" id ID #IMPLIED xmlns:xsl CDATA #FIXED "http://www.w3.org/XSL/Transform/1.0" %space-att; > <!ELEMENT xsl:import EMPTY> <!ATTLIST xsl:import href %URI; #REQUIRED> <!ELEMENT xsl:include EMPTY> <!ATTLIST xsl:include href %URI; #REQUIRED> <!ELEMENT xsl:strip-space EMPTY> <!ATTLIST xsl:strip-space elements NMTOKENS #REQUIRED> <!ELEMENT xsl:preserve-space EMPTY> <!ATTLIST xsl:preserve-space elements NMTOKENS #REQUIRED> <!ELEMENT xsl:key EMPTY> <!ATTLIST xsl:key name NMTOKEN #REQUIRED match %pattern; #REQUIRED use %expr; #REQUIRED > <!ELEMENT xsl:functions (#PCDATA)> <!ATTLIST xsl:functions ns NMTOKEN #REQUIRED code CDATA #IMPLIED archive CDATA #IMPLIED > <!ELEMENT xsl:locale EMPTY> <!ATTLIST xsl:locale name NMTOKEN #IMPLIED decimal-separator %char; "." grouping-separator %char; "," infinity CDATA "∞" minus-sign %char; "-" NaN CDATA "�" percent %char; "%" per-mill %char; "‰" zero-digit %char; "0" digit %char; "#" pattern-separator %char; ";" > <!ELEMENT xsl:template (#PCDATA %instructions; %result-elements; | xsl:param-variable)* > <!ATTLIST xsl:template match %pattern; #IMPLIED name NMTOKEN #IMPLIED priority %priority; #IMPLIED mode NMTOKEN #IMPLIED %space-att; > <!ELEMENT xsl:value-of EMPTY> <!ATTLIST xsl:value-of select %expr; #REQUIRED > <!ELEMENT xsl:copy-of EMPTY> <!ATTLIST xsl:copy-of select %expr; #REQUIRED> <!ELEMENT xsl:number EMPTY> <!ATTLIST xsl:number level (single|multi|any) "single" count CDATA #IMPLIED from CDATA #IMPLIED expr %expr; #IMPLIED format CDATA '1' xml:lang NMTOKEN #IMPLIED letter-value (alphabetic|other) #IMPLIED digit-group-sep CDATA #IMPLIED n-digits-per-group NMTOKEN #IMPLIED sequence-src %URI; #IMPLIED > <!ELEMENT xsl:apply-templates (xsl:sort|xsl:param)*> <!ATTLIST xsl:apply-templates select %expr; "node()" mode NMTOKEN #IMPLIED > <!ELEMENT xsl:apply-imports EMPTY> <!-- xsl:sort cannot occur after any other elements or any non-whitespace character --> <!ELEMENT xsl:for-each (#PCDATA %instructions; %result-elements; | xsl:sort)* > <!ATTLIST xsl:for-each select %expr; #REQUIRED %space-att; > <!ELEMENT xsl:sort EMPTY> <!ATTLIST xsl:sort select %expr; "." lang CDATA #IMPLIED data-type (text|number) "text" order (ascending|descending) "ascending" case-order (upper-first|lower-first) #IMPLIED > <!ELEMENT xsl:if %template;> <!ATTLIST xsl:if test %expr; #REQUIRED %space-att; > <!ELEMENT xsl:choose (xsl:when+, xsl:otherwise?)> <!ATTLIST xsl:choose %space-att;> <!ELEMENT xsl:when %template;> <!ATTLIST xsl:when test %expr; #REQUIRED %space-att; > <!ELEMENT xsl:otherwise %template;> <!ATTLIST xsl:otherwise %space-att;> <!ELEMENT xsl:attribute-set (xsl:attribute|xsl:use)*> <!ATTLIST xsl:attribute-set name NMTOKEN #REQUIRED > <!ELEMENT xsl:call-template (xsl:param)*> <!ATTLIST xsl:call-template name NMTOKEN #REQUIRED > <!ELEMENT xsl:param %template;> <!ATTLIST xsl:param name NMTOKEN #REQUIRED expr %expr; #IMPLIED > <!ELEMENT xsl:variable %template;> <!ATTLIST xsl:variable name NMTOKEN #REQUIRED expr %expr; #IMPLIED > <!ELEMENT xsl:param-variable %template;> <!ATTLIST xsl:param-variable name NMTOKEN #REQUIRED expr %expr; #IMPLIED > <!ELEMENT xsl:text (#PCDATA)> <!ELEMENT xsl:pi %char-template;> <!ATTLIST xsl:pi name CDATA #REQUIRED %space-att; > <!ELEMENT xsl:element %template;> <!ATTLIST xsl:element name CDATA #REQUIRED namespace CDATA #IMPLIED %space-att; > <!ELEMENT xsl:attribute %char-template;> <!ATTLIST xsl:attribute name CDATA #REQUIRED namespace CDATA #IMPLIED %space-att; > <!ELEMENT xsl:use EMPTY> <!ATTLIST xsl:use attribute-set NMTOKEN #REQUIRED> <!ELEMENT xsl:comment %char-template;> <!ATTLIST xsl:comment %space-att;> <!ELEMENT xsl:copy %template;> <!ATTLIST xsl:copy %space-att;> <!ELEMENT xsl:message %template;> <!ATTLIST xsl:message %space-att;>
The following is a simple but complete stylesheet.
<?xml version='1.0'?> <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/> </fo:queue> </fo:basic-page-sequence> </xsl:template> <xsl:template match="title"> <fo:block font-weight="bold"> <xsl:apply-templates/> </fo:block> </xsl:template> <xsl:template match="p"> <fo:block> <xsl:apply-templates/> </fo:block> </xsl:template> <xsl:template match="emph"> <fo:inline-sequence font-style="italic"> <xsl:apply-templates/> </fo:inline-sequence> </xsl:template> </xsl:stylesheet>
With the following source document
<doc> <title>An example</title> <p>This is a test.</p> <p>This is <emph>another</emph> test.</p> </doc>
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:block> <fo:block>This is a test.</fo:block> <fo:block>This is <fo:inline-sequence font-style="italic">another</fo:inline-sequence> test.</fo:block> </fo:queue> </fo:basic-page-sequence>
This is an example of using XSLT to create an XHTML document (see [XHTML]). The following stylesheet:
<?xml version="1.0"?> <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="/"> <html> <head> <title>Sales Results By Division</title> </head> <body> <table border="1"> <tr> <th>Division</th> <th>Revenue</th> <th>Growth</th> <th>Bonus</th> </tr> <xsl:apply-templates/> </table> </body> </html> </xsl:template> <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> </xsl:stylesheet>
with the following input document
<?xml version="1.0"?> <sales> <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> </sales>
would produce the following result
<?xml version="1.0"?> <html xmlns="http://www.w3.org/Profiles/xhtml1-transitional"> <head> <title>Sales Results By Division</title> </head> <body> <table border="1"> <tr> <th>Division</th> <th>Revenue</th> <th>Growth</th> <th>Bonus</th> </tr> <tr> <td><em>North</em></td> <td>10</td> <td>9</td> <td>7</td> </tr> <tr> <td><em>West</em></td> <td>6</td> <td>-1.5</td> <td>2</td> </tr> <tr> <td><em>South</em></td> <td>4</td> <td>3</td> <td>4</td> </tr> </table> </body> </html>
The following have contributed to authoring this draft:
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)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 into
id()
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 the
position()
and last()
functions and numeric
expressions inside []
.
Counters have been removed. An expr
attribute has been
added to xsl:number
which in conjunction with the
position()
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 by
xsl: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 to
xsl:element
and xsl:attribute
.