Navigational Stylesheets


Navigational stylesheets are a natural progression from simple fill-in-the-blanks stylesheets.

Like fill-in-the-blanks stylesheets, a navigational stylesheet is still essentially output oriented. However, it is now likely to use named templates or stylesheet functions as subroutines to perform commonly needed tasks ; it may use variables to calculate values needed in more than one place, and it may use constructs such as keys, parameters, and sorting.

Whereas a fill-in-the-blanks stylesheet looks like HTML sprinkled with a few extra control statements, a navigational stylesheet (once you look beyond the angle- bracket syntax) has a rather similar structure to a conventional procedural program with variables, conditional statements, for loops , and subroutine calls.

Navigational stylesheets are often used to produce reports on data-oriented XML documents, where the structure of the source document is regular and predictable.

A Navigational Stylesheet
start example

This example shows the use of a navigational stylesheet to produce a very simple sales report.

Input

Suppose the source document, booklist.xml , looks like this:

  <?xml version="1.0" encoding=".iso-8859-1 ?>   <booklist>   <book>   <title>Angela's Ashes</title>   <author>Frank McCourt</author>   <publisher>HarperCollins</publisher>   <isbn>0 00 649840 X</isbn>   <price>6.99</price>   <sales>235</sales>   </book>   <book>   <title>Sword of Honour</title>   <author>Evelyn Waugh</author>   <publisher>Penguin Books</publisher>   <isbn>0 14.018967 X</isbn>   <price>12.99</price>   <sales>12</sales>   </book>   </booklist>  

Stylesheet

The following navigational stylesheet ( booksales.xsl ) produces a report on the total number of sales for each publisher.

  <xsl:stylesheet   xmlns:xsl="http://wvw.w3.org/1999/XSL/Transforn"   xmlns:xs="http://www.w3.org/2001/XMLSchema"   exclude-result-prefixes="x.s"   version="2.0">   <xsl:key name="pub" match="book" use="publisher"/>  

We need to declare a variable that refers to the input document, for later use in a named template that has no context node.

  <xsl:variable name="in" select="/"/>  

The global variable $publishers ‰« is a sequence of strings containing one string for each distinct publisher found in the source file. This uses the new distinct-values () function introduced in XPath 2.0.

  <xsl:variable name="publishers" as="xs:string*"   select="distinct-values(/booklist/book/publisher)"/>  

The main template iterates over the distinct publishers using <xsl:for-each> .

  <xsl:template match="/">   <html>   <head>   <title>Sales volume by publisher</title>   </head>   <body>   <h1>Sales volume by publisher</h1>   <table id=" {generate-id(.) }">   <tr>   <th>publisher</th><th>Total Sales Value</th>   </tr>   <xsl:for-each select="$publishers">   <tr>   <td><xsl:value-of select="."/></td>   <td><xsl:call-template name="total-sales"/></td>   </tr>   </xs1:for-each>   </table>   </body>   </html>   </xsl:template>  

Finally, a named template that calculates the total sales for the publisher. The name of the publisher is supplied as an implicit parameter in the context node; however, to make the template more reusable a parameter is declared with this as the default.

  <xsl:template name="total-sales">   <xslsparam ,name="publisher"  select="."/>   <xsl:value-of select="sum($in/'key('pub', $publisher)/sales) "/>   </xsl:template>   </xsl:stylesheet>  

This stylesheet is not very far removed from the fill-in-the-blanks example earlier in the chapter. But because it uses some top-level elements such as <xsl:key> and a named template, it now needs to use the full syntax with an <xsl:stylesheet> element.

Output

  <html>   <head>   <META http-equiv="Content-Type" content="text/html;   charset=utf-8">   <title>Sales volume by publisher</title>   </head>   <body>   <h1>Sales volume by publisher</h1>   <table>   <tr>   <th>Publisher</th>   <th>Total Sales Value</th>   </tr>   <tr>   <td>HarperCollins</td>   <td>235</td>   </tr>   <tr>   <td>Penguin Books</td>   <td>12</td>   </tr>   </table>   </body>   </html>  
end example
 

The obvious difference between a fill-in-the-blanks stylesheet and this navigational stylesheet is that the <xsl:stylesheet> and <xsl:template> elements are now explicit, which makes it possible to introduce other top-level elements, such as <xsl:key> and global <xsl:variable> elements. More subtly, the range of XSLT features used means that this stylesheet has crossed the boundary from being an HTML document with added control instructions, to being a real program. The boundary, though, is a rather fuzzy one, with no visa required to cross it, so many people who have learned to write simple fill-in-the-blanks stylesheets should be able, as they expand their knowledge, to progress to writing navigational stylesheets of this kind.

Although the use of flow-of-control instructions like <xsl:if>,<xsl:call-template> , and <xsl:for-each > gives such a stylesheet a procedural feel, it does not violate the original concept that XSLT should be a declarative language. This is because the instructions do not have to be executed in the order they are written-variables can't be updated, so the result of one instruction can't affect the next one. For example, it's easy to think of the <xsl:for-each> instruction in this example processing the selected nodes in document order and adding them one by one to the result tree; but it would be equally valid for an XSLT processor to process them in reverse order, or in parallel, so long as the nodes - are added to the result tree in the right place. That's why I was careful to call this design pattern navigational rather than procedural . It's navigational in that you say exactly where to find the nodes in the source tree that you want to visit, but it's not procedural, because you don't define the order in which you will visit them.

New features available in XSLT 2.0 and XPath 1.0 greatly increase the scope of what can be achieved with a navigational stylesheet. Many problems that in XSLT 1.0 required complex programming (using the computational design pattern described later in this chapter) can now be tacked within the navigational approach. Examples include grouping problems, and problems that require splitting up of text fields, using delimiters such as commas or newlines, as well as many arithmetic operations such as summing the total value of an invoice. The features that provide this capability include the following:

  • The availability of sequences in the data model, together with the for ‰« expression in Xpath, to manipulate them.

  • Grouping constructs, including the <xsl:for-each- group > instruction in XSLT 2.0 and the distinct-values() function in XPath 2.0.

  • Text manipulation facilities, notably the <xsl:analyze-string> instruction in XSLT 2.0 and the replace() and tokenize() functions in XPath 2.0.

  • Aggregation functions such as avg() , min() , and max() .

The ability to write chunks of reusable code in the form of stylesheet functions that can be invoked from XPath expressions, rather than only as templates to be called using XSLT instructions, also helps to make navigational stylesheets much easier to write.




XSLT 2.0 Programmer's Reference
NetBeansв„ў IDE Field Guide: Developing Desktop, Web, Enterprise, and Mobile Applications (2nd Edition)
ISBN: 764569090
EAN: 2147483647
Year: 2003
Pages: 324

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net