xsl:variable question

S

sylvain.loiseau

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
 
D

Dimitre Novatchev [MVP XML]

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
 
D

Dimitre Novatchev

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
 
K

Kenneth Stephen

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
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top