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

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

The
count
attribute of

can be used in two ways.

Firstly, it is useful if there are several different kinds of sibling elements that you want to count. There is an example of this in the entry for

on page 433, where we want to number the scenes, prologue and epilogue of a play in a single sequence. (The example actually uses
level=“any”
, but it applies equally well to
level=“single”
):


   


The number is then used to construct a hyperlink:


   


Without the
count
attribute, the
PROLOGUE
would be numbered 1, the first
SCENE
would also be numbered 1, and so would the
EPILOGUE
.

Another use of the
count
attribute is to specify that it is not the context node that should be counted, but an ancestor node. For example, in the template rule for a
<br/></span>element, you can use<br/><span><xsl:number><br/></span>to determine the number of the section that the title belongs to, by writing:<br/></p><div><p><span><xsl:template match=“title”><br/></span></p><p><span>   <xsl:number count=“section”/><br/></span></p><p><span>…<br/></span></p><p><span></xsl:template><br/></span></p></div><p>This usage is less common, and with XSLT 2.0 the<br/><span>select<br/></span>attribute gives more flexibility, because its value is an expression rather than a pattern. The above example can be written as:<br/></p><div><p><span><xsl:template match=“title”><br/></span></p><p><span>   <xsl:number select=“parent::section”/><br/></span></p><p><span>…<br/></span></p><p><span></xsl:template><br/></span></p></div><p>The<br/><span>select<br/></span>attribute is particularly handy when you want to construct a cross-reference to a node other than the context node. For example, if your document contains anchors with tags such as<br/><span><bookmark name=“biog”/><br/></span>, and references to these anchors of the form<br/><span><ref name=“biog”/><br/></span>, then your stylesheet might expand a reference as follows:<br/></p><div><p><span><xsl:key name=“bm” match=“bookmark” select=“@name”/><br/></span></p><p><span><xsl:template match=“ref”><br/></span></p><p><span>   <xsl:variable name=“target” select=“key(‘bm’, @name)/ancestor::div”/><br/></span></p><p><span>   <xsl:text>(See section </xsl:text><br/></span></p><p><span>   <a href=“{generate-id($target)}”><br/></span></p><p><span>      <xsl:number select=“$target”/><br/></span></p><p><span>   </a><br/></span></p><p><span>   <xsl:text>)</xsl:text><br/></span></p><p><span>…<br/></span></p><p><span></xsl:template><br/></span></p></div><p>The<br/><span>from attribute<br/></span>is rarely needed with<br/><span><img src="/files/04/27/65/f042765/public/ll.gif" />level=“single”<br/><img src="/files/04/27/65/f042765/public/gg.gif" /></span>. In fact, it's difficult to construct an example that isn't completely artificial.<br/></p><p>If you want numbering to start at a value other than 1, or perhaps to proceed in increments other than 1, you can capture the result of<br/><span><xsl:number><br/></span>in a variable and manipulate it using XPath expressions. For example, the following template rule numbers the items in a list starting at an offset passed in as a parameter:<br/></p><div><p><span><xsl:template match=“item”><br/></span></p><p><span>   <xsl:param name=“first-number” select=“1” as=“xs:integer”/><br/></span></p><p><span>   <xsl:variable name=“number”><xsl:number/></xsl:variable><br/></span></p><p><span>   <xsl:value-of select=“$first-number + $number - 1”/><br/></span></p><p><span>…<br/></span></p><p><span></xsl:template><br/></span></p></div><div><p>Example: Identifying Location of Text within a Document<br/></p><p>This example is adapted from the stylesheet used to produce the errata for the XSLT 2.0 and XPath 2.0 specifications. It searches the XSLT 2.0 specification for a given phrase (supplied as a the value of parameter<br/><span>$phrase<br/></span>) and outputs an HTML document listing all the places where the phrase occurs, with hyperlinks to the containing sections, and a description of the location of the text in terms such as “first numbered list, second item, third paragraph”.<br/></p><p>Source<br/></p><p>This stylesheet takes no principal input. Execution starts with the template named<br/><span>main<br/></span>, and the code reads the XHTML version of the XSLT 2.0 specification directly from the Web.<br/></p><p>Stylesheet<br/></p><p>This stylesheet is<br/><span>xslt-search.xsl<br/></span>.<br/></p><div><p><span><?xml version=‘1.0’?><br/></span></p><p><span><xsl:stylesheet version=“2.0”<br/></span></p><p><span>   xmlns:xsl=“http://www.w3.org/1999/XSL/Transform”<br/></span></p><p><span>   xmlns:xs=“http://www.w3.org/2001/XMLSchema”<br/></span></p><p><span>   xmlns:f=“http://www.wrox.com/xslt-errata”<br/></span></p><p><span>   xpath-default-namespace=“http://www.w3.org/1999/xhtml”><br/></span></p><p><span><xsl:param name=“spec” as=“document-node()”<br/></span></p><p><span>           select=“doc(‘http://www.w3.org/TR/xslt20’)”/><br/></span></p><p><span><xsl:param name=“phrase” as=“xs:string” required=“yes”/><br/></span></p></div><p>The main template searches the document for text nodes containing the required phrase. For each match, it finds the containing section in the specification and outputs a hyperlink to that section. Then it calls the<br/><span>f:location()<br/></span>function (which is the part we are interested in) to show the location of the text within the section:<br/></p><div><p><span><xsl:template name=“main”><br/></span></p><p><span>  <html><br/></span></p><p><span>    <head><br/></span></p><p><span>      <title>XSLT 2.0 Specification Search

    

    

      XSLT 2.0 Specification Search

      

           name=“matches” select=“$spec//text()[contains(.,$phrase)]”/>

      

        

          Matches for “

          

            

                 name=“div” select=“ancestor::div[(h1|h2|h3|h4)/a][1]”/>

            

             

                /a/@id}”>

                 

             

            

            

See :


            

          

        

        

          No matches found

        

      

    

         


The function
f:location()
does nothing for an element that is the only child of its parent. If the subsection is a direct child of the containing section, it outputs its position using

. If it is more deeply nested, it first makes a recursive call to display the position of its parent element, then appends its own position, again by calling

. The format used is
w
, which displays the position in words, and this is followed by a friendly name of the type of element (for example,


becomes “paragraph”) so with
ordinal=“yes”
we get a string such as
first table, second row, third column, second paragraph
.


  

  

  

    

                     or $subsection[self::span|self::a]”>

      

    

    

      

        

         

        

                                mode=“user-element-name”/>

      

    

    

      

        

        

        

         

        

                                    mode=“user-element-name”/>

      

    

  


Note the use of an

element to concatenate several text nodes into a single text node that can be converted to a string, as required by the function signature. The stylesheet finishes with a list of template rules that convert the names of elements into user-friendly terms:


  


paragraph

>bulleted list

>numbered list

… etc …


Output

This output is produced by supplying “formatted result” as the search phrase. The

output is “first bulleted list, third list item”.

See
Figure 6-8
, where the relevant text is highlighted.

Other books

At Peace by Kristen Ashley
My Buried Life by Doreen Finn
Play Me Right by Tracy Wolff
The Raphael Affair by Iain Pears
SHIVER by Tiffinie Helmer
Blonde With a Wand by Thompson, Vicki Lewis
In the Garden of Beasts by Erik Larson
The Fire Dance by Helene Tursten
Burning Down the House by Russell Wangersky