XML is not a fixed tag set (like HTML)
XML by itself has no (application) semantics
A generic XML processor has no idea what is "meant" by the XML
XML markup does not (usually) include formatting information
The information in an XML document may not be in the form in which it is desired to present it
Therefore there must be something in addition to the XML document that provides information on how to present or otherwise process the XML
Contrary to when style information is hard-coded into the content, separation of style from content allows for the same data to be presented in different ways. This enables:
reuse of fragments of data: the same content should look different in different contexts
multiple output formats: different media (paper, online), different sizes (manuals, reports), different classes of output devices (workstations, hand-held devices)
styles tailored to the reader's preference (e.g., accessibility): print size, color, simplified layout for audio readers
standardized styles: corporate stylesheets can be applied to the content at any time
freedom from style issues for content authors: technical writers needn't be concerned with layout issues because the correct style can be applied later
A stylesheet specifies the presentation of XML information using two basic categories of techniques:
Description of how to present the (possibly transformed) data includes three levels of formatting information:
The full XSL language logically consists of three component languages which are described in three W3C (World Wide Web Consortium) Recommendations:
XPath: XML Path Language--a language for referencing specific parts of an XML document
XSLT: XSL Transformations--a language for describing how to transform one XML document (represented as a tree) into another
XSL: Extensible Stylesheet Language--XSLT plus a description of a set of Formatting Objects and Formatting Properties
An XSLT "stylesheet" transforms the input (source) document's tree into a structure called a result tree consisting of result objects
The result tree's structure is that of an XML document, and its objects correspond to elements with attributes
The result tree's structure and "tag set" can match that of any XML document or doctype. In particular, the result tree could be:
result tree is easily written out as an HTML document
result tree is easily written out as an XML document in this other doctype (for some further application-specific processing)
result tree's structure (and element and attribute names) matches the set of formatting objects and formatting properties defined by the (non-transformation) part of XSL
Serialization of the result tree is not necessary for further processing of the result tree.
An XSL stylesheet basically consists of a set of templates
Each template "matches" some set of elements in the source tree and then describes the contribution that the matched element makes to the result tree
Generally, elements in a stylesheet in the "xsl" namespace are part of the XSLT language, and non-xsl elements within a template are what get put into the result tree
Transformation is independent of the target result type
Most people are more familiar with HTML so many of the examples in this tutorial use HTML
The XSL implementation in IE5 is incomplete. The examples in this tutorial will not work in IE5
The techniques apply equally well to XSL Formatting Objects or other tag sets
XSLT is a tree-to-tree transformation process
Serialization may vary depending on the selected output method
There is a distinction between HTML element names and HTML
XSLT Stylesheets are XML documents; namespaces (http://www.w3.org/TR/REC-xml-names) are used to identify semantically significant elements.
Most stylesheets are stand-alone documents rooted at <xsl:stylesheet> or <xsl:transform>. It is possible to have "single template" stylesheet/documents.
<xsl:stylesheet> and <xsl:transform> are completely synonymous.
Note that it is the mapping from namespace abbreviation to URI that is important, not the literal namespace abbreviation "xsl:" that is used most commonly.
Figure 3. Document as Stylesheet
<html xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<head>
<title>Silly Example</title>
</head>
<body>
<h1>Silly Example</h1>
<p>You'd probably use extension elements, or somthing
more interesting in real life: 3+4 is <xsl:value-of select="3+4"/>.
</p>
</body>
</html>
This is a simple stylesheet that transforms source <para> and <emphasis> elements into HTML:
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="para">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="emphasis">
<i><xsl:apply-templates/></i>
</xsl:template>
</xsl:stylesheet>
With this stylesheet, the following XML document:
<?xml version='1.0'?>
<para>This is a <emphasis>test</emphasis>.</para>
Would be transformed into:
<?xml version="1.0" encoding="utf-8"?>
<p>This is a <i>test</i>.</p>
Note that this has been serialized as XML.
Most templates have the following form:
<xsl:template match="emphasis"> <i><xsl:apply-templates/></i> </xsl:template>
One critical capability of a stylesheet language is to locate source elements to be styled. CSS, for example, does this with "selectors." FOSIs do it with "e-i-c's", elements in context. XSLT does it with "match patterns" defined by the XML Path Language (XPath) (http://www.w3.org/TR/xpath).
Two things to remember about XPath expressions:
Matches all <para> children in the current context
Matches all <emphasis> elements that have a parent of <para>
Matches the root of the document
Matches all <emphasis> elements that have an ancestor of <para>
Matches the first <para> child of all the <section> children in the current context
Matches all <title> elements anywhere in the document
Matches all <title> elements that are descendants of the current context
Matches <note> elements that have <section> grandparents.
Matches <stockquote> elements that have a "symbol" attribute
Matches <stockquote> elements that have a "symbol" attribute with the value "XXXX"
Matches <emphasis> or <strong> elements
The XPath pattern syntax is described formally in the XPath specification. Here we're going to look at the syntax in abstract, but less formal terms:
The formal syntax is made more complicated by the fact that it must describe both the abbreviated and unabbreviated syntaxes
Node tests are most frequently element names, but other node tests are possible:
Matches <name> element nodes
Matches any element node
Matches <name> element nodes in the specified namespace
Matches any element node in the specified namespace
Matches comment nodes
Matches text nodes
Matches processing instructions
Matches processing instructions with the specified target (<?target ...?>
Matches any node
Predicates occur after the node test in square brackets. A wide range of expressions are possible.
Most node tests return nodes in document order, only the tests which select ancestor or preceding elements return nodes in reverse document order. The practical result of this is that the "first" node is almost always the one closest to the context node, although parenthesis can change the effective order.
Matches the last node
Matches even nodes
Matches the element(s) with id attributes whos value is "foo"
Matches elements that don't have an id attribute
Match <author> elements that have <firstname> children with the content "Norman".
Match "Norman" without regard to leading and trailing space.
Predicate expressions can be more-or-less arbitrarily complex.
The axis of a node test determines what general category of nodes may be considered for the following node test. There are thirteen axes:
Ancestors of the current node
Ancestors, including the current node
Attributes of the current node (abbreviated "@")
Children of the current node (the default axis)
Descendants of the current node
Descendants, including the current node (abbreviated "//")
Elements which occur after the current node, in document order
Elements which occur before the current node, in document order (returned in reverse-document order)
The namespace nodes of the current node
The parent of the current node (abbreviated "..")
The current node (abbreviated ".")
The following graphic, courtesy of Crane Softwrights, demonstrates the axes graphically:
Now that we've seen the unabbreviated syntax, let's look at a few more patterns
One model for applying style is to allow the process to run recursively, driven primarily by the document. A series of templates is created, such that there is a template to match each context, then these templates are recursively applied starting at the root of the document.
There are two obstacles to overcome when using the recursive model, how to arbitrate between multiple patterns that match and how to process the same nodes in different contexts.
Figure 4. recursive.xml
<doc>
<para>This is a <emphasis>test</emphasis>.
<emphasis>Nested <emphasis>emphasis</emphasis></emphasis>.</para>
</doc>
Figure 5. recursive.xsl
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="doc">
<html><head><title>A Document</title></head>
<body><xsl:apply-templates/></body></html>
</xsl:template>
<xsl:template match="para">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="emphasis">
<i><xsl:apply-templates/></i>
</xsl:template>
<xsl:template match="emphasis/emphasis">
<b><xsl:apply-templates/></b>
</xsl:template>
</xsl:stylesheet>
Figure 6. recursive.html
<html>
<head>
<title>A Document</title>
</head>
<body>
<p>This is a <i>test</i>.
<i>Nested <b>emphasis</b></i>.</p>
</body>
</html>
The problem of multiple patterns that match is handled by conflict resolution:
Matching templates from imported modules are not considered if there is a matching template in the current module
Matching templates with a lower priority are not considered. The default priority is determined as follows:
Unqualified child or attribute names have a priority of 0.
Processing-instructions with a target have a priority of 0.
A namespace-qualified "*" child or attribute name has a priority of -0.25.
An unqualified "*" has a priority of -0.5
Any other template has a default priority of 0.5
Template priority may be specified explicitly with the priority attribute on <xsl:template>
It is technically an error if the conflict resolution process yields more than one template, however, XSLT processors may (silently) recover from this error by selecting the template that occurs last in the stylesheet.
Effectively, this means that stylesheet template order is the final arbiter.
Now we have an algorithm for selecting exactly which pattern matches, but what happens if the same elements must be processed in multiple contexts? This happens, for example, when dealing with cross references, automatic tables of contents, and multiple views of the same data.
Consider the following example:
Figure 7. modes.xml
<?xml version='1.0'?>
<chapter id="foo"><title>Chapter Title</title>
<para>This chapter is self-referential:
<xref linkend="foo"/>.</para>
</chapter>
And a stylesheet that produces:
Figure 8. modes.html
<h2>Chapter Title</h2>
<p>This chapter is self-referential:
<i>Chapter Title</i>.</p>
The chapter title must be processed twice, once to produce the title and once to produce the cross reference.
There is no dynamic mechanism for adjusting template priority, but there is a mechanism for selecting specific sets of templates. That mechanism is called "modes".
Without modes, you always get the same template:
Figure 9. modes-broken.xsl
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="chapter/title">
<h2><xsl:apply-templates/></h2>
</xsl:template>
<xsl:template match="xref">
<xsl:variable name="linkend" select="@linkend"/>
<xsl:apply-templates select="//*[@id=$linkend]/title"/>
</xsl:template>
<xsl:template match="para">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="emphasis">
<i><xsl:apply-templates/></i>
</xsl:template>
</xsl:stylesheet>
Figure 10. modes-broken.html
<?xml version="1.0" encoding="utf-8"?>
<h2>Chapter Title</h2>
<p>This chapter is self-referential:
<h2>Chapter Title</h2>.</p>
Figure 11. modes.xsl
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html"/>
<xsl:template match="chapter/title">
<h2><xsl:apply-templates/></h2>
</xsl:template>
<xsl:template match="chapter/title" mode="crossref">
<i><xsl:apply-templates/></i>
</xsl:template>
<xsl:template match="xref">
<xsl:variable name="linkend" select="@linkend"/>
<xsl:apply-templates select="//*[@id=$linkend]/title"
mode="crossref"/>
</xsl:template>
<xsl:template match="para">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="emphasis">
<i><xsl:apply-templates/></i>
</xsl:template>
</xsl:stylesheet>
Figure 12. modes.html
<h2>Chapter Title</h2>
<p>This chapter is self-referential:
<i>Chapter Title</i>.</p>
The other model for applying style is to select each action procedurally. A series of templates is created, such that each template explicitly selects and processes the necessary elements.
Figure 13. foreach.xml
<?xml version='1.0'?>
<table>
<row><entry>a1</entry><entry>a2</entry></row>
<row><entry>b1</entry><entry>b2</entry></row>
<row><entry>c1</entry><entry>c2</entry></row>
</table>
Figure 14. foreach.xsl
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="table">
<table>
<xsl:for-each select="row">
<tr>
<xsl:for-each select="entry">
<td><xsl:apply-templates/></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Figure 15. foreach.html
<table>
<tr>
<td>a1</td><td>a2</td>
</tr>
<tr>
<td>b1</td><td>b2</td>
</tr>
<tr>
<td>c1</td><td>c2</td>
</tr>
</table>
Challenge: rewrite this stylesheet in recursive terms
Figure 16. namedtemplate.xml
<chapter>
<warning>
<para>Using a damaged extension cord may cause a fire.</para>
</warning>
<caution>
<para>Freshly brewed coffee is hot.</para>
</caution>
</chapter>
Figure 17. namedtemplate.xsl
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template name="admonition">
<xsl:param name="type">Warning</xsl:param>
<table border="1">
<tr><th><xsl:value-of select="$type"/>:</th></tr>
<tr><td><xsl:apply-templates/></td></tr>
</table>
</xsl:template>
<xsl:template match="warning">
<xsl:call-template name="admonition"/>
</xsl:template>
<xsl:template match="caution">
<xsl:call-template name="admonition">
<xsl:with-param name="type">Caution</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template match="para">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="emphasis">
<i><xsl:apply-templates/></i>
</xsl:template>
</xsl:stylesheet>
Figure 18. namedtemplate.html
<table border="1">
<tr>
<th>Warning:</th>
</tr>
<tr>
<td>
<p>Using a damaged extension cord may cause a fire.</p>
</td>
</tr>
</table>
<table border="1">
<tr>
<th>Caution:</th>
</tr>
<tr>
<td>
<p>Freshly brewed coffee is hot.</p>
</td>
</tr>
</table>
Any element in a template rule that is not in the XSL (or other extension) namespace is copied literally to the result tree
The content of <xsl:text> elements is copied directly to the result tree; whitespace is preserved by default
<xsl:text>Literal result text</xsl:text>
Inserts the value of an expression into the result tree, converting it to a string first if necessary
<xsl:value-of select="$count + 1"/>
Copies the current node or, in the case of xsl:copy-of, the selected nodes, into the result tree without first converting them to a string
<xsl:copy-of select="title"/>
Instantiates the named element
... <xsl:param name="header">h3</xsl:param> ... <xsl:element name="{$header}"> <xsl:apply-templates/> </xsl:element>
Adds the named attribute to the nearest containing element
<table> <xsl:if test="@pgwide='1'"> <xsl:attribute name="width">100%</xsl:attribute> </xsl:if> ... </table>
Simple conditional (no "else")
<xsl:if test="$somecondition"> <xsl:text>this text only gets used if $somecondition is true()</xsl:text> </xsl:if>
Select among alternatives with <xsl:when> and <xsl:otherwise>
<xsl:choose> <xsl:when test="$count > 2"><xsl:text>, and </xsl:text></xsl:when> <xsl:when test="$count > 1"><xsl:text> and </xsl:text></xsl:when> <xsl:otherwise><xsl:text> </xsl:text></xsl:otherwise> </xsl:choose>
To report errors, use <xsl:message>.
<xsl:message> <xsl:text>Error: no ID found for linkend: </xsl:text> <xsl:value-of select="@linkend"/> <xsl:text>.</xsl:text> </xsl:message>
<xsl:variable> allows you to associate a variable with a string, node list, or result tree fragment.
Variables are "single assignment" (no side effects)
Variables are lexically scoped
Variables assigned inside a conditional only apply inside that conditional. This is rarely correct:
<xsl:if test="$foo"> <xsl:variable name="bar">...</xsl:variable> </xsl:if>
Usually, you want to put the conditional inside the variable
<xsl:variable name="bar"> <xsl:if test="$foo">...</xsl:if> </xsl:variable>
After variables (or parameters) have been declared, they can be used in two places:
In XSL element attributes that expect an expression. These are summarized in the following table:
In attribute value templates; attribute value templates have the form "{$variable}". They are allowed in the following places:
To insert a literal "{" character in a context where attribute value templates are expanded, use "{{".
The <xsl:number> element performs two functions:
It evaluates a numeric expression and converts the result into a formatted string:
<xsl:number value="3" format="A. "/> <xsl:number value="count(listitem)" format="01"/>
It counts elements in the source tree and converst the result into a formatted string:
<xsl:number count="listitem" format="i. "/> <xsl:number count="chapter" from="book" level="any" format="1. "/> <xsl:number count="h1|h2|h3" level="multiple" from="chapter|appendix" format="1."/>
The details of number to string conversion is spelled out in great detail in Section 7.7.1 (http://www.w3.org/TR/xslt.html#convert) of the XSLT Recommendation (http://www.w3.org/TR/xslt.html). See also, <xsl:decimal-format> and the Java JDK 1.1 DecimalFormat (http://java.sun.com/products/jdk/1.1/docs/api/java.text.DecimalFormat.html) class.
The <xsl:sort> element sorts a set of nodes according to the criteria specified:
<xsl:apply-templates select="row"> <xsl:sort data-type="number" select="entry[2]"/> </xsl:apply-templates>
It can appear as a child of <xsl:apply-templates> or <xsl:for-each>. It can also be nested.
Figure 19. sort.xml
<doc>
<para>Here's a table of sales:</para>
<table>
<row><cell>3000</cell><cell>Widgets 'R' Us</cell></row>
<row><cell>2400</cell><cell>Widget Design and Implementation</cell></row>
<row><cell>10000</cell><cell>Widgets for Dummies</cell></row>
<row><cell>101</cell><cell>101 Uses for a Dead Widget</cell></row>
</table>
</doc>
Figure 20. sort.xsl
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:import href="element.xsl"/>
<xsl:template match="table">
<xsl:if test="@id"><a name="{@id}"/></xsl:if>
<table>
<xsl:apply-templates select="row">
<xsl:sort data-type="number" select="./cell[1]"/>
</xsl:apply-templates>
</table>
</xsl:template>
</xsl:stylesheet>
Figure 21. sort.html
<p>Here's a table of sales:</p>
<table>
<tr>
<td>101</td><td>101 Uses for a Dead Widget</td>
</tr>
<tr>
<td>2400</td><td>Widget Design and Implementation</td>
</tr>
<tr>
<td>3000</td><td>Widgets 'R' Us</td>
</tr>
<tr>
<td>10000</td><td>Widgets for Dummies</td>
</tr>
</table>
XSL = XSLT + vocabulary of FOs and properties
XSL defines a powerful set of formatting objects
XSL uses (and extends) a set of Common Formatting Properties developed jointly with the CSS&FP (Cascading Style Sheet and Formatting Property) Working Group
When a result tree uses this standardized set of formatting objects and properties, then an XSL-compliant formatter can process that result tree to produce the specified output
<?xml version="1.0" encoding="utf-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
...
<fo:page-sequence>
<fo:flow>
<fo:block font-size="18pt" font-weight="bold"
text-align="centered">
Preface
</fo:block>
<fo:block font-size="12pt" space-before="1pc"
text-align="justified">
This is a simple test document. It shows a
<fo:inline font-style="italic">partial</fo:inline>
fo-result tree (page layout missing).
</fo:block>
</fo:flow>
</fo:page-sequence>
...
</fo:root>
<xsl:template match="chapter">
<fo:flow>
<xsl:apply-templates/>
</fo:flow>
</xsl:template>
<xsl:template match="chapter/title">
<fo:block font-size="18pt" font-weight="bold"
text-align="centered">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="para">
<fo:block font-size="12pt" space-before="1pc"
text-align="justified">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="emphasis">
<fo:inline font-style="italic">
<xsl:apply-templates/>
</fo:inline>
</xsl:template>
page-sequence--a major part (such as front or body) in which the basic page layout may differ from other parts
flow--a chapter- or section-like division within a page-sequence
block--a paragraph (or title or block quote, etc.)
inline--e.g., a font change within a paragraph
wrapper--a "transparent" object usable as either a block or inline object that has no effect other than to provide a place to hang inheritable properties
list FOs--list-block, list-item, list-item-label, list-item-body
graphic--references an external graphic object
table FOs--mostly analogous to the standard (CALS, OASIS, HTML) table models
XSL FO formatting capabilities in XSL 1.0 are approximately the union of:
Not included are complex page layouts (e.g., magazine and newspaper layout), complex layout-driven formatting (e.g., copyfitting and complex floats), and looseleaf pagination (change page production)
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
>
<xsl:include href="fo-root.xsl"/>
<xsl:template match="article">
<fo:page-sequence font-family="serif" font-size="12pt">
<xsl:apply-templates/>
</fo:page-sequence>
</xsl:template>
<xsl:template match="chapter">
<fo:flow>
<xsl:apply-templates/>
</fo:flow>
</xsl:template>
<xsl:template match="para">
<fo:block space-before="6pt">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="chapter/title">
<fo:block font-family="sans-serif" color="blue"
font-weight="bold" font-size="18pt"
space-after="0.5em">
<xsl:number level="multiple" count="chapter"/>
<xsl:text> </xsl:text>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="section/title">
<fo:block font-family="sans-serif"
font-weight="bold" font-size="16pt"
space-after="0.5em">
<xsl:number level="multiple" count="chapter|section"/>
<xsl:text> </xsl:text>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="article/title">
<fo:block font-family="sans-serif" font-size="24pt"
space-after="2pc">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
An <xsl:import> statement loads an auxilary stylesheet
<xsl:import href = uri-reference />
Templates imported from another stylesheet have a different import precedence.
An <xsl:include> statement performs a "textual include" of another stylesheet:
<xsl:include href = uri-reference />
Templates included from another stylesheet have the same import precedence and behave exactly as if they had been literally inserted where the <xsl:include> statement occurs.
XSLT has to handle whitespace in both the stylesheet and the source document in a reasonable and controllable way.
To deal with whitespace in the stylesheet, it employs the following rules:
The rules for whitespace in the source document are the same, with the exception that you can specify the default stripping rules with <xsl:preserve-space> and <xsl:strip-space>:
If a text node contains non-whitespace characters, it is preserved
If a text node occurs inside an element listed in <xsl:preserve-space>, it is preserved
If the nearest ancestor xml:space attribute has the value preserve, it is preserved
Otherwise it is stripped (discarded from the tree before any transformation begins)
The <xsl:preserve-space> element lists the source tree elements in which input whitespace is to be preserved.
<xsl:preserve-space elements = tokens />
Note that namespace:* and * can be used to incorporate all elements or all elements from a particular namespace by default.
The <xsl:strip-space> element lists the source tree elements in which input whitespace is to be discarded.
<xsl:strip-space elements = tokens />
Note that namespace:* and * can be used to incorporate all elements or all elements from a particular namespace by default.
XSLT is a tree-to-tree transformation. It isn't specifically the job of the XSLT processor to write out a text representation (serialization) of the tree. However, XSLT does allow the stylesheet author to suggest the desired serialization procedure:
The selection of namespace aliases is controlled by <xsl:namespace-alias>.
<xsl:output method = "xml" | "html" | "text" | qname-but-not-ncname version = nmtoken encoding = string omit-xml-declaration = "yes" | "no" standalone = "yes" | "no" doctype-public = string doctype-system = string cdata-section-elements = qnames indent = "yes" | "no" media-type = string />
The serialization method
The version of the serializer
The encoding to use, if possible
Do not output the <?xml ...?> declaration
Identify the result as a standalone document (in the XML sense)
The public identifier to use on the output <!DOCTYPE> declaration
The system identifier to use on the output <!DOCTYPE> declaration
A list of element names; the content of these element should be escaped with CDATA sections if possible
Add additional space to the serialized result tree for readability
The media type of the serialized result
Allows the stylesheet to alias one namespace prefix for another in the result tree
<xsl:namespace-alias stylesheet-prefix = prefix | "#default" result-prefix = prefix | "#default" />
Suppose that you have a stylesheet which customizes another stylesheet, perhaps changing the formatting of a few elements. Suppose that one of these elements is formatted by a complex template in the base stylesheet, and all you want to change is one small, special case. How can you do this?
The answer is with <xsl:apply-imports>:
... <xsl:import href="basestyle.xsl"/> ... <xsl:template match="table"> <xsl:choose> <xsl:when test="@role='something-special'"> <xsl:call-template name="special-table-handler"/> </xsl:when> <xsl:otherwise> <xsl:apply-imports/> </xsl:otherwise> </xsl:choose> </xsl:template>
Process the context node with the "next matching" pattern from an imported stylesheet.
<xsl:apply-imports/>
There are several more elements that can be used in creating the result tree:
The <xsl:attribute-set> element gives a name to a collection of attribute/value pairs.
<xsl:attribute-set name = qname use-attribute-sets = qnames> <!-- Content: xsl:attribute* --> </xsl:attribute-set>
A <xsl:comment> element inserts an XML comment into the result tree.
<xsl:comment> <!-- Content: template --> </xsl:comment>
A <xsl:processing-instruction> element inserts an XML processing instruction into the result tree.
<xsl:processing-instruction name = { ncname }> <!-- Content: template --> </xsl:processing-instruction>
Figure 22. attrset.xsl
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html"/>
<xsl:attribute-set name="table-cell-attrs">
<xsl:attribute name="align">left</xsl:attribute>
<xsl:attribute name="valign">top</xsl:attribute>
<xsl:attribute name="bordercolor">blue</xsl:attribute>
</xsl:attribute-set>
<xsl:template match="doc">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="table">
<xsl:if test="@id"><a name="{@id}"/></xsl:if>
<xsl:comment>Attributes created with xsl:attribute-set</xsl:comment>
<table border="1">
<xsl:apply-templates/>
</table>
</xsl:template>
<xsl:template match="head|cell">
<xsl:variable name="output-element">
<xsl:choose>
<xsl:when test="local-name(.)='head'">th</xsl:when>
<xsl:otherwise>td</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="{$output-element}" use-attribute-sets="table-cell-attrs">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="row">
<tr>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</tr>
</xsl:template>
<xsl:template match="link">
<a>
<xsl:attribute name="href">
<xsl:text>#</xsl:text>
<xsl:value-of select="@linkend"/>
</xsl:attribute>
<xsl:apply-templates/>
</a>
</xsl:template>
<xsl:template match="para">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="emphasis">
<i><xsl:apply-templates/></i>
</xsl:template>
</xsl:stylesheet>
Figure 23. attrset.html
<p>This is some paragraph of text. See
<a href="#foo">the table</a>.</p>
<a name="foo"></a><!--Attributes created with xsl:attribute-set-->
<table border="1">
<tr>
<th align="left" valign="top" bordercolor="blue">Head 1</th><th align="left" valign="top" bordercolor="blue">Head 2</th>
</tr>
<tr>
<td align="center" valign="top" bordercolor="blue">Value 1</td><td align="left" valign="top" bordercolor="blue">Value 2</td>
</tr>
<tr>
<td align="left" valign="top" bordercolor="blue">Value 3</td><td align="left" valign="top" bordercolor="blue">Value 3</td>
</tr>
<tr>
<td align="left" valign="top" bordercolor="blue">Value 5</td><td align="left" valign="top" bordercolor="blue">Value 4</td>
</tr>
</table>
Figure 24. disable-escaping.xml
<doc>
This document is <copyright>No One In Particular</copyright>.
</doc>
Figure 25. disable-escaping.xsl
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml"/>
<xsl:template match="doc">
<p><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="copyright">
<xsl:text>Copyright </xsl:text>
<xsl:text disable-output-escaping="yes">&copy;</xsl:text>
<xsl:text> 1999 </xsl:text>
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Figure 26. disable-escaping.html
<?xml version="1.0" encoding="utf-8"?>
<p>
This document is Copyright © 1999 No One In Particular.
</p>
A better technique for this particular example would be simply to use the numeric character reference for the Copyright symbol (©) and allow the serializer to "do the right thing."
The conversion of numbers from their internal, binary representation to a text representation is controlled by the <xsl:decimal-format> element.
A stylesheet can load additional documents with the document() function. In the following example, we recast the sorted table example using several features we have learned:
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:import href="element.xsl"/>
<xsl:variable name="tabledoc">sorttable.xml</xsl:variable>
<xsl:template match="insert-table">
<xsl:if test="@id"><a name="{@id}"/></xsl:if>
<xsl:apply-templates select="document($tabledoc)"/>
</xsl:template>
<xsl:template match="table">
<table>
<xsl:apply-templates select="row">
<xsl:sort data-type="number" select="./cell[1]"/>
</xsl:apply-templates>
</table>
</xsl:template>
</xsl:stylesheet>
The ID/IDREF mechanism for locating elements in XML documents has been generalized in XSL to the notion of keys.
Declaring keys gives the stylesheet processor an indication of what elements should be cached for fast access.
Figure 27. keys.xsl
<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:key name="bibkey" match="//biblio/bib" use="@abbrev"/>
<xsl:template match="doc">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="biblio">
<!-- suppressed -->
</xsl:template>
<xsl:template match="para">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="bibref">
<xsl:variable name="bib" select="key('bibkey',string(.))"/>
<xsl:choose>
<xsl:when test="$bib">
<i><xsl:apply-templates select="$bib"/></i>
</xsl:when>
<xsl:otherwise>
<b>NO BIB FOR <xsl:apply-templates/></b>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="bib">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Figure 28. keys.xml
<doc>
<para>See <bibref>xyzzy</bibref>.</para>
<biblio>
<bib abbrev="xyzzy">The Great Grue</bib>
<bib abbrev="abcde">That Alphabet Song</bib>
</biblio>
</doc>
Figure 29. keys.html
<?xml version="1.0" encoding="utf-8" ?>
See <i>The Great Grue</i>.
These examples are from James' XT distribution:
Figure 30. ext-func.xsl
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:date="http://www.jclark.com/xt/java/java.util.Date">
<xsl:template match="/">
<html>
<xsl:if test="function-available('date:to-string') and function-available('date:new')">
<p><xsl:value-of select="date:to-string(date:new())"/></p>
</xsl:if>
</html>
</xsl:template>
</xsl:stylesheet>
Figure 31. ext-elem.xsl
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
xmlns:xt="http://www.jclark.com/xt"
extension-element-prefixes="xt">
<xsl:output method="text"/>
<xsl:template match="file">
<xt:document href="{@name}" method="xml">
<xsl:fallback>This should not happen.</xsl:fallback>
<xsl:apply-templates mode="copy"/>
</xt:document>
<xsl:text>Created file </xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template mode="copy" match="*|@*">
<xsl:copy>
<xsl:apply-templates select="@*" mode="copy"/>
<xsl:apply-templates select="node()" mode="copy"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
>
<xsl:template match="doc">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="p">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="list">
<fo:list-block space-before="10pt"
provisional-distance-between-starts="3pc"
provisional-label-separation="1pc">
<xsl:apply-templates/>
</fo:list-block>
</xsl:template>
<xsl:template match="list//list">
<fo:list-block space-before="8pt"
provisional-distance-between-starts="3pc"
provisional-label-separation="1pc"
start-indent="3pc">
<xsl:apply-templates/>
</fo:list-block>
</xsl:template>
<xsl:template match="list/item">
<fo:list-item space-before="6pt">
<fo:list-item-label>
<fo:block>
<xsl:number count="item" format="1."/>
</fo:block>
</fo:list-item-label>
<fo:list-item-body>
<fo:block>
<xsl:apply-templates/>
</fo:block>
</fo:list-item-body>
</fo:list-item>
</xsl:template>
<xsl:template match="list//list/item" priority="1">
<fo:list-item space-before="6pt">
<fo:list-item-label>
<fo:block>
<xsl:number count="item" format="a."/>
</fo:block>
</fo:list-item-label>
<fo:list-item-body>
<fo:block>
<xsl:apply-templates/>
</fo:block>
</fo:list-item-body>
</fo:list-item>
</xsl:template>
<xsl:template match="list//list//list/item" priority="2">
<fo:list-item space-before="6pt">
<fo:list-item-label>
<fo:block>
<xsl:number count="item" format="i."/>
</fo:block>
</fo:list-item-label>
<fo:list-item-body>
<fo:block>
<xsl:apply-templates/>
</fo:block>
</fo:list-item-body>
</fo:list-item>
</xsl:template>
</xsl:stylesheet>
<fo:layout-master-set>
<fo:simple-page-master page-master-name="right">
<fo:region-body margin-bottom="50pt"/>
<fo:region-after extent="25pt"/>
</fo:simple-page-master>
<fo:simple-page-master page-master-name="left">
<fo:region-body margin-bottom="50pt"/>
<fo:region-after extent="25pt"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence>
<fo:static-content flow-name="xsl-after">
<fo:block><fo:page-number/></fo:block>
</fo:static-content>
<fo:flow>
. . .
</fo:flow>
</fo:page-sequence>
The final result of an XSL processor is the FO result tree that would then be passed to an XSL-enabled formatter for the final composition
To allow for the precise definition of the semantics of each formatting object and property, the XSL specification describes an area structure that is approximately analogous to a formatter's unpaginated "galley" structure
The area structure is conceptually one of nested boxes laid out with spaces around them and with formatting traits attached
There are two types of areas: block areas and inline areas
A line area is an example of a block are; a glyph area (for a "character") is an example of an inline area
The areas are separated by display space and inline space
The areas are placed within area containers (e.g., those corresponding to pages)
Areas have traits which are derived from the FO's properties (often directly, but sometimes via some computation)
The XSL formatting model consists of converting an fo-result tree into a structure of areas and traits
Properties are either inheritable or not--inheritance occurs within the result tree
Inheritable properties may not have any effect on a particular formatting object on which they are set but their values may affect descendant objects
Properties have some initial (default) value
Therefore, there is always a value defined for every property on every formatting object (either inherited, defaulted, or assigned), though not every property will be relevant to every formatting object
The description of each FO says which properties are relevant to it and how
Some properties can have values that require refinement to compute their value
Refinement occurs after inheritance
Examples of refinement:
shortcuts such as font which map to multiple properties such as font-size, font-weight, etc.
cases where multiple properties can affect similar traits such as padding-left and padding-start or space-before and margin-top
values (e.g., margins) that can be specified in terms of percentage of the column width need to be resolved to a distance
Properties such as space-before, space-after, and others are given as a space specifier
A space specifier consists of five parts:
Consecutive space specifiers are "merged" or "collapsed" according to an algorithm that takes their precedence and lengths into account
Space at the boundary of an area container (e.g., a page) gets discarded if its conditionality indicates that it is discardable
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="chapter">
<fo:block break-before="page">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="chapter/title">
<fo:block text-align="center" space-after="8pt"
space-before="16pt" space-after.precedence="3">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="section">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="section/title">
<fo:block text-align="center" space-after="6pt"
space-before="12pt" space-before.precedence="0"
space-after.precedence="3">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="paragraph[1]" priority="1">
<fo:block text-indent="0pc" space-after="7pt"
space-before.minimum="6pt" space-before.optimum="8pt"
space-before.maximum="10pt">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
<xsl:template match="paragraph">
<fo:block text-indent="2pc" space-after="7pt"
space-before.minimum="6pt" space-before.optimum="8pt"
space-before.maximum="10pt">
<xsl:apply-templates/>
</fo:block>
</xsl:template>
</xsl:stylesheet>
When the above stylesheet is applied to the following document, spacing will resolve as described below the following document.
<chapter>
<title>Chapter title</title>
<section>
<title>First section title</title>
<para>Section one's first paragraph.</para>
<para>Section one's second paragraph.</para>
</section>
<section>
<title>Second section title</title>
<para>Section two's only paragraph.</para>
</section>
</chapter>
Chapter title appears at the top of the page (its space-before is discarded).
Space between Chapter title and First section title is (8pt,8pt,8pt): the chapter title's space-after has a higher precedence than the section title's space-before (which takes on the initial value of zero), so the latter is discarded.
Space between First section title and Section one's first paragraph is (6pt,6pt,6pt): the section title's space-after has higher precedence than the paragraph's space-before, so the latter is discarded.
Space between the two paragraphs is (6pt,8pt,10pt): the space-after the first paragraph is discarded because its precedence is equal to that of the space-before the next paragraph, and the optimum of the space-after of the first paragraph is greater than the optimum of the space-before of the second paragraph.
Space between the second paragraph of the first section and the title of the second section is (12pt,12pt,12pt): the space-after the paragraph is discarded because its precedence is equal to that of the space-before of the section title, and the optimum of the space-after of the paragraph is less than the optimum of the space-before of the section title.
The indent on the first line of the first paragraph in section one and the only paragraph in section two is 2pc; the indent on the first line of the second paragraph in section one is zero.
XSL has a box model that includes CSS's border, padding, and margin concepts.
Other Information
An online version of this tutorial
Ken Holman offers a number of commercial tutorials
Specifications
XML Path Language 1.0, W3C Recommendation
XSL Transformations 1.0, W3C Recommendation
Extensible Style Language 1.0, W3C Proposed Recommendation
Extensible Markup Language 1.0, W3C Recommendation
Namespaces in XML 1.0, W3C Recommendation
Implementations
James Clark's XSLT processor
Scott Boag's XSLT processor
James Tauber's open source XSL formatter and renderer; see also http://xml.apache.org/ (http://xml.apache.org/)
XPath defines the grammer of location paths and a set of functions:
Returns the ordinal value of the last element in the current context
Returns the ordinal value of the current element in the current context
Returns the number of nodes in the specified node set
Returns the set of elements with the specified ID value
Returns the local name (the name without any namespace qualifiers) of the specified node (or the first node in document order)
Returns the namespace URI of the specified node (or the first node in document order)
Returns the fully qualified name of the specified node (or the first node in document order)
Returns the string representation of the object
Returns the concatenation of its arguments
Returns true if string1 starts with the characters in string2
Returns true if string1 contains string2
Returns the substring of string1 that occurs before the first occurance of string2, or the empty string if not(contains(string1, string2))
Returns the substring of string1 that occurs after the first occurance of string2, or the empty string if not(contains(string1, string2))
Returns the substring of string starting at position startpos of length length, or the rest of the string if length is not specified
Returns the length of the specified string
Returns the specified string with leading and trailing whitespace removed and internal sequences of multiple whitespace characters replaced by a single space
Returns string1 with the characters in string2 replaced by the characaters in string3
Returns the boolean representation of the object
Returns the negation of boolean
Returns true
Returns false (i.e., not(true())
Returns true if the language of the current context node (as specified by xml:lang) matches the specified language string
Returns the numeric representation of the object
Returns the sum of the numeric representations of the nodes in the node-set
Returns the largest integer not greater than number
Returns the smallest integer not less than number
Returns the integer value closest to number
XSLT extends the set of available functions with these:
Allows XSLT to access the nodes in another document
Returns the nodes that match object in the specified key
Returns the string representation of number using the formatstring specified and the decimalformat (or the default decimal format)
Returns the current context node
Returns the URI of the specified unparsed entity
Returns a string which uniquely identifies the specified node, or the first node in document order
Returns the value of the specified system property
Returns true if the specified element is available in the implementation
Returns true if the specified function is available in the implementation
The <xsl:stylesheet> or <xsl:transform> elements identify a complete stylesheet. They are completely synonymous.
<xsl:stylesheet id = id extension-element-prefixes = tokens exclude-result-prefixes = tokens version = number> <!-- Content: (xsl:import*, top-level-elements) --> </xsl:stylesheet>
A unique identifier
Identifies namespace (http://www.w3.org/TR/REC-xml-names) prefixes that are extension element prefixes
Lists namespace (http://www.w3.org/TR/REC-xml-names) prefixes that should not be put in the result tree
The XSLT version to which this stylesheet conforms (required)
A <xsl:template> constructs a portion of the result tree. It can be called either automatically by the XSLT processor or procedurally by other template(s) in the stylesheet.
<xsl:template match = pattern name = qname priority = number mode = qname> <!-- Content: (xsl:param*, template) --> </xsl:template>
The match pattern for this template
The name of this template
A priority for conflict resolution
The mode in which this template occurs
Either a match pattern or a name must be specified.
The <xsl:apply-templates> element indicates where additional templates should be used to construct a portion of the result tree. See also <xsl:call-template>
<xsl:apply-templates select = node-set-expression mode = qname> <!-- Content: (xsl:sort | xsl:with-param)* --> </xsl:apply-templates>
A <xsl:for-each> is a loop which processes each of the selected nodes using the template that it contains.
<xsl:for-each select = node-set-expression> <!-- Content: (xsl:sort*, template) --> </xsl:for-each>
A <xsl:call-template> allows one template to explicitly invoke another template by name. See also <xsl:apply-templates>.
<xsl:call-template name = qname> <!-- Content: xsl:with-param* --> </xsl:call-template>
The name of the template to be called. The stylesheet must contain an <xsl:template> with the specifed name.
A <xsl:param> can occur at either the top level or as the first child of a <xsl:template>. It is similar to a <xsl:variable>, but its value may be changed by the calling template or stylesheet environment.
This is analagous to the concept of subroutine parameters in a more traditional programming language.
<xsl:param name = qname select = expression> <!-- Content: template --> </xsl:param>
Used inside a <xsl:call-template>, a <xsl:with-param> specifies the value for parameters (<xsl:param>) within the called template.
<xsl:with-param name = qname select = expression> <!-- Content: template --> </xsl:with-param>
A <xsl:text> element inserts literal text into the result tree.
<xsl:text disable-output-escaping = "yes" | "no"> <!-- Content: #PCDATA --> </xsl:text>
Disabling output escaping may create result trees that are not well-formed, and are therefore not XML. Your gun, your bullet, your foot!
<xsl:copy use-attribute-sets = qnames> <!-- Content: template --> </xsl:copy>
Lists the names of attribute sets (<xsl:attribute-set>) to be copied into the result tree
The actual content of the <xsl:copy> element is copied literally into the result tree.
The <xsl:value-of> element inserts the string value of an expression into the result tree.
<xsl:value-of select = string-expression disable-output-escaping = "yes" | "no" />
Some examples of <xsl:value-of>:
The <xsl:element> allows you to dynamically calculate an element name.
<xsl:element name = { qname } namespace = { uri-reference } use-attribute-sets = qnames> <!-- Content: template --> </xsl:element>
The element name
The namespace URI reference for the element
Lists the names of attribute sets (<xsl:attribute-set>) to be copied into the result tree
An example of <xsl:element> in use:
<xsl:template name="process.table.cell"> <xsl:param name="cellgi">td</xsl:param> <xsl:element name="{$cellgi}"> <!-- whatever processing is desired --> </xsl:element> </xsl:template>
The <xsl:attribute> element allows you to dynamically or conditionally add attributes.
<xsl:attribute name = { qname } namespace = { uri-reference }> <!-- Content: template --> </xsl:attribute>
An example of <xsl:attribute> being used conditionally:
<xsl:template name="graphic"> <img src="{@fileref}"> <xsl:if test="@align"> <xsl:attribute name="align"> <xsl:value-of select="@align"/> </xsl:attribute> </xsl:if> </img> </xsl:template>
Note that the <img> tag has logical content in the stylesheet. The serializer is expected to render this appropriately for HTML or XML.
The <xsl:if> element is a simple "if" conditional:
<xsl:if test = boolean-expression> <!-- Content: template --> </xsl:if>
If the test expression returns a true value, the content of the <xsl:if> element is evaluated and inserted into the result tree. Otherwise, the <xsl:if> element and all of its contents are ignored.
For more complex conditionals, <xsl:choose> is a multi-way switching element.
<xsl:choose> <!-- Content: (xsl:when+, xsl:otherwise?) --> </xsl:choose>
The content of the first <xsl:when> element with a test expression that evaluates to true is inserted into the result tree. If none of them evaluate to true, the content of the <xsl:otherwise> element is inserted.
A <xsl:when> element is part of a <xsl:choose> statement.
<xsl:when test = boolean-expression> <!-- Content: template --> </xsl:when>
If the test expression returns a true value, the content of the <xsl:when> element is evaluated and inserted into the result tree.
An <xsl:otherwise> element is part of a <xsl:choose> statement.
<xsl:otherwise> <!-- Content: template --> </xsl:otherwise>
If none of the <xsl:when> elements evaluate to true, the content of the <xsl:otherwise> element is inserted into the result tree.
A <xsl:message> is a mechanism for the stylesheet author to communicate with the person running the stylesheet.
<xsl:message terminate = "yes" | "no"> <!-- Content: template --> </xsl:message>
The content of the <xsl:message> element may be presented to the user in an application-dependent fashion. This could be a terminal message, a browser popup, nothing more than writing it to a log file or simply terminating the program without displaying the message at all (for example, in a server-side environment).
A <xsl:variable> is a named storage location holding the results of a runtime evaluation of the variable content or select expression
<xsl:variable name = qname select = expression> <!-- Content: template --> </xsl:variable>
The <xsl:sort> element sorts a set of nodes.
<xsl:sort select = string-expression lang = { nmtoken } data-type = { "text" | "number" | qname-but-not-ncname } order = { "ascending" | "descending" } case-order = { "upper-first" | "lower-first" } />
The sorting data type determines how selected values are sorted; for example "02" sorts before "1" if "text" is used, after if "number" is used. Specifying any other value invokes a processor-dependent extension.
The <xsl:number> element counts elements in the source tree (or takes a numeric expression) and inserts a text representation of the resulting number into the result tree.
<xsl:number level = "single" | "multiple" | "any" count = pattern from = pattern value = number-expression format = { string } lang = { nmtoken } letter-value = { "alphabetic" | "traditional" } grouping-separator = { char } grouping-size = { number } />
Identifies the counting level
Selects the element(s) to count
Selects the location where counting should begin
A numeric expression to convert to a text representation
The format string
The language to use for conversion
Selects alphabetic or traditional letter values (in English, alphabetic is the traditional sequence, but that is not true in all languages)
The grouping separator character (",")
The number of digits in a group (3)
A <xsl:decimal-format> element defines the default decimal format for number to text conversion.
<xsl:decimal-format name = qname decimal-separator = char grouping-separator = char infinity = string minus-sign = char NaN = string percent = char per-mille = char zero-digit = char digit = char pattern-separator = char />
An optional name that can be used to refer to this decimal format; if no name is given, this declaration sets the default decimal format
The decimal separator character ("." for example)
The grouping separator character (",")
The string to use to represent infinity ("Infinity")
The character to use to represent negative numbers ("-")
The string to use to represent "not a number" ("NaN")
The percent character ("%")
The per-mille character ("‰")
The character used in format strings to represent a digit where a missing digit will show as this character ("0")
The character used in format strings to represent a digit where a missing digit will be absent ("#")
The character used to separate format strings (";")
All of these attributes, and the operation of the format number function, are interpreted according to the Java JDK 1.1 definition of the DecimalFormat (http://java.sun.com/products/jdk/1.1/docs/api/java.text.DecimalFormat.html) class.
The <xsl:key> element declares a key for subsequent use with the key() function.
<xsl:key name = qname match = pattern use = expression />
The <xsl:key> element is only useful in conjunction with the key function: