| 
 
Subject: Re: [xsl] multi-levels counter From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Mon, 10 Jun 2002 16:46:18 +0100  | 
Hi Allen,
> How can I keep a counter for each <text> segment? Thanks in
> advance!!
The method that most closely resembles your description is to turn the
natural rule-based processing model of XSLT into a procedural one by
stepping through the elements one by one, passing a parameter down
through each call.
Doing that is quite ugly and can make it difficult to get a structured
result, so it's probably easier to rephrase what you want to do to
"How can I assign a number to each text segment based on its position
relative to all the other text segments in the document?"
There's a natural solution to that in XSLT, namely xsl:number. Doing:
<xsl:template match="text">
  <xsl:number level="any" format="1." />
  <xsl:value-of select="." />
</xsl:template>
will produce output with numbers like '1.', '2.' for each text element
in the document.
xsl:number actually works by, for each text element, looking at all
the preceding nodes in the tree, finding text elements amongst them,
and counting them. That can be quite a lot of node visits in a large
document, which would be quite slow. If speed is an issue, then you
could try a partial version of the step-by-step method mentioned
above, which would be something like:
<xsl:template match="*">
  <!-- $ntext keeps track of the number of text elements so far -->
  <xsl:param name="ntext" select="0" />
  <!-- create a copy of this element -->
  <xsl:copy>
    <xsl:copy-of select="@*" />
    <!-- pass $ntext on to the first child of this element -->
    <xsl:apply-templates select="*[1]">
      <xsl:with-param name="ntext" select="$ntext" />
    </xsl:apply-templates>
  </xsl:copy>
  <!-- move on to the next sibling of this element, adding the number
       of text element children of this one to the count -->
  <xsl:apply-templates select="following-sibling::*[1]">
    <xsl:with-param name="ntext" select="$ntext + count(.//text)" />
  </xsl:apply-templates>
</xsl:template>
<xsl:template match="text">
  <xsl:param name="ntext" select="0" />
  <!-- give the number, followed by the text segment -->
  <xsl:value-of select="$ntext" />. <xsl:value-of select="." />
  <!-- move on to the next sibling of this element, adding one to the
       count -->
  <xsl:apply-templates select="following-sibling::*[1]">
    <xsl:with-param name="ntext" select="$ntext + 1" />
  </xsl:apply-templates>
</xsl:template>
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
| Current Thread | 
|---|
  | 
| <- Previous | Index | Next -> | 
|---|---|---|
| [xsl] multi-levels counter, Allen Chu | Thread | RE: [xsl] multi-levels counter, Michael Kay | 
| [xsl] How to generate Tag by parame, CAO Tuan Dung | Date | Re: [xsl] How to generate Tag by pa, Jeni Tennison | 
| Month |