<xsl:number> | |
Counts something. It is most often used to number parts of a document, although it can also be used to format a numeric value. | |
Category | |
Instruction |
|
Required Attributes | |
None. |
|
Optional Attributes | |
|
|
Content | |
None. <xsl:number> is an empty element. |
|
Appears in | |
<xsl:number> appears inside a template. |
|
Defined in | |
XSLT section 7.7, Numbering. |
|
Example | |
To fully illustrate how <xsl:number> works, we'll need an XML document with many things to count. Here's the document we'll use: <?xml version="1.0"?> <book> <chapter> <title>Alfa Romeo</title> <sect1> <title>Bentley</title> </sect1> <sect1> <title>Chevrolet</title> <sect2> <title>Dodge</title> <sect3> <title>Eagle</title> </sect3> </sect2> </sect1> </chapter> <chapter> <title>Ford</title> <sect1> <title>GMC</title> <sect2> <title>Honda</title> <sect3> <title>Isuzu</title> </sect3> <sect3> <title>Javelin</title> </sect3> <sect3> <title>K-Car</title> </sect3> <sect3> <title>Lincoln</title> </sect3> </sect2> <sect2> <title>Mercedes</title> </sect2> <sect2> <title>Nash</title> <sect3> <title>Opel</title> </sect3> <sect3> <title>Pontiac</title> </sect3> </sect2> <sect2> <title>Quantum</title> <sect3> <title>Rambler</title> </sect3> <sect3> <title>Studebaker</title> </sect3> </sect2> </sect1> <sect1> <title>Toyota</title> <sect2> <title>Um, is there a car that starts with "U"?</title> </sect2> </sect1> <sect1> <title>Volkswagen</title> </sect1> </chapter> </book> We'll use <xsl:number> in several different ways to illustrate the various options we have in numbering things. We'll look at the stylesheet and the results, then we'll discuss them. Here's the stylesheet: <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:variable name="newline"> <xsl:text> </xsl:text> </xsl:variable> <xsl:template match="/"> <xsl:value-of select="$newline"/> <xsl:apply-templates select="book" mode="number-1"/> <xsl:apply-templates select="book" mode="number-2"/> <xsl:apply-templates select="book" mode="number-3"/> <xsl:apply-templates select="book" mode="number-4"/> <xsl:apply-templates select="book" mode="number-5"/> <xsl:apply-templates select="book" mode="number-6"/> <xsl:apply-templates select="book" mode="number-7"/> </xsl:template> <xsl:template match="book" mode="number-1"> <xsl:text>Test #1: level="multiple", count="chapter|sect1|sect2|sect3", format="1.1.1.1. "</xsl:text> <xsl:value-of select="$newline"/> <xsl:value-of select="$newline"/> <xsl:for-each select="chapter|.//sect1|.//sect2|.//sect3"> <xsl:number level="multiple" count="chapter|sect1|sect2|sect3" format="1.1.1.1. "/> <xsl:value-of select="title"/> <xsl:value-of select="$newline"/> </xsl:for-each> <xsl:value-of select="$newline"/> </xsl:template> <xsl:template match="book" mode="number-2"> <xsl:text>Test #2: level="any", count="chapter|sect1|sect2|sect3", format="1. "</xsl:text> <xsl:value-of select="$newline"/> <xsl:value-of select="$newline"/> <xsl:for-each select="chapter|.//sect1|.//sect2|.//sect3"> <xsl:number level="any" count="chapter|sect1|sect2|sect3" format="1. "/> <xsl:value-of select="title"/> <xsl:value-of select="$newline"/> </xsl:for-each> <xsl:value-of select="$newline"/> </xsl:template> <xsl:template match="book" mode="number-3"> <xsl:text>Test #3: level="single", count="chapter|sect1|sect2|sect3", format="1.1.1.1. "</xsl:text> <xsl:value-of select="$newline"/> <xsl:value-of select="$newline"/> <xsl:for-each select="chapter|.//sect1|.//sect2|.//sect3"> <xsl:number level="single" count="chapter|sect1|sect2|sect3" format="1.1.1.1. "/> <xsl:value-of select="title"/> <xsl:value-of select="$newline"/> </xsl:for-each> <xsl:value-of select="$newline"/> </xsl:template> <xsl:template match="book" mode="number-4"> <xsl:text>Test #4: level="multiple", select=".//sect2", count="chapter|sect1|sect2", format="I-A-i: "</xsl:text> <xsl:value-of select="$newline"/> <xsl:value-of select="$newline"/> <xsl:for-each select=".//sect2"> <xsl:number level="multiple" count="chapter|sect1|sect2" format="I-A-i: "/> <xsl:value-of select="title"/> <xsl:value-of select="$newline"/> </xsl:for-each> <xsl:value-of select="$newline"/> </xsl:template> <xsl:template match="book" mode="number-5"> <xsl:text>Test #5: level="any", count="[various elements]" from="[various elements]" format="1.1.1.1. "</xsl:text> <xsl:value-of select="$newline"/> <xsl:value-of select="$newline"/> <xsl:for-each select=".//sect3"> <xsl:number level="any" from="book" count="chapter" format="1."/> <xsl:number level="any" from="chapter" count="sect1" format="1."/> <xsl:number level="any" from="sect1" count="sect2" format="1."/> <xsl:number level="any" from="sect2" count="sect3" format="1. "/> <xsl:value-of select="title"/> <xsl:value-of select="$newline"/> </xsl:for-each> <xsl:value-of select="$newline"/> </xsl:template> <xsl:template match="book" mode="number-6"> <xsl:text>Test #6: level="any", count="chapter|sect1|sect2|sect3", grouping-separator=",", using a variable to start counting at 1000.</xsl:text> <xsl:value-of select="$newline"/> <xsl:value-of select="$newline"/> <xsl:for-each select="chapter|.//sect1|.//sect2|.//sect3"> <xsl:variable name="value1"> <xsl:number level="any" count="chapter|sect1|sect2|sect3"/> </xsl:variable> <xsl:number value="$value1 + 999" grouping-separator="." grouping-size="3"/> <xsl:text>. </xsl:text> <xsl:value-of select="title"/> <xsl:value-of select="$newline"/> </xsl:for-each> <xsl:value-of select="$newline"/> </xsl:template> <xsl:template match="book" mode="number-7"> <xsl:text>Test #7: level="multiple", count="chapter|sect1|sect2|sect3", format="1.1.1.1. ", selecting up to the first two <sect1> elements from chapter 2.</xsl:text> <xsl:value-of select="$newline"/> <xsl:value-of select="$newline"/> <xsl:for-each select="chapter[2]/sect1[position() < 3]"> <xsl:for-each select="chapter|.//sect1|.//sect2|.//sect3"> <xsl:number level="multiple" count="chapter|sect1|sect2|sect3" format="1.1.1.1. "/> <xsl:value-of select="title"/> <xsl:value-of select="$newline"/> </xsl:for-each> </xsl:for-each> </xsl:template> </xsl:stylesheet> Here are our results: Test #1: level="multiple", count="chapter|sect1|sect2|sect3", format="1.1.1.1. " 1. Alfa Romeo 1.1. Bentley 1.2. Chevrolet 1.2.1. Dodge 1.2.1.1. Eagle 2. Ford 2.1. GMC 2.1.1. Honda 2.1.1.1. Isuzu 2.1.1.2. Javelin 2.1.1.3. K-Car 2.1.1.4. Lincoln 2.1.2. Mercedes 2.1.3. Nash 2.1.3.1. Opel 2.1.3.2. Pontiac 2.1.4. Quantum 2.1.4.1. Rambler 2.1.4.2. Studebaker 2.2. Toyota 2.2.1. Um, is there a car that starts with "U"? 2.3. Volkswagen Test #2: level="any", count="chapter|sect1|sect2|sect3", format="1. " 1. Alfa Romeo 2. Bentley 3. Chevrolet 4. Dodge 5. Eagle 6. Ford 7. GMC 8. Honda 9. Isuzu 10. Javelin 11. K-Car 12. Lincoln 13. Mercedes 14. Nash 15. Opel 16. Pontiac 17. Quantum 18. Rambler 19. Studebaker 20. Toyota 21. Um, is there a car that starts with "U"? 22. Volkswagen Test #3: level="single", count="chapter|sect1|sect2|sect3", format="1.1.1.1. " 1. Alfa Romeo 1. Bentley 2. Chevrolet 1. Dodge 1. Eagle 2. Ford 1. GMC 1. Honda 1. Isuzu 2. Javelin 3. K-Car 4. Lincoln 2. Mercedes 3. Nash 1. Opel 2. Pontiac 4. Quantum 1. Rambler 2. Studebaker 2. Toyota 1. Um, is there a car that starts with "U"? 3. Volkswagen Test #4: level="multiple", select=".//sect2", count="chapter|sect1|sect2", format="I-A-i: " I-B-i: Dodge II-A-i: Honda II-A-ii: Mercedes II-A-iii: Nash II-A-iv: Quantum II-B-i: Um, is there a car that starts with "U"? Test #5: level="any", count="[various elements]" from="[various elements]" format="1.1.1.1. " 1.2.1.1. Eagle 2.1.1.1. Isuzu 2.1.1.2. Javelin 2.1.1.3. K-Car 2.1.1.4. Lincoln 2.1.3.1. Opel 2.1.3.2. Pontiac 2.1.4.1. Rambler 2.1.4.2. Studebaker Test #6: level="any", count="chapter|sect1|sect2|sect3", grouping-separator=",", using a variable to start counting at 1000. 1,000. Alfa Romeo 1,001. Bentley 1,002. Chevrolet 1,003. Dodge 1,004. Eagle 1,005. Ford 1,006. GMC 1,007. Honda 1,008. Isuzu 1,009. Javelin 1,010. K-Car 1,011. Lincoln 1,012. Mercedes 1,013. Nash 1,014. Opel 1,015. Pontiac 1,016. Quantum 1,017. Rambler 1,018. Studebaker 1,019. Toyota 1,020. Um, is there a car that starts with "U"? 1,021. Volkswagen Test #7: level="multiple", count="chapter|sect1|sect2|sect3", format="1.1.1.1. ", selecting up to the first two <sect1> elements from chapter 2. 2.1. GMC 2.1.1. Honda 2.1.1.1. Isuzu 2.1.1.2. Javelin 2.1.1.3. K-Car 2.1.1.4. Lincoln 2.1.2. Mercedes 2.1.3. Nash 2.1.3.1. Opel 2.1.3.2. Pontiac 2.1.4. Quantum 2.1.4.1. Rambler 2.1.4.2. Studebaker 2.2. Toyota 2.2.1. Um, is there a car that starts with "U"? In Test 1, we used level="multiple" to count the <chapter>, <sect1>, <sect2>, and <sect3> elements. Numbering these at multiple levels gives us a dotted-decimal number for each element. We can look at the number next to Studebaker and know that it is the second <sect3> element inside the fourth <sect2> element inside the first <sect1> element inside the second <chapter> element. Test 2 uses level="any" to count all of the <chapter>, <sect1>, <sect2>, and <sect3> elements in order. Test 3 uses level="single" to count the elements at each level. This means that the fourth <sect3> element inside a given <sect2> element will be numbered with a 4 (or iv or D or whatever the appropriate value would be). Notice that the number used for each element is the same as the last number beside each element in Test 1. Test 4 does a couple of things differently: first, it uses the uppercase-alpha and lowercase-roman numbering styles. Second, it counts elements at multiple levels (for the <chapter>, <sect1>, and <sect2> elements), but we only process the <sect2> elements. Even though we only output the title text for the <sect2> elements, we can still generate the appropriate multilevel numbers. Test 5 generates numbers similarly to Test 4, except that it uses the from attribute. We generate numbers for <sect3> elements in four stages; first, we count the <chapter> ancestors, starting at the first <book> ancestor; then we count the <sect1> ancestors, starting at the first <chapter> ancestor, etc. Test 6 starts counting at 1000 instead of 1. To do this, we have to store the value generated by <xsl:number> in a variable, then output the value of the variable plus 1000. Notice that we can use an expression in the value attribute of the <xsl:number> element. We also used the grouping-separator attribute to use a comma to separate groups of three digits. Last but not least, Test 7 only numbers items from the first and second <sect1> elements (<sect1> elements whose position() is less than 3) in the second <chapter> element. Even though we're only processing these sections, we can still use <xsl:number> to generate the correct numbers for the elements. |