469,296 Members | 2,082 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,296 developers. It's quick & easy.

xsl:variable question

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
Jul 20 '05 #1
4 2385

"sylvain.loiseau" <sy*************@wanadoo.fr> wrote in message
news:c1**********@news-reader2.wanadoo.fr...
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:output 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
Jul 20 '05 #2
> Hope this helped.

Yes it helped. Thanks !

Sylvain
Jul 20 '05 #3
"sylvain.loiseau" <sy*************@wanadoo.fr> wrote in message news:<c1**********@news-reader5.wanadoo.fr>...
Hope this helped.


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:output 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:otherwise>
<xsl:apply-templates select="node()[1]">
<xsl:with-param name="ptxtLength"
select="$ptxtLength"/>
</xsl:apply-templates>
</xsl:otherwise>
</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:otherwise>
<xsl:value-of select="$vsubtreeLength"/>
</xsl:otherwise>
</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
Jul 20 '05 #4

"sylvain.loiseau" <sy*************@wanadoo.fr> wrote in message
news:c1**********@news-reader2.wanadoo.fr...
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:otherwise>
<xsl:value-of select="$sum + string-length($nodes[1])" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>

Regards,
Kenneth
Jul 20 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Xeon | last post: by
2 posts views Thread by Norman Barker | last post: by
10 posts views Thread by Tjerk Wolterink | last post: by
3 posts views Thread by schaf | last post: by
2 posts views Thread by sucheta.phatak | last post: by
5 posts views Thread by Afshar Mohebbi | last post: by
reply views Thread by Markchivs | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by harlem98 | last post: by
1 post views Thread by Geralt96 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.