all groups > dotnet xml > june 2004 >
You're in the

dotnet xml

group:

Passing node-sets as parameters?



Passing node-sets as parameters? Alfred Taylor
6/28/2004 3:08:09 PM
dotnet xml: I essentially need a countif() function for xsl. Something to where I could
do countif(node-set, condition). Rather than try to get too extreme, i
decided to just write one for my countif() with the condition hardcoded.
(this was also my first venture into creating "functions")

Pseudo-code is essentially this: Look at the current node and check the
condition. If the condition is true, call our function again with an
incremented count. If false, call function with the same value. Once we
reach the end of the node set, return the counter variable. The whole time
we're passing around a node-set and a current index.

My problem is that i get an error when i try to index into the node-set like
this $node-set[$index]. It looks like when i call the template and pass in
a node-set using the select attribute, it converts that node-set into a
string? (according to some posts i've read) So ways around that were to
use the mxsl:node-set(). The problem is i tried that and it didn't work.
(I'm using .NET to do the transform)

The other question I had was if i can even index into a node set like i'm
doing? Or maybe there's a better alternative for what i'm trying to do?

Thanks,
-A

-------- CODE
<xsl:template name="countWagesGreaterZero">
<xsl:param name="number" />
<xsl:param name="index" select="1"/>
<xsl:param name="count" select="0" />
<xsl:choose>
<xsl:when test="$index > count($number)">
<xsl:value-of select="$count" />
</xsl:when>
<xsl:otherwise>
<xsl:when test="$number[$index]/@Value > 0">
<xsl:choose>
<xsl:variable name="recursive_result">
<xsl:call-template name="countWagesGreaterZero">
<xsl:with-param name="number" select="$number" />
<xsl:with-param name="index" select="$index + 1" />
<xsl:with-param name="count" select="$count + 1" />
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$recursive_result" />
</xsl:choose>
<xsl:otherwise>
<xsl:variable name="recursive_result">
<xsl:call-template name="countWagesGreaterZero">
<xsl:with-param name="number" select="$number" />
<xsl:with-param name="index" select="$index + 1" />
<xsl:with-param name="count" select="$count" />
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$recursive_result" />
</xsl:otherwise>
</xsl:when>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

Re: Passing node-sets as parameters? Oleg Tkachenko [MVP]
6/29/2004 1:46:07 PM
[quoted text, click to view]

Well, are you sure you can't do that with count() function?
E.g. count(//employee[@wage>60000])

The problem usually is with sum() function when one needs to get sum of
calculated values. Then the simplest (but not the most effective)
solution is using temporary tree of calculated values and then coverting
it to nodeset using xxx:node-set function and summing. Other solution is
recursive template just like yours, but instead of passing index,
usually tail nodeset is passed (nodeset with no first node):
<xsl:with-param name="nodes" select="$nodes[position()>1]"/>
You may want to look at FXSL library where this ideas were developed
much further.

[quoted text, click to view]

Which error? Try $node-set[position()=$index]

--
Oleg Tkachenko [XML MVP]
Re: Passing node-sets as parameters? Alfred Taylor
7/1/2004 2:49:30 PM

[quoted text, click to view]

I guess countif() was a bad example to use. It's essentially a
countifAndSum() function. ;)

[quoted text, click to view]

Ahh crap. Brings back bad memories of the days they taught me functional
languages. Man, looks like i'll have to get myself back into that mindset.
Thanks for reminding me on the different programming paradigms.

As for using xxx:node-set(), i'm still have a terrible time getting it to
work with the .NET transform. something as simple as this:

-- SNIP

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:template match="/">
<xsl:call-template name="testMe">
<xsl:with-param name="param1" select="." />
</xsl:call-template>
</xsl:template>
<xsl:template name="testMe">
<xsl:param name="param1" />
<xsl:value-of select="msxsl:node-set($param1)/Example/Element/@Value" />
</xsl:template>
</xsl:stylesheet>

-- END

I've read numerous other posts with people being able to use it
successfully, but i must be missing something here.

-A

[quoted text, click to view]

Re: Passing node-sets as parameters? Oleg Tkachenko [MVP]
7/4/2004 10:08:28 AM
[quoted text, click to view]

Here is a classical example of evaluating a sum of calculated values
using temporary tree and xxx:node-set() function. It's very easy, but
not the most effective way:

<items>
<item price="9.99" quantity="30">Screwdriver</item>
<item price="29.99" quantity="10">Handsaw</item>
<item price="49.99" quantity="15">Electric drill</item>
</items>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">
<xsl:template match="/">
<xsl:variable name="totals-rtf">
<xsl:for-each select="/items/item">
<t>
<xsl:value-of select="@price*@quantity"/>
</t>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="totals" select="msxsl:node-set($totals-rtf)/t"/>
Total: <xsl:value-of select="format-number(sum($totals), '##0.00')"/>
</xsl:template>
</xsl:stylesheet>

PS. rtf means result-tree fragment, which is temporary tree type in XSLT
1.0.
--
Oleg Tkachenko [XML MVP]
AddThis Social Bookmark Button