Copying the Context Node with xsl:copy
The xsl:copy element copies the source node into the output tree.However, the contents
of the xsl:copy element are a template that can select these things to be copied as
well. This is often useful when transforming a document from one markup vocabulary
to the same or a closely related markup vocabulary.
<xsl:template match=”ATOM”>
<xsl:copy>
<B><xsl:value-of select=”.”/></B>
</xsl:copy>
</xsl:template>
One useful template xsl:copy makes possible is the identity transformation; that
is, a transformation from a document into itself. Such a transformation looks like
this:
<xsl:template
match=”*|@*|comment()|processing-instruction()|text()”>
<xsl:copy>
<xsl:apply-templates select=”*|@*|comment()|processing-instruction()|text()”/>
</xsl:copy>
</xsl:template>
a style sheet that strips comments from a document,
leaving the document otherwise untouched. It simply omits the comment() node
test from the match and select attribute values in the identity transformation.
xsl:copy only copies the source node. However, it does not automatically copy the
node’s attributes, children, or namespaces. In other words, it is a shallow copy. To
deep copy the entire node including all its attributes and descendants, use
xsl:copy-of. The select attribute of xsl:copy-of chooses the nodes to be
copied.For example, Listing 15-15 is a style sheet that uses xsl:copy-of to strip
out elements without melting points from the periodic table by copying only ATOM
elements that have MELTING_POINT children.
<?xml version=”1.0”?>
<xsl:stylesheet version=”1.0”
xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”>
<xsl:template match=”/PERIODIC_TABLE”>
<PERIODIC_TABLE>
<xsl:apply-templates select=”ATOM”/>
</PERIODIC_TABLE>
</xsl:template>
<xsl:template match=”ATOM”>
<xsl:apply-templates select=”MELTING_POINT”/>
</xsl:template>
<xsl:template match=”MELTING_POINT”>
<xsl:copy-of select=”..”/>
</xsl:template>
</xsl:stylesheet>
Counting Nodes with xsl:number
The xsl:number element inserts a formatted integer into the output document.
The value of the integer is given by the value attribute. This contains a number,
which is rounded to the nearest integer, then formatted according to the value of
the format attribute.
<?xml version=”1.0”?>
<xsl:stylesheet version=”1.0”
xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”>
<xsl:template match=”PERIODIC_TABLE”>
<HTML>
<HEAD><TITLE>The Elements</TITLE></HEAD>
<BODY>
<TABLE>
<TR><xsl:apply-templates select=”ATOM”/></TR>
</TABLE>
</BODY>
</HTML>
</xsl:template>
<xsl:template match=”ATOM”>
<TD><xsl:number value=”ATOMIC_NUMBER”/></TD>
<TD><xsl:value-of select=”NAME”/></TD>
</xsl:template>
</xsl:stylesheet>
Default numbers
If you use the value attribute to calculate the number, that’s all you need. However,
if the value attribute is omitted, the position of the current node in the source tree
is used as the number.
the default value calculated by xsl:
number is the position of the node among other sibling nodes of the same type
This is not the same as the number returned by the
position() function, which only calculates position relative to other nodes in
the context node list
You can change what xsl:number counts
using these three attributes
? level
? count
? from
Number to string conversion
four attributes of xsl:number
? format
? letter-value
? grouping-separator
? grouping-size
The format attribute
You can adjust the numbering style used by xsl:number using the format
attribute. This attribute generally has one of the following values:
? i—The lowercase Roman numerals i, ii, iii, iv, v, vi, . . .
? I—The uppercase Roman numerals I, II, III, IV, V, VI, . . .
? a—The lowercase letters a, b, c, d, e, f, . . .
? A—The uppercase letters A, B, C, D, E, F, . . .
You can specify decimal numbering with leading zeros by including the number of
leading zeros you want in the format attribute. For example, setting format=”01”
produces the sequence 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, . . . .
The letter-value attribute
The letter-value attribute distinguishes between letters interpreted as numbers
and letters interpreted as letters. For instance, if you want to use format=”I” to
start the sequence I, J, K, L, M, N, . . . instead of I, II, III, IV, V, VI, . . ., you would set
the letter-value attribute to the keyword alphabetic. The keyword traditional
specifies a numeric sequence
Grouping attributes
The grouping-separator attribute specifies the grouping separator used between
groups of digits. The grouping-size attribute specifies the number of digits used
in a group, as in the following example:
<xsl:number grouping-separator=” “ grouping-SIZE=”3”/>
Sorting Output
The xsl:sort element sorts the output nodes into a different order than they were
generated in. An xsl:sort element appears as a child of an xsl:apply-templates
element or xsl:for-each element. The select attribute of the xsl:sort element
defines the key used to sort the element’s output by xsl:apply-templates or
xsl:for-each.
By default, sorting is performed in alphabetical order of the keys. If more than one
xsl:sort element is present in a given xsl:apply-templates or xsl:for-each
element, the elements are sorted first by the first key, then by the second key, and
so on. If any elements still compare equally, they are output in the order they
appear in the source document.
<xsl:apply-templates>
<xsl:sort select=”ATOMIC_NUMBER”/>
</xsl:apply-templates>
You can, however, adjust the order of the sort by setting the optional data-type
attribute to the value number, as in this element:
<xsl:sort data-type=”number” select=”ATOMIC_NUMBER”/>
You can change the order of the sort from the default ascending order to descending
by setting the order attribute to descending, like this:
<xsl:sort order=”descending”
data-type=”number”
select=”ATOMIC_NUMBER”/>
The lang attribute can set
the language of the keys. The value of this attribute should be an ISO 639 language
code such as en for English.The lang attribute is ignored if data-type is
number.
Finally, you can set the case-order attribute to one of the two values, upperfirst
or lower-first, to specify whether uppercase letters sort before lowercase
letters or vice versa. The default depends on the language.
Modes
You need two different rules
that both apply to the ATOM element at different places in the document. The solution
is to give each of the different rules a mode attribute. Then you can choose
which template to apply by setting the mode attribute of the xsl:apply-templates
element. Listing 15-19 demonstrates.
<?xml version=”1.0”?>
<xsl:stylesheet version=”1.0”
xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”>
<xsl:template match=”/PERIODIC_TABLE”>
<HTML>
<HEAD><TITLE>The Elements</TITLE></HEAD>
<BODY>
<H2>Table of Contents</H2>
<UL>
<xsl:apply-templates select=”ATOM” mode=”toc”/>
</UL>
<H2>The Elements</H2>
<xsl:apply-templates select=”ATOM” mode=”full”/>
</BODY>
</HTML>
</xsl:template>
<xsl:template match=”ATOM” mode=”toc”>
<LI><A>
<xsl:attribute name=”HREF”>#<xsl:value-of
select=”SYMBOL”/></xsl:attribute>
<xsl:value-of select=”NAME”/>
</A></LI>
</xsl:template>
<xsl:template match=”ATOM” mode=”full”>
<H3><A>
<xsl:attribute name=”NAME”>
<xsl:value-of select=”SYMBOL”/>
</xsl:attribute>
<xsl:value-of select=”NAME”/>
</A></H3>
<P>
<xsl:value-of select=”.”/>
</P>
</xsl:template>
</xsl:stylesheet>
The default template rule for nodes preserves modes. That is, for every mode n you
declare in your style sheet, the XSLT processor adds one template rule that applies
specifically to that mode and looks like this:
<xsl:template match=”*|/” mode=”n”>
<xsl:apply-templates mode=”n”/>
</xsl:template>
Defining Constants with xsl:variable
The xsl:variable element defines a named string for use elsewhere in the
style sheet via an attribute value template. It has a single attribute, name, which
provides a name by which the variable can be referred to. The contents of the
xsl:variable element provide the replacement text.
<xsl:variable name=”copy04”>
Copyright 2004 Elliotte Rusty Harold
</xsl:variable>
To access the value of this variable, you prefix a dollar sign to the name of the variable.
To insert this in an attribute, use an attribute value template. For example:
<BLOCK COPYRIGHT=”{$copy04}”>
</BLOCK>
An xsl:value-of element can insert the variable’s replacement text into the output
document as text:
<xsl:value-of select=”$copy04”/>
The contents of the xsl:variable element can contain markup including other
XSLT instructions. This means that you can calculate the value of a variable based
on other information, including the value of other variables. However, a variable
may not refer to itself recursively, either directly or indirectly.
xsl:variable elements can either be top-level children of the xsl:stylesheet
root element or they can be included inside template rules. A variable present at
the top level of a style sheet can be accessed anywhere in the style sheet. It’s a
global variable. By contrast, a variable that’s declared inside a template rule is only
accessible by its following sibling elements and their descendants (the scope of the
variable). It’s a local variable. That is, it only applies inside that one template rule. It
is local to the template. Local variables override global variables with the same
name. Local variables can also override other local variables. In the event of a conflict
between two variables with the same name, the closest local variable with the
same name is used.
Unlike variables in traditional programming languages such as Java, XSLT variables
may not be changed. After the value of a variable has been set, it cannot be
changed. It can be shadowed by another variable with the same name in a more
local scope, but its own value is fixed. An XSLT variable is more like an algebraic
variable than a programming language variable.