The xsl:number Element

The <xsl:number> Element

You use <xsl:number> to assign a number in a sequence to a node in the result document. For example, you can number paragraphs in a contract or stanzas in a poem. You can even number parts of a document down to multiple levels, such as Paragraph 3.2.5.1. and so on.

Here are the <xsl:number> elements attributes:

  • level (optional). Determines how sequence numbers are assigned. Set to single, multiple, or any. The default is single.

  • count (optional). Determines which nodes are to be counted. Set to a pattern.

  • from (optional). Determines the point at which counting starts. Set to a pattern.

  • value (optional). A number to be formatted.

  • format (optional). Determines the output format. Set to an attribute value template that returns a format string.

  • lang (optional). Determines the language whose conventions to use for numbering. Set to a language code that you can use with the xml:lang attribute.

  • letter-value (optional). Enables you to distinguish between different numbering schemes. Set to alphabetical or traditional.

  • grouping-separator (optional). A character used to separate groups of digits, such as a comma. Set to an attribute value template that returns a single character.

  • grouping- size (optional). Number of digits in each groupdetermines where the grouping separator should be used. Set to an attribute value template that returns a number.

A Tip for Numbering

As you can see from this list of attributes, theres quite an array of options when it comes to numbering schemes. In fact, numbering operations can become quite complex, so heres a tip: if the numbering becomes too difficult and convoluted, I just produce the result document without numbering, then use a second stylesheet that applies the numbering.

There are three main ways of applying numbering, depending on how you set the level attribute: single, multiple, or any. The following sections look at each of these schemes in turn , starting with single numbering, which is the default.

Single-Level Numbering

Single-level numbering is simple numbering, where youre just numbering sibling nodes on the same level. This is the default type of numbering. Heres an example where Im using single numbering to number the planets in planets.xml:

Listing 5.11 Single-Level Numbering
 <?xml version="1.0"?>  <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">      <xsl:template match="/PLANETS">          <HTML>              <HEAD>                  <TITLE>                      The Planets Table                  </TITLE>              </HEAD>              <BODY>                  <H1>                      The Planets Table                  </H1>                  <TABLE BORDER="2">                      <TR>                          <TD>Name</TD>                          <TD>Mass</TD>                          <TD>Radius</TD>                          <TD>Day</TD>                      </TR>                      <xsl:apply-templates/>                  </TABLE>              </BODY>          </HTML>      </xsl:template>      <xsl:template match="PLANET">         <TR>            <TD><xsl:number/>. <xsl:value-of select="NAME"/></TD>            <TD><xsl:apply-templates select="MASS"/></TD>            <TD><xsl:apply-templates select="RADIUS"/></TD>            <TD><xsl:apply-templates select="DAY"/></TD>         </TR>     </xsl:template>      <xsl:template match="MASS">          <xsl:value-of select="."/>          <xsl:text> </xsl:text>          <xsl:value-of select="@UNITS"/>      </xsl:template>          .          .          .      <xsl:template match="DAY">          <xsl:value-of select="."/>          <xsl:text> </xsl:text>          <xsl:value-of select="@UNITS"/>      </xsl:template>  </xsl:stylesheet> 

And heres the result:

 <HTML>      <HEAD>          <TITLE>              The Planets Table          </TITLE>      </HEAD>      <BODY>          <H1>              The Planets Table          </H1>          <TABLE BORDER="2">              <TR>                  <TD>Name</TD>                  <TD>Mass</TD>                  <TD>Radius</TD>                  <TD>Day</TD>              </TR>              <TR>                  <TD>1. Mercury</TD>                  <TD>.0553 (Earth = 1)</TD>                  <TD>1516 miles</TD>                  <TD>58.65 days</TD>              </TR>              <TR>                  <TD>2. Venus</TD>                  <TD>.815 (Earth = 1)</TD>                  <TD>3716 miles</TD>                  <TD>116.75 days</TD>              </TR>              <TR>                  <TD>3. Earth</TD>                  <TD>1 (Earth = 1)</TD>                  <TD>2107 miles</TD>                  <TD>1 days</TD>              </TR>          </TABLE>      </BODY>  </HTML> 

You can see this result in Figure 5.2.

Figure 5.2. Single numbering of elements.
graphics/05fig02.gif

By default, numbering uses digits, but there are other options. For example, if I had used <xsl:number format="a"/> , the planets would have been assigned a., b., and c.:

 <HTML>      <HEAD>          <TITLE>              The Planets Table          </TITLE>      </HEAD>      <BODY>          <H1>              The Planets Table          </H1>          <TABLE BORDER="2">              <TR>                  <TD>Name</TD>                  <TD>Mass</TD>                  <TD>Radius</TD>                  <TD>Day</TD>              </TR>              <TR>                  <TD>a. Mercury</TD>                  <TD>.0553 (Earth = 1)</TD>                  <TD>1516 miles</TD>                  <TD>58.65 days</TD>              </TR>              <TR>                  <TD>b. Venus</TD>                  <TD>.815 (Earth = 1)</TD>                  <TD>3716 miles</TD>                  <TD>116.75 days</TD>              </TR>          .          .          . 

Here are the possible tokens you can use in the format attribute and what kinds of numbering they produce:

  • 1 generates 1, 2, 3...

  • 01 generates 01, 02, 03...

  • Other Unicode digits in other numbering systems follow the same two preceding rules.

  • a generates a, b, c...aa, ab...

  • A generates A, B, C...AA, AB...

  • i generates i, ii, iii, iv...ix, x, xi, xii...

  • I generates I, II, III, IV...IX, X, XI, XII...

Any-Level Numbering

Sometimes, you might want to just count nodes of a specific type, no matter at what level they appear in the document. For example, you might have multiple <NAME> elements that appear at different places in a documents hierarchy, and you might simply want to treat the document as a stream of data, counting <NAME> elements as you encounter them.

Heres how it might look if you had <NAME> elements at different levels in planets.xml:

 <?xml version="1.0"?>  <?xml-stylesheet type="text/xml" href="planets.xsl"?>  <PLANETS>      <TITLE>           <NAME>Planets Table</NAME>      </TITLE>      <PLANET>          <NAME>Mercury</NAME>          <MASS UNITS="(Earth = 1)">.0553</MASS>          <DAY UNITS="days">58.65</DAY>          <RADIUS UNITS="miles">1516</RADIUS>          <DENSITY UNITS="(Earth = 1)">.983</DENSITY>          <DISTANCE UNITS="million miles">43.4</DISTANCE><!--At perihelion-->      </PLANET>      <PLANET>          <NAME>Venus</NAME>          <MASS UNITS="(Earth = 1)">.815</MASS>          <DAY UNITS="days">116.75</DAY>          <RADIUS UNITS="miles">3716</RADIUS>          <DENSITY UNITS="(Earth = 1)">.943</DENSITY>          <DISTANCE UNITS="million miles">66.8</DISTANCE><!--At perihelion-->      </PLANET>          .          .          . 

To count the total number of <NAME> elements, I can set the level attribute to any in a stylesheet:

Listing 5.12 Any-Level Numbering
 <?xml version="1.0"?>  <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">      <xsl:template match="/PLANETS">          <HTML>              <HEAD>                  <TITLE>                      The Planets Table                  </TITLE>              </HEAD>              <BODY>                  <H1>                      The Planets Table                  </H1>                  <xsl:apply-templates select="TITLE"/>                  <TABLE BORDER="2">                      <TR>                          <TD>Name</TD>                          <TD>Mass</TD>                          <TD>Radius</TD>                          <TD>Day</TD>                      </TR>                      <xsl:apply-templates select="PLANET"/>                  </TABLE>              </BODY>          </HTML>      </xsl:template>      <xsl:template match="PLANET">         <TR>            <TD><xsl:apply-templates select="NAME"/></TD>            <TD><xsl:apply-templates select="MASS"/></TD>            <TD><xsl:apply-templates select="RADIUS"/></TD>            <TD><xsl:apply-templates select="DAY"/></TD>         </TR>     </xsl:template>      <xsl:template match="TITLE">          <xsl:apply-templates/>      </xsl:template>      <xsl:template match="NAME">          <xsl:number level="any" count="NAME"/>. <xsl:value-of select="."/>      </xsl:template>      <xsl:template match="MASS">          <xsl:value-of select="."/>          <xsl:text> </xsl:text>          <xsl:value-of select="@UNITS"/>      </xsl:template>          .          .          .      <xsl:template match="DAY">          <xsl:value-of select="."/>          <xsl:text> </xsl:text>          <xsl:value-of select="@UNITS"/>      </xsl:template>  </xsl:stylesheet> 

And heres the resultnote that the text from each <NAME> element, no matter where it appears in the document, is numbered:

 <HTML>      <HEAD>          <TITLE>              The Planets Table          </TITLE>      </HEAD>      <BODY>          <H1>              The Planets Table          </H1>          1. Planets Table          <TABLE BORDER="2">              <TR>                  <TD>Name</TD>                  <TD>Mass</TD>                  <TD>Radius</TD>                  <TD>Day</TD>              </TR>              <TR>                  <TD>2. Mercury</TD>                  <TD>.0553 (Earth = 1)</TD>                  <TD>1516 miles</TD>                  <TD>58.65 days</TD>              </TR>              <TR>                  <TD>3. Venus</TD>                  <TD>.815 (Earth = 1)</TD>                  <TD>3716 miles</TD>                  <TD>116.75 days</TD>              </TR>              <TR>                  <TD>4. Earth</TD>                  <TD>1 (Earth = 1)</TD>                  <TD>2107 miles</TD>                  <TD>1 days</TD>              </TR>          </TABLE>      </BODY>  </HTML> 

You can also use the from attribute to indicate from which ancestor node to start counting; for example, if you set the ancestor node to a <PLANET> element as follows :

 <xsl:number level="any" count="NAME" from="PLANET"/> 

then the XSLT processor would count back only until it finds a <PLANET> ancestor, and start numbering from that point in the document.

Multiple-Level Numbering

The <xsl:number> element also supports multi-level numbering, such as 3.1.2.5 and so on. To use multiple-level numbering, you set the level attribute to multiple. You can also indicate what type of nodes you want to number with the count attribute, setting it to a pattern, such as PARTCHAPTERPARAGRAPH. When processing <xsl:number> elements, the XSLT processor numbers nodes to match the document hierarchy.

In this example, I number every level in the element hierarchy of planets.xml, setting the count attribute to * to match all elements. I can also indicate the format I want to use for numbering with the format attribute. With multi-level numbering, you set the format attribute to indicate the numbering you want to use for various levels, as in 1.1.1. to number the top-level nodes 1., 2., and so on, the next level down 1.1., 1.2., and so on, and the next level down 1.2.1., 1.2.2., and so on. Heres what the stylesheet in this example looks like:

Listing 5.13 Multiple-Level Numbering
 <?xml version="1.0"?>  <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  <xsl:output method="xml"/>    <xsl:template match="node()">      <xsl:copy>        <xsl:number format="1.1.1. " level="multiple" count="*"/>        <xsl:apply-templates select="node()"/>      </xsl:copy>    </xsl:template>  </xsl:stylesheet> 

And heres the result of transforming planets.xml into a new XML document with all element levels numbered to show the document hierarchy:

 <?xml version="1.0" encoding="utf-8"?>  <?xml-stylesheet type="text/xml" href="planets.xsl"?>  <PLANETS>1.      <PLANET>1.1.          <NAME>1.1.1. Mercury</NAME>          <MASS>1.1.2. .0553</MASS>          <DAY>1.1.3. 58.65</DAY>          <RADIUS>1.1.4. 1516</RADIUS>          <DENSITY>1.1.5. .983</DENSITY>          <DISTANCE>1.1.6. 43.4</DISTANCE><!--At perihelion-->      </PLANET>      <PLANET>1.2.          <NAME>1.2.1. Venus</NAME>          <MASS>1.2.2. .815</MASS>          <DAY>1.2.3. 116.75</DAY>          <RADIUS>1.2.4. 3716</RADIUS>          <DENSITY>1.2.5. .943</DENSITY>          <DISTANCE>1.2.6. 66.8</DISTANCE><!--At perihelion-->      </PLANET>      <PLANET>1.3.          <NAME>1.3.1. Earth</NAME>          <MASS>1.3.2. 1</MASS>          <DAY>1.3.3. 1</DAY>          <RADIUS>1.3.4. 2107</RADIUS>          <DENSITY>1.3.5. 1</DENSITY>          <DISTANCE>1.3.6. 128.4</DISTANCE><!--At perihelion-->      </PLANET>  </PLANETS> 

That completes this look at document numbering; the final topic in this chapter is XSLT extensibility , and Ill turn to that now.



Inside XSLT
Inside Xslt
ISBN: B0031W8M4K
EAN: N/A
Year: 2005
Pages: 196

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