[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: multi-levels counter

Subject: Re: multi-levels counter
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Mon, 10 Jun 2002 16:46:18 +0100
ntext number
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

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.