home movie radio music chord lyrics book game Dictionary clip
HOME HAND MADE RADIO SHOP CHORD LYRICS BOOKS GAME Dictionary Clip
[ Team LiB ] Previous Section Next Section

12.1 The if Element

The XML document you'll process in this chapter is Example 12-1, africa.xml, found in examples/ch12. It's over 300 lines long, so only part of it is shown here.

Example 12-1. An excerpt of a document listing countries in Africa
<?xml version="1.0" encoding="ISO-8859-1"?>
   
<africa>
 <source>
  <title>CIA Factbook</title>
  <url>http://www.cia.gov/cia/publications/factbook/</url>
  <populations estimate="true" year="2002"/>
 </source>
 <nation>
  <name>Algeria</name>
  <capital>Algiers</capital>
  <population>32277942</population>
  <cc>dz</cc>
 </nation>
 <nation>
  <name>Angola</name>
  <capital>Luanda</capital>
  <population>10593171</population>
  <cc>ao</cc>
 </nation>
 <nation>
  <name>Benin</name>
  <capital>Porto-Novo</capital>
  <population>6787625</population>
  <cc>bj</cc>
 </nation>
 <nation>
  <name>Bostwana</name>
  <capital>Gaborone</capital>
  <population>1591232</population>
  <cc>bw</cc>
 </nation>
 <nation>
  <name>Burkina Faso</name>
  <capital>Ouagadougou</capital>
  <population>12603185</population>
  <cc>bf</cc>
 </nation>
 <nation>

After some source information about the online CIA World Factbook where you can find this information, each of the 53 nations on the African continent is listed, along with the nation's capital city, population (an estimate as of midyear 2002), and two-letter country code. (You can find the factbook at http://www.cia.gov/cia/publications/factbook/.)

The simple stylesheet if.xsl, shown in Example 12-2, uses the if element to process africa.xml.

Example 12-2. A stylesheet that checks to see if countries have populations over 10,000,000
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
   
<xsl:template match="africa">
 <xsl:apply-templates select="nation"/>
</xsl:template>
   
<xsl:template match="nation">
 <xsl:text> * </xsl:text>
 <xsl:value-of select="name"/>
  <xsl:if test="population > 10000000">
   <xsl:text> (over 10M)</xsl:text>
  </xsl:if>
 <xsl:text>&#10;</xsl:text>
</xsl:template>
   
</xsl:stylesheet>

The first template in if.xsl matches the document element africa, and then applies templates to any nation element that is a child of africa. The template that matches nation elements writes the name of the nation to the result tree, preceded by a literal asterisk, which acts as a bullet in the plain text output.

Then comes the if element. The if element has one required attribute, test, which must contain an expression that produces a Boolean result (true or false). The content of an if element is a template. If test returns true, the template is instantiated; if false, the template is not instantiated. (You don't actually see the words true or false returned. Booleans are handled internally by the processor.)

In this instance, the test attribute contains an expression testing whether the population child of nation has content (converted implicitly to a number) that is greater than 10,000,000. If the number is greater than 10,000,000, the template inside the if element is instantiated—that is, the text (over 10M) is written to the result; if it is less than 10,000,000, the template is not instantiated.

Let's see what happens. Process africa.xml with this command:

xalan africa.xml if.xsl

to produce the following results (only the first 10 lines of the output are shown):

 * Algeria (> 10M)
 * Angola (> 10M)
 * Benin
 * Bostwana
 * Burkina Faso (> 10M)
 * Burundi
 * Cameroon (> 10M)
 * Cape Verde
 * Central African Republic
 * Chad

The African nations shown here that have populations greater than 10,000,000—Algeria, Angola, Burkina Faso, and Cameroon—are annotated with (> 10m).

Compare those results with that of less.xsl, shown in Example 12-3.

Example 12-3. Testing to see if a population is less than 10,000,000
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
   
<xsl:template match="africa">
 <xsl:apply-templates select="nation"/>
</xsl:template>
   
<xsl:template match="nation">
 <xsl:text> * </xsl:text>
 <xsl:value-of select="name"/>
  <xsl:if test="population &lt;= 10000000">
   <xsl:text> (&lt;= to 10M)</xsl:text>
  </xsl:if>
 <xsl:text>&#10;</xsl:text>
</xsl:template>
   
</xsl:stylesheet>

Because it is in an attribute value, the less-than symbol (<) is represented by &lt; in the value of the test attribute. (The need for predefined entities was explained in Chapter 2.) When you process africa.xml with less.xsl using:

xalan africa.xml less.xsl

you get the opposite effect, that is, results showing those nations whose populations are less than 10,000,000 are annotated (first 10 shown):

 * Algeria
 * Angola
 * Benin (<= to 10M)
 * Bostwana (<= to 10M)
 * Burkina Faso
 * Burundi (<= to 10M)
 * Cameroon
 * Cape Verde (<= to 10M)
 * Central African Republic (<= to 10M)
 * Chad (<= to 10M)

if.xsl and less.xsl are simple examples of the if element. You can just as easily perform similar conditional operations using predicates, without the if element. Example 12-4, withoutif.xsl, shows you one way you could process on the same conditions without using if.

Example 12-4. Testing using predicates instead of explicit if statements
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
   
<xsl:template match="africa">
 <xsl:apply-templates select="nation"/>
</xsl:template>
   
<xsl:template match="nation[population &lt;= 10000000]">
 <xsl:text> * </xsl:text>
 <xsl:value-of select="name"/>
 <xsl:text> (&lt;= 10M)</xsl:text>
 <xsl:text>&#10;</xsl:text>
</xsl:template>
   
<xsl:template match="nation[population > 10000000]">
 <xsl:text> * </xsl:text>
 <xsl:value-of select="name"/>
 <xsl:text> (> 10M)</xsl:text>
 <xsl:text>&#10;</xsl:text>
</xsl:template>
   
</xsl:stylesheet>

In this stylesheet, the conditional testing for population numbers is done by predicates (see the bold lines). Applied to africa.xml with:

xalan africa.xml withoutif.xsl

this stylesheet will give you the following output (first 10 lines):

 * Algeria (> 10M)
 * Angola (> 10M)
 * Benin (<= 10M)
 * Bostwana (<= 10M)
 * Burkina Faso (> 10M)
 * Burundi (<= 10M)
 * Cameroon (> 10M)
 * Cape Verde (<= 10M)
 * Central African Republic (<= 10M)
 * Chad (<= 10M)

In Example 12-5, I'll show you how to use several if elements together in a useful way. The stylesheet is comma.xsl.

Example 12-5. A stylesheet using multiple if statements
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
   
<xsl:template match="africa">
 <xsl:text>The nations of Africa are </xsl:text>
 <xsl:apply-templates select="nation"/>
</xsl:template>
   
<xsl:template match="nation">
 <xsl:value-of select="name"/>
  <xsl:if test="position(  ) != last(  )">, </xsl:if>
  <xsl:if test="position(  ) mod 5 = 0">
   <xsl:text>&#10;</xsl:text>
  </xsl:if>
  <xsl:if test="position(  ) = (last(  ) - 1)">and </xsl:if>
  <xsl:if test="position(  ) = last(  )">.</xsl:if>
</xsl:template>
   
</xsl:stylesheet>

This stylesheet writes out the entire list of African nations, separating nearly all of them by commas and spaces. The first template writes some text at the beginning of the result tree. Then after printing the name of each African nation with value-of, comma.xsl considers the position of nation nodes with four instances of the if element. Each instance of if uses the position( ) function to test the condition of the current nation node:

  • The first one tests to see whether the context node is the last of the nation nodes; if it is not the last, the template in if writes a comma to the result tree.

  • The second uses the modulo operator mod to test whether the remainder of its operation is zero. If the remainder is zero, it means that five nation nodes have been written to the result tree and so, upon finding that condition, the processor adds a linefeed to the result tree.

  • The third writes the word and to the result tree if the node is the next-to-last nation node.

  • The fourth writes a period (.) if the node is the last nation node in the list.

To see the outcome, type the following on a command line:

xalan africa.xsl comma.xsl

Here is the result. Note the placement of commas, line breaks, the word and, and the period (.):

The nations of Africa are Algeria, Angola, Benin, Bostwana, Burkina Faso,
Burundi, Cameroon, Cape Verde, Central African Republic, Chad,
Comoros, Congo, Congo, Democratic Republic of, Cote d'Ivoire, Djibouti,
Eqypt, Equatorial Guinea, Eritrea, Ethiopia, Gabon,
Gambia, Ghana, Guinea, Guinea-Bissau, Kenya,
Lesotho, Liberia, Libya, Madagascar, Malawi,
Mali, Mauritania, Maurutius, Morocco, Mozambique,
Namibia, Niger, Nigeria, Rwanda, Sao Tome and Principe,
Senegal, Seychelles, Sierra Leone, Somalia, South Africa,
Sudan, Swaziland, Tanzania, Togo, Tunisia,
Uganda, Zambia, and Zimbabwe.

This concludes your brief tour of the if instruction. You're ready to move on to using the choose element, which processes multiple conditions at one time, and to dealing with exceptions to those conditions.

    [ Team LiB ] Previous Section Next Section