4.5 Predicates

A predicate is a filter that can be used with a pattern as well as an expression. It checks to see whether a node-set matches an expression contained in square brackets. Again harking back to nodes.xml, here is an example of a pattern with a predicate:

amount[@vendor = '314']

One way to think about predicates is in terms of the word where in other words, this pattern matches an amount element where the vendor attribute associated with amount has a value of 314. (As I mentioned earlier in the chapter, when the predicate is evaluated, the node in the predicate temporarily becomes the current node.)

The content between the square brackets is actually an expression. This is the only way that a pattern makes use of an expression. You can, of course, use predicates with expressions, as well as with patterns. If a predicate matches a given criteria, the predicate returns a Boolean value of true, or false if otherwise. In other words, if the expression in a predicate matches a node-set in a pattern, it returns true, and the template that matches the pattern is instantiated; if there is no match, the template is skipped.

Look at another example of a predicate:

amount[current(  ) = '7598.00']

This one checks to see whether the content of amount is 7598.00 and returns true if it is. This could also be written as:

amount[. = '7598.00']

Here is yet another example:

amount[position(  )=1]

This tests to see whether amount is the first node in the set. This could also be written as:

amount[1]

To illustrate these concepts further, Example 4-1 shows the document names.xml. It's a slightly different version of wg.xml, which you worked with in the last chapter. The last and first elements have been changed to family and given, respectively. Several attributes and an encoding declaration have been added.

Example 4-1. An XML list of contributors to XML 1.0
<?xml version="1.0" encoding="ISO-8859-1"?>     <!--  names of persons acknowledged as current and past members  of the W3C XML Working Group at the time of the publication  of the first edition of the XML specification on 1998-02-10 -->     <names>  <name>   <family>Angerstein</family>   <given>Paula</given>  </name>  <name title="chair">   <family>Bosak</family>   <given>Jon</given>  </name>  <name title="editor">   <family>Bray</family>   <given>Tim</given>  </name>  <name title="technical lead">   <family>Clark</family>   <given>James</given>  </name>  <name>   <family>Connolly</family>   <given>Dan</given>  </name>  <name>   <family>DeRose</family>   <given>Steve</given>  </name>  <name>   <family>Hollander</family>   <given>Dave</given>  </name>  <name>   <family>Kimber</family>   <given>Eliot</given>  </name>  <name>   <family>Magliery</family>   <given>Tom</given>  </name>  <name>   <family>Maler</family>   <given>Eve</given>  </name>  <name>   <family>Maloney</family>   <given>Murray</given>  </name>  <name>   <family>Murata</family>   <given>Makoto</given>  </name>  <name>   <family>Nava</family>   <given>Joel</given>  </name>  <name>   <family>O'Connell</family>   <given>Conleth</given>  </name>  <name title="editor">   <family>Paoli</family>   <given>Jean</given>  </name>  <name>   <family>Sharpe</family>   <given>Peter</given>  </name>  <name title="editor">   <family>Sperberg-McQueen</family>   <given>C. M.</given>  </name>  <name>   <family>Tigue</family>   <given>John</given>  </name> </names>

Now consider the stylesheet pattern.xsl, shown in Example 4-2.

Example 4-2. A stylesheet extracting the fourth listed member of the XML team
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/>     <xsl:template match="/">  <xsl:apply-templates select="names"/> </xsl:template>     <xsl:template match="names">  <xsl:apply-templates select="name[4]/@title"/> </xsl:template>     <xsl:template match="name[4]/@title">  <xsl:text>The XML 1.0 WG's </xsl:text>  <xsl:value-of select="."/>  <xsl:text> was </xsl:text>  <xsl:value-of select="../given"/>  <xsl:text> </xsl:text>  <xsl:value-of select="../family"/>  <xsl:text>.</xsl:text> </xsl:template>     </xsl:stylesheet>

Apply this stylesheet to names.xml with Xalan:

xalan names.xml pattern.xsl

and you'll see this one-line result:

The XML 1.0 WG's technical lead was James Clark.

There are other, more efficient ways to write this stylesheet, but this version suffices for the moment. Each match attribute in each of the three templates contains a pattern:

  • The pattern in the first template rule, /, matches the root or document node and then applies the template that matches names.

  • The pattern in the second template rule matches the document element names, and then applies the template that matches the title attribute (@title) of the fourth name child (name[4]) of names.

  • The third and final pattern matches the title attribute of the fourth name element.

When the final template is instantiated, it uses several value-of elements to take information out of the source document, and also uses four text elements to put text on the result tree. The period (.) in the select attribute of the first value-of selects the current node.

4.5.1 Matching Multiple Nodes with a Pattern

You can match a union of multiple nodes by using the union operator (|) in a pattern or expression. The union operator denotes alternatives, that is, when you see the union operator separating node names, read the word or. To see what I mean, I'll show you union.xsl, which produces valid, string HTML 4.01 output. But first, Example 4-3 shows provinces.xml, along with an internal subset DTD, which contains a list of Canadian provinces.

Example 4-3. An XML list of contributors to XML 1.0
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet href="union.xsl" type="text/xsl"?> <!DOCTYPE provinces [ <!ELEMENT provinces (province)+> <!ELEMENT province (name, abbreviation)> <!ATTLIST province id ID #REQUIRED> <!ELEMENT name (#PCDATA)> <!ELEMENT abbreviation (#PCDATA)> ]>     <provinces>  <province >   <name>Alberta</name>   <abbreviation>AB</abbreviation>  </province>  <province >   <name>British Columbia</name>   <abbreviation>BC</abbreviation>  </province>  <province >   <name>Manitoba</name>   <abbreviation>MB</abbreviation>  </province>  <province >   <name>New Brunswick</name>   <abbreviation>NB</abbreviation>  </province>  <province >   <name>Newfoundland and Labrador</name>   <abbreviation>NL</abbreviation>  </province>  <province >   <name>Northwest Territories</name>   <abbreviation>NT</abbreviation>  </province>  <province >   <name>Nova Scotia</name>   <abbreviation>NS</abbreviation>  </province>  <province >   <name>Nunavut</name>   <abbreviation>NU</abbreviation>  </province>  <province >   <name>Ontario</name>   <abbreviation>ON</abbreviation>  </province>  <province >   <name>Prince Edward Island</name>   <abbreviation>PE</abbreviation>  </province>  <province >   <name>Quebec</name>   <abbreviation>QC</abbreviation>  </province>  <province >   <name>Saskatchewan</name>   <abbreviation>SK</abbreviation>  </province>  <province >   <name>Yukon</name>   <abbreviation>YT</abbreviation>  </province> </provinces>

This document has an internal subset DTD. The only attribute declared is the required attribute id, which is of type ID. This attribute type is explained further in Chapter 5.

This document may be transformed into HTML with union.xsl, shown in Example 4-4.

Example 4-4. A stylesheet that applies the same rule to multiple nodes
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html"/> <xsl:output doctype-system="http://www.w3.org/TR/html4/strict.dtd"/> <xsl:output doctype-public="-//W3C//DTD HTML 4.01//EN"/>     <xsl:template match="provinces">  <html>  <head><title>Provinces of Canada and Abbreviations</title></head>  <body style="text-align:center">  <h3 style="text-align:center">Provinces of Canada and Abbreviations</h3>  <table style="margin-left:auto;margin-right:auto" rules="all" border="4">  <thead style="background-color:black;color:white">   <tr>    <th style="width:230">Province</th>    <th style="width:230">Abbreviation</th>   </tr>  </thead>  <tbody align="center">  <xsl:apply-templates select="province"/>  </tbody>  </table>  </body>  </html> </xsl:template>     <xsl:template match="province">  <tr>   <xsl:apply-templates select="name|abbreviation"/>  </tr> </xsl:template>     <xsl:template match="name|abbreviation">  <td>  <xsl:apply-templates/>  </td> </xsl:template>     </xsl:stylesheet>

After the first template rule matches provinces, it generates the main body of HTML markup, which includes table-related elements such as table, thead, and tbody, plus CSS rules in style attributes.

The second template rule matches province nodes and then applies templates to the name or abbreviation children of province. (name | abbreviation) surrounds the output with tr (table row) tags. The final template rule matches on the pattern of name or abbreviation nodes, enclosing that output with td (table data) tags.

When you process provinces.xml with union.xsl:

xalan provinces.xml union.xsl

you see the following outcome from processing the union of name and abbreviation nodes. Note how the text content of both name and abbreviation nodes are contained in td elements, which are children of tr elements. This allows the columns of the table to line up properly. The resulting HTML document, listed in Example 4-5, is shown in Figure 4-4.

Example 4-5. An HTML table created by the stylesheet in Example 4-4
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/ strict.dtd"> <html> <head> <META http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Provinces of Canada and Abbreviations</title> </head> <body style="text-align:center"> <h3 style="text-align:center">Provinces of Canada and Abbreviations</h3> <table style="margin-left:auto;margin-right:auto" rules="all" border="4"> <thead style="background-color:black;color:white"> <tr> <th style="width:230">Province</th><th style="width:230">Abbreviation</th> </tr> </thead> <tbody align="center"> <tr> <td>Alberta</td><td>AB</td> </tr> <tr> <td>British Columbia</td><td>BC</td> </tr> <tr> <td>Manitoba</td><td>MB</td> </tr> <tr> <td>New Brunswick</td><td>NB</td> </tr> <tr> <td>Newfoundland and Labrador</td><td>NL</td> </tr> <tr> <td>Northwest Territories</td><td>NT</td> </tr> <tr> <td>Nova Scotia</td><td>NS</td> </tr> <tr> <td>Nunavut</td><td>NU</td> </tr> <tr> <td>Ontario</td><td>ON</td> </tr> <tr> <td>Prince Edward Island</td><td>PE</td> </tr> <tr> <td>Quebec</td><td>QC</td> </tr> <tr> <td>Saskatchewan</td><td>SK</td> </tr> <tr> <td>Yukon</td><td>YT</td> </tr> </tbody> </table> </body> </html>
Figure 4-4. An HTML table in Mozilla
figs/lxsl_0404.gif


Learning XSLT
Learning XSLT
ISBN: 0596003277
EAN: 2147483647
Year: 2003
Pages: 164

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