Re: [xsl] Creating a hierarchical table of contents using xsl:number

Subject: Re: [xsl] Creating a hierarchical table of contents using xsl:number
From: Syd Bauman <Syd_Bauman@xxxxxxxxx>
Date: Tue, 16 Feb 2010 15:17:28 -0500
I think you may be working too hard, and that the following will do
what you want:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  xmlns:xs="http://www.w3.org/2001/XMLSchema";
  version="2.0">
  
  <xsl:output indent="yes" method="xml"/>
  
  <xsl:template match="/">
    <wrap>
      <xsl:apply-templates select="//level1 | //level2 | //level3"/>
    </wrap>
  </xsl:template>

  <xsl:template match="level1|level2|level3">
    <xsl:number level="multiple" count="level1|level2|level3" format="1.1. "/>
    <xsl:value-of select="@title"/><br/><xsl:text>&#x0A;</xsl:text>
  </xsl:template>

</xsl:stylesheet>


It is worth reading the discussion of <xsl:number> in a worthwhile
reference (I use Kay's) a few times, and playing around with it.



Martin Jackson writes:
> I'm trying to create a table of content that looks like this:
> 
> 1. Fruit
> 1.1. Citrus
> 1.1.1. Orange
> 1.1.2. Lemon
> 1.1.3. Lime
> 1.2. Apple
> 2. Vegetables
> 2.1. Tomato
> 2.2. Carrot
> 
> 
> from an xml file with this structure
> 
> <level1 title="fruit">
>    <level2 title="citrus">
>       <level3 title="orange"/>
>       <level3 title="lemon"/>
>       <level3 title="lime"/>
>    </level2>
>    <level2 title="apple"/>
> </level1>
> <level1 title="vegetables">
>    <level2 title="tomato"/>
>    <level2 title="carrot"/>
> 
> 
> But I can't figure out how to make my xsl transformation write the
> numbers for all the levels in the hierarchy. Right now it just outputs
> the bottom level, so it looks like this:
> 
> 1. Fruit
> 1. Citrus
> 1. Orange
> 2. Lemon
> 3. Lime
> 2. Apple
> 2. Vegetables
> 1 Tomato
> 2 Carrot
> 
> 
> This is what my code looks like:
> 
> <xsl:for-each select="level1">
>       <xsl:number level="multiple" count="h1" value="position()" format="1.1. "/>
>       <xsl:value-of select="@title"/><br />
>                       
>       <xsl:for-each select="level2">
>               <xsl:number level="multiple" count="h1|h2" value="position()" format="1.1. "/>
>               <xsl:value-of select="@title"/><br />
>                               
>               <xsl:for-each select="level3">
>                       <xsl:number level="multiple" count="h1|h2|h3" value="position()"
> format="1.1.  "/>
>                       <xsl:value-of select="@title"/><br />
>               </xsl:for-each>         
>       </xsl:for-each> 
> </xsl:for-each>
> 
> From some stuff I have read I have gathered that this probably should
> be possible to solve without nested for-each-loops, with just one
> <xsl:number> tag having correctly formulated attributes. But for
> reasons hard to explain, right now I need to solve this using
> for-each.
> 
> So I have two questions:
> 1. Is it possible to solve it using roughly the structure I have now,
> with the for-each-loops, and how would I do that?
> 2. If that code structure is unnecessarily complicated (which I
> suspects it is), what would be a more optimal way of achieving the
> same result (still using xsl:number)?
> 
> Regards,
> Martin Jackson

Current Thread