[xsl] Re: Counting number of characters of sibling text node

Subject: [xsl] Re: Counting number of characters of sibling text node
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Wed, 22 May 2002 06:30:17 -0700 (PDT)
> What I want to do is to count the number os characters in a  text 
> node and all previous text nodes children of the current text node's
> parent.
> 
>            parent
>               |
>   ----------------------------
>   |        |        |         |
> text1 <br/>  text2  <br/>
> 
> 
>   When having text1 has the current node my template would return the
> number of characters of text1 but when having text2 has the current 
> node my template would return the sum of number of characters of 
> text1 with number of characters of text2.
> 
>   I've tried using the following template:
> 
> <xsl:template match="text()" mode="getStrLen">
>    <xsl:variable name="pastTxtLen"><xsl:apply-templates 
> select="preceding-sibling::text()[1]" 
> mode="getStrLen"/></xsl:variable>
>    <xsl:value-of select="string-length($pastTxtLen) + string-length
> (.)" />
> </xsl:template>
> 
> I get it's result by doing: 
> <xsl:variable name="pastTxtLen"><xsl:apply-templates select="." 
> mode="getStrLen"/></xsl:variable>
> 
> Doing it this way I get the rong result.
> For the example above, when I have text1 has the current node it 
> works fine(the number of characters of text1 only is returned) but 
> when I have text2 has the current node a rong result.
> 
>    Any suggestions?

You're almost there, just two things:

1. Change 

>    <xsl:value-of select="string-length($pastTxtLen) + string-length
> (.)" />

to

    <xsl:value-of select="$pastTxtLen + string-length(.)" />


2. In case there are no preceding siblings that are text nodes, the
value of $pastTxtLen will be the empty nodeset, which is not a number.
As a result you'll get NaN adding to it anything. Therefore, you need
to process this special case in an appropriate way.

Here's one solution:

stylesheet:
----------
<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
 <xsl:output omit-xml-declaration="yes"/>
 
 <xsl:strip-space elements="*"/>
 
  <xsl:template match="/">

    <xsl:for-each select="/t/text()">
      <xsl:apply-templates select="." mode="getStrLen"/>
      <xsl:text>&#xA;</xsl:text>
    </xsl:for-each>
  </xsl:template>
  <xsl:template match="text()" mode="getStrLen">
    <xsl:variable name="vPrecText" 
         select="preceding-sibling::text()[1]"/>
    <xsl:variable name="pastTxtLen">
      <xsl:choose>
        <xsl:when test="$vPrecText">
          <xsl:apply-templates mode="getStrLen"
               select="$vPrecText[1]" />
        </xsl:when>
        <xsl:otherwise>0</xsl:otherwise>
      </xsl:choose> 
    </xsl:variable>
    <xsl:value-of select="$pastTxtLen + string-length(.)" />
  </xsl:template>
</xsl:stylesheet>

source xml:
----------
<t><br/>a<br/>ab<br/>abc<br/>abcd</t>

Result:
------
1
3
6
10


Cheers,
Dimitre Novatchev.




__________________________________________________
Do You Yahoo!?
LAUNCH - Your Yahoo! Music Experience
http://launch.yahoo.com

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread