xsl:variable question

sylvain.loiseau

Usenet Archive
Joined
Oct 29, 2003
Messages
10
Reaction score
0
Hello

Given a node set, I try to compute the total of the string-length value of each node.

For instance, with :

<xsl:for-each select="//q">
<!-- the length of each node is compute with: -->
<xsl:value-of select="string-length(.)" />
</xsl:for-each>

but how to get the total of the different values, since xsl:variable do not allow the modification of its value?

Thanks,
Sylvain
 

Dimitre Novatchev MVP XML

Usenet Archive
Joined
Feb 11, 2004
Messages
43
Reaction score
0
sylvain.loiseau said:
Hello

Given a node set, I try to compute the total of the string-length value of each node.

For instance, with :

<xsl:for-each select="//q">
<!-- the length of each node is compute with: -->
<xsl:value-of select="string-length(.)" />
</xsl:for-each>

but how to get the total of the different values, since xsl:variable do not allow the modification of its value?

Copy all nodes into an the RTF contents of an xsl:variable, then just use the string-length function:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:eek:utput method="text"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/">
<xsl:variable name="vPersons">
<xsl:copy-of select="//person"/>
</xsl:variable>

<xsl:value-of select="string-length($vPersons)"/>
</xsl:template>
</xsl:stylesheet>

when this transformation is applied to the following source.xml:

<persons>
<person name="pt" public="false">
<password>asdf</password>
</person>
<person name="ab" public="true">xx</person>
</persons>

the wanted result is produced:

6

Hope this helped.

Cheers,

Dimitre Novatchev [XML MVP],
FXSL developer, XML Insider,

http://fxsl.sourceforge.net/ -- the home of FXSL
Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html
 

Dimitre Novatchev

Usenet Archive
Joined
Nov 7, 2000
Messages
737
Reaction score
0
sylvain.loiseau said:
Yes it helped. Thanks !

Sylvain

Another way to do this is by using the Tree Visitor pattern:

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

<xsl:template match="@* | node" name="treeVisitor">
<xsl:param name="ptxtLength" select="0"/>
<xsl:variable name="vsubtreeLength">
<xsl:choose>
<xsl:when test="not(node)">0</xsl:when>
<xsl:eek:therwise>
<xsl:apply-templates select="node[1]">
<xsl:with-param name="ptxtLength"
select="$ptxtLength"/>
</xsl:apply-templates>
</xsl:eek:therwise>
</xsl:choose>
</xsl:variable>

<xsl:choose>
<xsl:when test="following-sibling::node">
<xsl:apply-templates select="following-sibling::node[1]"> <xsl:with-param name="ptxtLength" select="$ptxtLength + $vsubtreeLength * (number(.) = number(.))"/> </xsl:apply-templates> </xsl:when> <xsl:eek:therwise> <xsl:value-of select="$vsubtreeLength"/> </xsl:eek:therwise> </xsl:choose> </xsl:template>

<xsl:template match="node[not(node) and not(following-sibling::node)]"> <xsl:param name="ptxtLength" select="0"/> <xsl:value-of select="$ptxtLength"/> </xsl:template>

<xsl:template match="person">
<xsl:param name="ptxtLength" select="0"/>

<xsl:call-template name="treeVisitor">
<xsl:with-param name="ptxtLength"
select="$ptxtLength + string-length(.)"/>
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>

When this transformation is applied on this source.xml:

<persons>
<person name="pt" public="false">
<password>asdf</password>
</person>
<person name="ab" public="true">xx</person>
</persons>

the wanted result is obtained:

6

Cheers,

Dimitre Novatchev [XML MVP],
FXSL developer, XML Insider,

http://fxsl.sourceforge.net/ -- the home of FXSL
Resume: http://fxsl.sf.net/DNovatchev/Resume/Res.html
 

Kenneth Stephen

Usenet Archive
Joined
Dec 29, 2003
Messages
36
Reaction score
0
sylvain.loiseau said:
Hello

Given a node set, I try to compute the total of the string-length value of each node.

For instance, with :

<xsl:for-each select="//q">
<!-- the length of each node is compute with: -->
<xsl:value-of select="string-length(.)" />
</xsl:for-each>
Hi,

I've looked at the other solutions presented and I feel that even though they work, they really arent utilizing the functional programming paradigm.
Here is my solution :

<xsl:call-template name="accumulate">
<xsl:with-param name="nodes" select="//q" />
<xsl:with-param name="sum" select="0" />
</xsl:call-template>

.....and then define "accumulate" as :

<xsl:template name="accumulate">
<xsl:param name="nodes" />
<xsl:param name="sum" />

<xsl:choose>
<xsl:when test = "count($nodes) &gt; 1">
<xsl:call-template name="accumulate">
<xsl:with-param name="nodes" select="$nodes[position != 1]" /> <xsl:with-param name="sum" select="$sum + string-length($nodes[1])" /> </xsl:call-template> </xsl:when> <xsl:eek:therwise> <xsl:value-of select="$sum + string-length($nodes[1])" /> </xsl:eek:therwise> </xsl:choose> </xsl:template>

Regards,
Kenneth
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
548,042
Messages
3,104,223
Members
248,131
Latest member
Tonypshaw1

Latest Threads

Top