9.5 Numbering Levels

An XSLT processor analyzes a source tree before any processing takes place. This makes it reasonably easy for the processor to determine how many nodes lie along a given axis, and makes it possible to produce different numbering levels when transforming a document. You can control this with number's level attribute.

The level attribute lets you set the level at which numbering takes place with one of three values: single, multiple, and any. So far, you have only seen numbering single level, which is the default. Here is a brief explanation of the three numbering levels, assuming that you don't use the from attribute and that the count attribute matches the current node:

  • By default, the value of level is single, meaning that numbering takes place only with regard to sibling nodes on one level. More precisely, nodes on the single (one) level are counted along the preceding-sibling axis, and include all the preceding sibling nodes that match count or the current node.

  • If the value of level is multiple, this means that all nodes on the ancestor-or-self axis, that match count or the current node, are counted.

  • If the level attribute has a value of any, all nodes on the preceding or ancestor axes before the current node, that match count or the current node, are counted as they appear in document order.

That's the technical explanation. The different numbering levels will be clearer to you after you get a chance to go through a couple of examples.

9.5.1 Counting on Multiple Levels

To start out, take a look at Example 9-17, outline.xml, which lists some information about money in the United States.

Example 9-17. An XML document about U.S. currency
<?xml version="1.0"?>     <outline>  <section title="US coin denominations">   <item>cent</item>   <item>nickel</item>   <item>dime</item>   <item>quarter</item>   <item>half dollar</item>   <item>dollar</item>  </section>  <section title="Persons on US coins">   <item>Abraham Lincoln (cent)</item>   <item>Thomas Jefferson (nickel)</item>   <item>Franklin Roosevelt (dime)</item>   <item>George Washington (quarter)</item>   <item>John Kennedy (half dollar)</item>   <item>Sacagawea (dollar)</item>  </section>  <section title="US currency in bills">   <item>$1 dollar bill</item>   <item>$2 dollar bill</item>   <item>$5 dollar bill</item>   <item>$10 dollar bill</item>   <item>$20 dollar bill</item>   <item>$50 dollar bill</item>   <item>$100 dollar bill</item>  </section>  <section title="Persons on US bills">   <item>George Washington ($1)</item>   <item>Thomas Jefferson ($2)</item>   <item>Abraham Lincoln ($5)</item>   <item>Alexander Hamilton $10</item>   <item>Andrew Jackson ($20)</item>   <item>Ulysses Grant ($50)</item>   <item>Benjamin Franklin ($100)</item>  </section> </outline>

There are two levels to count in outline.xml, namely, section and item nodes. The following stylesheet, outline.xsl, counts on both levels because it uses multiple as the value of the level attribute on number.

This stylesheet also introduces the for-each instruction element. As stated earlier, the for-each element works like a template within a template, and it is instantiated each time the node in the required select attribute is matched.

Example 9-18 shows outline.xsl.

Example 9-18. Using for-each for numbering
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/>     <xsl:template match="outline">  <xsl:for-each select="section|//item">   <xsl:number level="multiple" count="section | item" format="i. a. "/>   <xsl:value-of select="@title | text(  )"/>   <xsl:text>&#10;</xsl:text>  </xsl:for-each>  <xsl:text>&#10; see http://www.usmint.gov and http://www.bep.treas.gov&#10;</xsl:text> </xsl:template>     </xsl:stylesheet>

The select attribute of for-each can contain an expression. In outline.xsl, the select attribute instructs the processor to iterate through the section elements and (signified by |) all item elements in outline.xml. The two slashes (//) preceding item in the select attribute refer to all item elements that are descendants of the root node in other words, all item elements in the entire source document.

The number element specifies a multilevel count for section and item elements by using the value of multiple for level, meaning that all ancestors will be counted. number also formats the numbers with lowercase Roman numerals on one level and with lowercase letters on another. After the appropriate number is inserted, a value-of grabs title attributes and text nodes. When for-each is done iterating through the nodes, the template adds a couple of URLs on to the end of the result to show where the information came from.

The result of applying outline.xsl to outline.xml with:

xalan outline.xml outline.xsl

is shown in Example 9-19.

Example 9-19. The results of using the stylesheet on multiple levels
i. US coin denominations i. a. cent i. b. nickel i. c. dime i. d. quarter i. e. half dollar i. f. dollar ii. Persons on US coins ii. a. Abraham Lincoln (cent) ii. b. Thomas Jefferson (nickel) ii. c. Franklin Roosevelt (dime) ii. d. George Washington (quarter) ii. e. John Kennedy (half dollar) ii. f. Sacagawea (dollar) iii. US currency in bills iii. a. $1 dollar bill iii. b. $2 dollar bill iii. c. $5 dollar bill iii. d. $10 dollar bill iii. e. $20 dollar bill iii. f. $50 dollar bill iii. g. $100 dollar bill iv. Persons on US bills iv. a. George Washington ($1) iv. b. Thomas Jefferson ($2) iv. c. Abraham Lincoln ($5) iv. d. Alexander Hamilton $10 iv. e. Andrew Jackson ($20) iv. f. Ulysses Grant ($50) iv. g. Benjamin Franklin ($100)     see http://www.usmint.gov and http://www.bep.treas.gov

As a result of using level="multiple", the section nodes are counted at one level with Roman numerals, and the item nodes are counted at another level, alphabetically.

Now I'll clean up the Roman numerals that repeat in the previous example. I want to see the Roman numerals only on the section nodes, and the alphabetical numbering only on the item nodes. The way to make this happen is to number each node-set differently, in separate templates that don't use level="multiple", which is what is done in Example 9-20, better.xsl.

Example 9-20. A cleaner method for numbering on multiple levels manually
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/>     <xsl:template match="outline">  <xsl:apply-templates select="section"/>  <xsl:text>&#10;</xsl:text>  <xsl:text>see http://www.usmint.gov and http://www.bep.treas.gov</xsl:text>  <xsl:text>&#10;</xsl:text> </xsl:template>     <xsl:template match="section">  <xsl:number format="I. "/>  <xsl:value-of select="@title"/>  <xsl:text>&#10;</xsl:text>  <xsl:apply-templates select="item"/> </xsl:template>     <xsl:template match="item">  <xsl:number format=" a. "/>  <xsl:value-of select="text(  )"/>  <xsl:text>&#10;</xsl:text> </xsl:template>     </xsl:stylesheet>

The template that matches the outline node applies templates to section nodes, and the template that matches section nodes applies templates to item nodes, in that order. The template that matches section nodes numbers the section nodes on the single level (the default) using one format, and the template that matches item nodes numbers item nodes also on the single level using a different format. I think the result is more attractive than the previous, multilevel example. When applied to outline.xml, using:

xalan outline.xml better.xsl

better.xsl creates the output shown in Example 9-21.

Example 9-21. A cleaner result
I. US coin denominations  a. cent  b. nickel  c. dime  d. quarter  e. half dollar  f. dollar II. Persons on US coins  a. Abraham Lincoln (cent)  b. Thomas Jefferson (nickel)  c. Franklin Roosevelt (dime)  d. George Washington (quarter)  e. John Kennedy (half dollar)  f. Sacagawea (dollar) III. US currency in bills  a. $1 dollar bill  b. $2 dollar bill  c. $5 dollar bill  d. $10 dollar bill  e. $20 dollar bill  f. $50 dollar bill  g. $100 dollar bill IV. Persons on US bills  a. George Washington ($1)  b. Thomas Jefferson ($2)  c. Abraham Lincoln ($5)  d. Alexander Hamilton $10  e. Andrew Jackson ($20)  f. Ulysses Grant ($50)  g. Benjamin Franklin ($100)     see http://www.usmint.gov and http://www.bep.treas.gov

That looks better. If you increased the depth of the outline by adding child elements to item elements, you could add another template to better.xsl that numbers the new level of nodes and is invoked from the template that processes nodes just above this new level.

9.5.2 More Depth

Now, let's look at a document that has a little more depth, where you can see a varied hierarchy in the elements. Example 9-22, the document data.xml, contains some contact information for several standards organizations headquartered in the United States.

Example 9-22. Information about standards organizations
<?xml version="1.0" encoding="US-ASCII"?> <data locale="us">  <record>   <name>    <full>Internet Assigned Numbers Authority</full>    <brief>IANA</brief>   </name>   <address>    <street>4676 Admiralty Way, Suite 330</street>    <city>Marina del Rey</city>    <state>CA</state>    <code>90292</code>    <nation>USA</nation>   </address>   <tel>    <phone>+1 310 823 9358</phone>    <fax>+1 310 823 8649</fax>    <email>iana@iana.org</email>   </tel>  </record>  <record>   <name>    <full>Internet Society</full>    <brief>ISOC</brief>   </name>   <address>    <street>1775 Wiehle Ave., Suite 102</street>    <city>Reston</city>    <state>VA</state>    <code>20190</code>    <nation>USA</nation>   </address>   <tel>    <phone>+1 703 326 9880</phone>    <fax>+1 703 326 9881</fax>    <email>info@ison.org</email>   </tel>  </record>  <record>   <name>    <full>Organization for the Advancement of Structured Information Standards</full>    <brief>OASIS</brief>   </name>   <address>    <street>630 Boston Rd.</street>    <city>Billerica</city>    <state>MA</state>    <code>01821</code>    <nation>USA</nation>   </address>   <tel>    <phone>+1 978 667 5115</phone>    <fax>+1 978 667 5114</fax>    <email>info@oasis-open.org</email>   </tel>  </record> </data>

The stylesheet shown in Example 9-23, data.xsl, counts all elements on the multiple level from the data element.

Example 9-23. A stylesheet numbering with the from element
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:strip-space elements="*"/>     <xsl:template match="/">  <xsl:apply-templates select="data//*"/> </xsl:template>     <xsl:template match="data//*">  <xsl:number level="multiple" count="*" from="data" format="1.1.1 "/>  <xsl:value-of select="name(  )"/>  <xsl:text>: </xsl:text>  <xsl:text>&#9;</xsl:text>  <xsl:value-of select="text(  )"/>  <xsl:text>&#10;</xsl:text> </xsl:template>     </xsl:stylesheet>

I'll discuss the from attribute in a moment. data.xsl prints each element's name with its immediate text node children, with each name preceded by a formatted section number and interspersed with a colon and whitespace. The result of processing data.xml with data.xsl with:

xalan data.xml data.xsl

is shown in Example 9-24.

Example 9-24. Results with section numbering
1 record: 1.1 name: 1.1.1 full:    Internet Assigned Numbers Authority 1.1.2 brief:   IANA 1.2 address: 1.2.1 street:  4676 Admiralty Way, Suite 330 1.2.2 city:    Marina del Rey 1.2.3 state:   CA 1.2.4 code:    90292 1.2.5 nation:  USA 1.3 tel: 1.3.1 phone:   +1 310 823 9358 1.3.2 fax:     +1 310 823 8649 1.3.3 email:   iana@iana.org 2 record: 2.1 name: 2.1.1 full:    Internet Society 2.1.2 brief:   ISOC 2.2 address: 2.2.1 street:  1775 Wiehle Ave., Suite 102 2.2.2 city:    Reston 2.2.3 state:   VA 2.2.4 code:    20190 2.2.5 nation:  USA 2.3 tel: 2.3.1 phone:   +1 703 326 9880 2.3.2 fax:     +1 703 326 9881 2.3.3 email:   info@ison.org 3 record: 3.1 name: 3.1.1 full:    Organization for the Advancement of Structured Information Standards 3.1.2 brief:   OASIS 3.2 address: 3.2.1 street:  630 Boston Rd. 3.2.2 city:    Billerica 3.2.3 state:   MA 3.2.4 code:    01821 3.2.5 nation:  USA 3.3 tel: 3.3.1 phone:   +1 978 667 5115 3.3.2 fax:     +1 978 667 5114 3.3.3 email:   info@oasis-open.org

The numbering in Example 9-24 shows the structure of the elements and the hierarchical relationship of these elements to each other. It also shows how markup can be structured into numbered sections that technical or legal documents sometimes require.

9.5.3 Counting on Any Level

I'll now show you the difference between counting with multiple levels compared to counting on any level. The stylesheet any.xsl is a little different than outline.xsl: the value of level is any instead of multiple, and the value of format is also changed (i. a. becomes 1.). When you process outline.xml with any.xsl:

xalan outline.xml any.xsl

you get the result shown in Example 9-25.

Example 9-25. Results of numbering using the any level
1. US coin denominations 2. cent 3. nickel 4. dime 5. quarter 6. half dollar 7. dollar 8. Persons on US coins 9. Abraham Lincoln (cent) 10. Thomas Jefferson (nickel) 11. Franklin Roosevelt (dime) 12. George Washington (quarter) 13. John Kennedy (half dollar) 14. Sacagawea (dollar) 15. US currency in bills 16. $1 dollar bill 17. $2 dollar bill 18. $5 dollar bill 19. $10 dollar bill 20. $20 dollar bill 21. $50 dollar bill 22. $100 dollar bill 23. Persons on US bills 24. George Washington ($1) 25. Thomas Jefferson ($2) 26. Abraham Lincoln ($5) 27. Alexander Hamilton $10 28. Andrew Jackson ($20) 29. Ulysses Grant ($50) 30. Benjamin Franklin ($100)     see http://www.usmint.gov and http://www.bep.treas.gov

Using the any level produces a sequential numbering of all nodes no matter what level they are on. This could be useful, for example, when numbering diagrams in a document.



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