Subject: RE: sequence as function parameter
From: "Fabien Tillier" <f.tillier@xxxxxxxx>
Date: Mon, 4 Jul 2011 17:09:56 +0200
|
Thank you for your didactic explanations, Ken. It will help me next time I am
trying to complicate things :)
Regards,
Fabien
-----Message d'origine-----
De : G. Ken Holman [mailto:gkholman@xxxxxxxxxxxxxxxxxxxx]
Envoyi : lundi 4 juillet 2011 17:06
@ : xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Objet : Re: sequence as function parameter
At 2011-07-04 16:46 +0200, Fabien Tillier wrote:
>I am trying to create a simple function to multiply each item in a
>sequence by each other (like a sum()).
>My problem is that I am unable to have the parameter treated as a node
>sequence (using saxon, so XSL2.0)
>
>I have
><xsl:template name=" multiplie">
That is a template, not a function, so I'm guessing we aren't looking
at the code that produced your result. Perhaps you are simply
calling the template from the function?
> <xsl:param name="serie"/>
> <xsl:param name="result" as="xs:double"/>
Doesn't this have an initial value of 1? Your template won't work if
you pass an initial sequence of only a single value because you are
multiplying that by the result and the result has no value.
> <!--some test output -->
> <xsl:value-of select="$serie"/>-<xsl:value-of
>select="$result"/>--
> ###<xsl:value-of select="count($serie)"/>###
> <!-- -->
> <xsl:choose>
> <xsl:when test="count($serie) gt 1">
> <!-- make the multiplication between result and
>the first item in the serie, then remove it and call again -->
> <xsl:variable name="comp">
> <xsl:value-of select="number($serie[1])
>* $result"/>
> </xsl:variable>
This is wastefully creating a node tree...
> <xsl:call-template name=" multiplie">
> <xsl:with-param name="serie"><xsl:copy-of
>select="subsequence($serie,2)"/></xsl:with-param>
... as is this ...
> <xsl:with-param name="result"><xsl:value-of
>select="$comp"/></xsl:with-param>
... and that.
> </xsl:call-template>
> </xsl:when>
> <xsl:otherwise>
> <xsl:value-of select="number($serie[1]) *
>$result"/>
Here is where your template won't work if you pass it an initial
sequence of a single value.
>...
>So, the part where I do a count gets me 1, when I should have 4...
>I have tried with
><xsl:param name="serie" as="node()*"/> but I have an error message
>XTTE0790: Required item type of first argument of multiplie() is node();
>supplied
> value has item type xs:double
If you want to pass either nodes or atomic values then use:
as="item()*"
>I am a bit out of ideas....
I think you are looking too deep. And certainly your use of XSLT
constructs could be more streamlined. I believe you can implement
your requirement completely in a one-line template with one parameter.
Does the example below help?
. . . . . . . . Ken
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="urn:X-Fabien"
version="2.0">
<xsl:template match="/">
?<xsl:variable name="seq" select="(6.8E-06,5.5E-06,7.1E-06,7.3E-06)"/>
Fabien's test: <xsl:value-of select="f:multiplie($seq)"/>
Ken's tests: <xsl:value-of select="f:multiplie((7))"/>
and: <xsl:value-of select="f:multiplie((1,2,3,4,5))"/>
</xsl:template>
<xsl:function name="f:multiplie">
<xsl:param name="seq" as="item()+"/><!--at least one item in sequence-->
<xsl:sequence select="if( count($seq)=1 ) then $seq
else $seq[1] * f:multiplie($seq[position()>1])"/>
</xsl:function>
</xsl:stylesheet>
--
Contact us for world-wide XML consulting & instructor-led training
Crane Softwrights Ltd. http://www.CraneSoftwrights.com/s/
G. Ken Holman mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Legal business disclaimers: http://www.CraneSoftwrights.com/legal
|