Re: [xslt] math:max and node-sets

Markus Bayerlein said:
> Hi.
> I ran into a problem concerning EXSLT math:max function (and maybe
> other
> EXSLT functions handling node-sets) in combination with the
> exsl:node-set function:

I always wonder, when I read a question like this, whether I should
assume the reporter (you) thoroughly understands what result is
expected, and whether the result obtained is "right" or "wrong".

> If $treefrag is a XML tree fragment, then calling
> math:max(exsl:node-set($treefrag)/*) returns NaN, while first
> converting
> $treefrag to a node-set and applying math:max on the result (i.e.
> $nodeset = exsl:node-set($treefrag), math:max($nodeset/*) ) works.

Well, here we need to be a little careful.  Certainly your program
shows two different results, and it is highly unlikely both are
correct, so I would agree that one of the results is wrong. 
However, I'm not yet willing to agree the other two implied points
here - first this summary is actually an accurate description of
what your program is doing, and second that the second result
"works" (implying that the first result is "wrong").

> The same is true for math:min.
> I did not test other EXSLT functions working on node-sets.
> The attached example also includes another xsltproc misconduct:
> xsltproc underestimates itself by returning false on
> element-available(func:function) :)

Here you certainly seem authoritative - "another xsltproc
misconduct".  But.... The "element-available" returns true if and
only if the function can be used at the point of evalulation.  You
are evaluating *inside a template*, and the func:function can only
be used *at the top level of the stylesheet*.  So, I must disagree
with your conclusion, and rather point out that xsltproc has behaved
perfectly properly.

Now on to your program. You have two functions of interest -
foo:getMaxVal and foo:getMaxVal2.  Both of them declare a variable
resNodes, and within the variable generate a Result Value Tree.  So
far, so good.  Now to the difference between them.  foo:getMaxVal2
ends up with

  <func:result select="math:max(exsl:node-set($resNodes)/*)"/>

while foo:getMaxVal ends up with

  <xsl:variable name="resNodeSet" select="exsl:node-set($resNodes)"/>
  <func:result select="math:max($resNodeSet/*)"/>

Further, foo:getMaxVal returns a value of 300 while foo:getMaxVal2
returns NaN.  Your description of the problem, as well as your
variable name, shows that you believe foo:getMaxVal is giving
math:max a nodeset as its argument.  This is, unfortunately, *not*
correct.  The variable resNodeSet, even though it "selects" a
node-set, is by definition a Result Tree Fragment.

So, foo:getMaxVal calls math:max with a Result Tree Fragment as its
argument.  On the other hand, foo:getMaxVal2 uses exsl:node-set to
convert the Result Tree Fragment into a node-set before passing it
to math:max, i.e. it calls math:max with a node-set as it's

Now, finally, to the result.  Permit me to abbreviate your element
name "dummynode" to just "d".  The Result Tree Fragment in resNodes,
with your test file, looks like this:

If taken as a Result Tree Fragment, under the rules of XSL, that
will be converted to the *string value of the node that is first*,
i.e. '300', and when this string is converted to a number, under the
rules of XPath, it has the value 300.  When this is given as the
argument to math:max, it is taken as a node-set with a single node,
value 300, so math:max returns 300.

If the argument of math:max is converted to a nodeset, however (i.e.
foo:maxVal2), the function examines each of the nodes. This includes
the node with the string value 'nothing' which, by XPath definition,
is NaN.  Again *by definition* of the math:max function, if any of
the nodes are NaN the function returns NaN.

So, in summary, all of your accusations were incorrect.  xsltproc
has performed perfectly.  I would suggest that, in the future, you
spend a bit more time studying the definitions and usage of the
features you are trying to use before reporting problems with them.


> Cheers,
> Markus



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]