This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Counting number of characters of sibling text node
- From: Dimitre Novatchev <dnovatchev at yahoo dot com>
- To: xsl-list at lists dot mulberrytech dot com
- Date: Wed, 22 May 2002 06:30:17 -0700 (PDT)
- Subject: [xsl] Re: Counting number of characters of sibling text node
- Reply-to: xsl-list at lists dot mulberrytech dot com
> 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>
</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