Read XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition Online
Authors: Michael Kay
Using Template Parameters
Template parameters are used more often with
Declaring the expected type of a parameter, using the
as
attribute, is optional, but I would always recommend it. It provides useful documentation for anyone who has to debug the stylesheet later, as well as trapping errors when the caller provides incorrect parameter values. My experience is that it catches many coding errors that would otherwise have led to incorrect output being generated. In addition, the information is very useful to the XSLT processor itself, as it enables optimized code to be produced. For example, a test such as
$p
will always be an integer, than if the processor has to deal with the possibility of it being a node, a sequence of nodes, a sequence of doubles, or perhaps an
untypedAtomic
value.
Using Tunnel Parameters
Tunnel parameters provide a halfway house between global variables and local template parameters, combining the advantages of both and removing many of the problems of both. Compared with global variables, their great advantage is that their value can change in the course of the transformation. This doesn't mean that they introduce side effects, because only the caller of a template can set the value, not the callee. Compared with local parameters, their great advantage is that you don't have to change every template in the stylesheet to pass the values through.
I found a good use case for tunnel parameters in the stylesheet used to generate the XSLT working draft. The XML master version of this document includes entries describing each error condition that can arise. This is used both to generate inline descriptions of the errors in the document body and to generate a summary of errors in an appendix. Much of the code to handle the two cases is the same, but a few details differ; for example, the way that hyperlinks are generated. Traditionally, this problem is tackled using modes; however, even with the XSLT 2.0 ability to write a single template rule that works in more than one mode, using modes means that the intermediate template rules need to be aware of the fact that they can be invoked under two different circumstances. They shouldn't need to know this: only the code that produces different results in the two cases should need to know that there are two possible cases. A tunnel parameter indicating which phase of processing is active solves the problem neatly.
Examples
This section presents two examples showing the use of
Example: Using
This example shows a simple named template that defines a parameter and gives it a default value.
Source
This stylesheet works with any XML source file.
Stylesheet
The stylesheet is
call.xsl
.
It contains a named template that outputs the depth of a node (defined as the number of ancestors). The node may be supplied as a parameter; if it is not supplied, the parameter defaults to the current node.
The stylesheet includes a template rule for the document node that invokes this named template, defaulting the parameter, to display the name and depth of every element in the source document.
xmlns:xsl=“http://www.w3.org/1999/XSL/Transform”
version=“2.0”
>
Output
If the stylesheet is run using itself as the source document, the output is as follows:
xsl:transform -- 1;
xsl:output -- 2;
xsl:template -- 2;
xsl:for-each -- 3;
xsl:value-of -- 4;
xsl:call-template -- 4;
xsl:template -- 2;
xsl:param -- 3;
xsl:value-of -- 3;
Example: Tunnel Parameters
Realistic examples using tunnel parameters tend to involve customization of rather complex stylesheets, such as the DocBook stylesheet suite (
http://docbook.sourceforge.net/
) used for producing many technical manuals. Unfortunately, explaining such an example would take a full chapter of this book. So we'll make do with a simpler case.
Suppose that you start with the stylesheet
play.xsl
, which is designed to generate a set of linked HTML files containing the text of one of Shakespeare's plays as marked up by Jon Bosak. I won't present this stylesheet in full, because it's pretty standard, and most of it isn't relevant to the example: you can find it in the download files for this book. The challenge now is to customize this stylesheet so that instead of producing a single rendition of the play, it produces a script for each of the characters appearing in the play, with the lines spoken by the character highlighted. I have done this by producing another stylesheet module,
scripts.xsl
, which overrides selected template rules from the original.
Source
This stylesheet can be applied to any of the Shakespeare plays available from
http://metalab.unc.edu/bosak/xml/eg/shaks200.zip
. The examples use
othello.xml
, which is included in the download files for this book.
Output
The existing stylesheet,
play.xsl
, produces a set of HTML files: one file called
play.html
, which acts as a cover sheet and index, and one file for each scene in the play, with names such as
sceneN.html
. You can run it with a command like this:
java -jar c:\saxon\saxon9.jar othello.xml play.xsl dir=c:/temp/othello
The first page of the output, in the file
play.html
, is shown in
Figure 6-10
.
In the customized presentation, we want to create an index page that looks like the one shown in
Figure 6-11
.
This presents an index showing all the speaking parts in the play. Clicking on one of the names brings up a modified version of the front page shown before, in which the titles of the scenes are shown as active links if the character appears in these scenes, or as plain text otherwise. The actual text of the scene should also be modified so that the speaker's lines are highlighted.
Stylesheet
The base stylesheet
play.xsl
is unmodified (it is one that has been included in the Saxon distribution for a while, to illustrate how a stylesheet can create multiple output files).
The customization layer is in the file
scripts.xsl
. This starts by importing
play.xsl
. It then contains a template rule providing the new control logic:
This template creates the index page. It calls the
distinct-values()
function to get a list of speakers appearing in the play, and for each one, it firstly outputs a hyperlink to a
play.html
file in a subdirectory named after the speaker and then calls
There are three template rules in the
play.xsl
stylesheet that need to be modified: these are the template for the
play.html
file now has to be placed in a subdirectory), the template for the
The modifications here, apart from the addition of the
The template rule for the
The changes from the original are addition of the
The key point about this example is that the original stylesheet has been customized and reused without changing it in any way. Without tunnel parameters, this would have required many more of its template rules to be changed, merely to pass the extra parameter through.