XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition (222 page)

BOOK: XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition
13.97Mb size Format: txt, pdf, ePub

Using Template Parameters

Template parameters are used more often with

than with

, though they are available to both, and in XSLT 2.0 they can also be used with

and

. The actual value of the parameter is set by the caller using an

element. Parameters are often needed by the recursive algorithms used in XSLT to handle lists of items: there are examples of such algorithms under

on page 271. In XSLT 2.0, however, it is often more convenient to implement such algorithms using

.

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

is very much simpler if it is known in advance that
$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

to define template parameters. The first is a very simple demonstration of how parameters work with

. The second is a more complicated example, making use of tunnel parameters.

Example: Using with a Default Value

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:


  

  

    

    <xsl:apply-templates select=“PLAY/TITLE”/>

    

    

        


            

            


            

        


        


          

            

              

            

             | 

            

              

            

          

        


        


    

    

  


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

to process the

element, which is the outermost element in the source file. Crucially, it supplies the name of the speaker as a tunnel parameter to this template.

There are three template rules in the
play.xsl
stylesheet that need to be modified: these are the template for the

element (because the
play.html
file now has to be placed in a subdirectory), the template for the

element (which must now generate pages only for those scenes in which the selected speaker appears), and the template for the

element (to highlight the lines spoken by the selected speaker). Each of these contains a declaration of the tunnel parameter in an

element. Here is the modified template for the

element:


    

    

      

    

    

    

    

    

        

            

        

        

      “file:///{$dir}/{encode-for-uri($speaker, true())}/scene{$NR}.html”>

            

            

            <br/></span></p><p><span>              <xsl:value-of select=“concat($play, ‘ ’, $act, ‘: ’, TITLE)”/><br/></span></p><p><span>            

            

            

            


                

                

                

            


            

            

            

        

    

    

        

    

    


The modifications here, apart from the addition of the

to declare the tunnel parameter, are the addition of the

to generate the scene page conditionally, and the choice of file name produced by

.

The template rule for the

element becomes:


    

    


    

    

       

    

    

    

    

    

    

    



The changes from the original are addition of the

declaring the tunnel parameter, and the addition of the

instruction that outputs an attribute changing the background color if the selected speaker participates in this

(a

can have more than one

, the equality test succeeds if any of them match).

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.

Other books

A Darker Place by Jack Higgins
Everything Happened to Susan by Malzberg, Barry
Asperger's and Girls by Wrobel, Mary, Iland, Lisa, Myers, Jennifer McIlwee, Snyder, Ruth, Wagner, Sheila, Attwood, Tony, Faherty, Catherine, Grandin, Temple
Love Falls by Esther Freud
Body Blows by Marc Strange
Blood Ties by Nicholas Guild