You are viewing a plain text version of this content. The canonical link for it is here.
Posted to j-users@xalan.apache.org by Julian Reschke <ju...@gmx.de> on 2010/10/18 16:58:56 UTC

exslt:node-set differs between Xalan-J and XSLTC

Hi,

I see some strange behavior with Xalan-J (as opposed to other engines, 
such as XSLTC or Saxon). It happens when an RTF is passed as a template 
parameter, and is converted to a node-set (using exslt:node-set).

-- test case --
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                 xmlns:exslt="http://exslt.org/common"
 >

<xsl:output method="text"/>

<xsl:template match="/">

   <xsl:variable name="t">
     <root>
       <x>1</x>
       <x>2</x>
       <x>3</x>
     </root>
   </xsl:variable>

   <xsl:variable name="tns" select="exslt:node-set($t)/root/x"/>

   <xsl:message>Type of t: <xsl:value-of 
select="exslt:object-type($t)"/></xsl:message>
   <xsl:message>Type of tns: <xsl:value-of 
select="exslt:object-type($tns)"/></xsl:message>
   <xsl:message>Name of tns: <xsl:value-of 
select="local-name($tns)"/></xsl:message>
   <xsl:message>Nodes in tns: <xsl:value-of 
select="count($tns)"/></xsl:message>
   <xsl:message>$tns[2]: <xsl:value-of select="$tns[2]"/></xsl:message>

   <xsl:call-template name="foo">
     <xsl:with-param name="t" select="$tns"/>
     <xsl:with-param name="i" select="'1'"/>
   </xsl:call-template>

</xsl:template>

<xsl:template name="foo">
   <xsl:param name="t"/>
   <xsl:param name="i"/>
   <xsl:variable name="tns" select="exslt:node-set($t)"/>

   <xsl:message>In template - i: <xsl:value-of select="$i"/></xsl:message>
   <xsl:message>In template - Type of t: <xsl:value-of 
select="exslt:object-type($t)"/></xsl:message>
   <xsl:message>In template - Type of tns: <xsl:value-of 
select="exslt:object-type($tns)"/></xsl:message>
   <xsl:message>In template - Name of tns: <xsl:value-of 
select="local-name($tns)"/></xsl:message>
   <xsl:message>In template - Nodes in tns: <xsl:value-of 
select="count($tns)"/></xsl:message>
   <xsl:message>In template - $tns[2]: <xsl:value-of 
select="$tns[2]"/></xsl:message>

   <xsl:if test="$i &lt; count($tns)">
     <xsl:call-template name="foo">
       <xsl:with-param name="t" select="$tns"/>
       <xsl:with-param name="i" select="$i + 1"/>
     </xsl:call-template>
   </xsl:if>

</xsl:template>

</xsl:stylesheet>
-- test case --

The expected result is that the template "foo" is called three times 
(the number of "x" elements in "root"); once from the root template, 
twice recursively.

With Xalan-J (2.7.0), this happens only two times; in the first recursion,

   count($tns)

evaluates to 1 instead of 3.

Any ideas? Known issue?

Best regards, Julian

Re: exslt:node-set differs between Xalan-J and XSLTC

Posted by Michael Ludwig <mi...@gmx.de>.
Julian Reschke schrieb am 21.10.2010 um 14:27 (+0200):
> On 19.10.2010 23:17, Michael Ludwig wrote:
> >Julian Reschke schrieb am 18.10.2010 um 16:58 (+0200):

> >>select="count($tns)"/></xsl:message>
> >
> >><xsl:template name="foo">
> >>   <xsl:param name="t"/>
> >>   <xsl:param name="i"/>
> >>   <xsl:variable name="tns" select="exslt:node-set($t)"/>
> >
> >Second template, declaring its own variable. Should be one element
> >node.
> 
> Why? I would think it should be three, and XSLTC/Saxon/xsltproc
> agree on that.

You're right. I must have been confused. Try omitting the call to
exsl:node-set() here, you shouldn't need it, because at this point,
the variable already is a node-set.

-- 
Michael Ludwig

Re: exslt:node-set differs between Xalan-J and XSLTC

Posted by Julian Reschke <ju...@gmx.de>.
On 19.10.2010 23:17, Michael Ludwig wrote:
> Julian Reschke schrieb am 18.10.2010 um 16:58 (+0200):
>>
>> I see some strange behavior with Xalan-J (as opposed to other
>> engines, such as XSLTC or Saxon). It happens when an RTF is passed
>> as a template parameter, and is converted to a node-set (using
>> exslt:node-set).
>
>> <xsl:template match="/">
>>
>>    <xsl:variable name="t">
>>      <root>
>>        <x>1</x>
>>        <x>2</x>
>>        <x>3</x>
>>      </root>
>>    </xsl:variable>
>>
>>    <xsl:variable name="tns" select="exslt:node-set($t)/root/x"/>
>
> Should be three element nodes here.

Yes.

>> select="count($tns)"/></xsl:message>
>
>> <xsl:template name="foo">
>>    <xsl:param name="t"/>
>>    <xsl:param name="i"/>
>>    <xsl:variable name="tns" select="exslt:node-set($t)"/>
>
> Second template, declaring its own variable. Should be one element node.

Why? I would think it should be three, and XSLTC/Saxon/xsltproc agree on 
that.

>> select="count($tns)"/></xsl:message>
>>    <xsl:message>In template - $tns[2]:<xsl:value-of
>> select="$tns[2]"/></xsl:message>
>>
>>    <xsl:if test="$i&lt; count($tns)">
>
>> With Xalan-J (2.7.0), this happens only two times; in the first recursion,
>>
>>    count($tns)
>>
>> evaluates to 1 instead of 3.
>
> Here's the (stripped) output I'm getting using Xalan 2.7.1:
>
> Type of t: RTF
> Type of tns: node-set
> Name of tns: x
> Nodes in tns: 3
> $tns[2]: 2
> In template - i: 1
> In template - Type of t: node-set
> In template - Type of tns: unknown
> In template - Name of tns: x
> In template - Nodes in tns: 3
> In template - $tns[2]: 2
> In template - i: 2
> In template - Type of t: unknown
> In template - Type of tns: unknown
> In template - Name of tns: x
> In template - Nodes in tns: 1
> In template - $tns[2]:
>
> Don't know if this is right or wrong for your test case.

This is consistent with what I see in 2.7.0, and is, as far as I can 
tell, showing a bug.

Should I follow up somewhere else, or raise a bug in JIRA directly?

Best regards, Julian


Re: exslt:node-set differs between Xalan-J and XSLTC

Posted by Michael Ludwig <mi...@gmx.de>.
Julian Reschke schrieb am 18.10.2010 um 16:58 (+0200):
> 
> I see some strange behavior with Xalan-J (as opposed to other
> engines, such as XSLTC or Saxon). It happens when an RTF is passed
> as a template parameter, and is converted to a node-set (using
> exslt:node-set).

> <xsl:template match="/">
> 
>   <xsl:variable name="t">
>     <root>
>       <x>1</x>
>       <x>2</x>
>       <x>3</x>
>     </root>
>   </xsl:variable>
> 
>   <xsl:variable name="tns" select="exslt:node-set($t)/root/x"/>

Should be three element nodes here.

> select="count($tns)"/></xsl:message>

> <xsl:template name="foo">
>   <xsl:param name="t"/>
>   <xsl:param name="i"/>
>   <xsl:variable name="tns" select="exslt:node-set($t)"/>

Second template, declaring its own variable. Should be one element node.

> select="count($tns)"/></xsl:message>
>   <xsl:message>In template - $tns[2]: <xsl:value-of
> select="$tns[2]"/></xsl:message>
> 
>   <xsl:if test="$i &lt; count($tns)">

> With Xalan-J (2.7.0), this happens only two times; in the first recursion,
> 
>   count($tns)
> 
> evaluates to 1 instead of 3.

Here's the (stripped) output I'm getting using Xalan 2.7.1:

Type of t: RTF
Type of tns: node-set
Name of tns: x
Nodes in tns: 3
$tns[2]: 2
In template - i: 1
In template - Type of t: node-set
In template - Type of tns: unknown
In template - Name of tns: x
In template - Nodes in tns: 3
In template - $tns[2]: 2
In template - i: 2
In template - Type of t: unknown
In template - Type of tns: unknown
In template - Name of tns: x
In template - Nodes in tns: 1
In template - $tns[2]:

Don't know if this is right or wrong for your test case.

-- 
Michael Ludwig

Re: exslt:node-set differs between Xalan-J and XSLTC

Posted by Julian Reschke <ju...@gmx.de>.
On 21.10.2010 18:10, Mukul Gandhi wrote:
>> Besides that, consistency with other implementations, and conformance to the
>> specification should be reasons enough, methinks.
>
> may be. but node-set is not endorsed officially by XSL WG.

It's not, but when the implementation claims to implement 
exslt:node-set(), it should do that. I don't think there's any wiggle 
room here :-)

Best regards, Julian

Re: exslt:node-set differs between Xalan-J and XSLTC

Posted by Mukul Gandhi <ga...@gmail.com>.
On Thu, Oct 21, 2010 at 9:18 PM, Julian Reschke <ju...@gmx.de> wrote:
> You may be writing a template and want to allow callers to send either a
> node set or a RTF.

a workaround in 1.0 environment could be to write two templates (one
to accept node-set as parameter and the other one to accept RTF as
parameter) and according modify the calling code. I think this is
probably doable.

A polymorphic kind of template definition (i sense that's the pattern
which is reflected in your problem description) get's quite easier to
achieve in XSLT 2.0 environment, where the template parameter is
defined to have type like element(*, xs:anySimpleType) and we pass an
argument to this template which has type say, element(*, xs:int).

> Besides that, consistency with other implementations, and conformance to the
> specification should be reasons enough, methinks.

may be. but node-set is not endorsed officially by XSL WG.



-- 
Regards,
Mukul Gandhi

Re: exslt:node-set differs between Xalan-J and XSLTC

Posted by Julian Reschke <ju...@gmx.de>.
On 21.10.2010 17:41, Mukul Gandhi wrote:
> On Thu, Oct 21, 2010 at 8:35 PM, Julian Reschke<ju...@gmx.de>  wrote:
>> "The purpose of the exsl:node-set function is to return a node-set from a
>> result tree fragment. If the argument is a node-set already, it is simply
>> returned as is..."
>
> If you've a node-set already then what's the use of passing that again
> to node-set function? Why can't the original node-set be used as it
> is?

You may be writing a template and want to allow callers to send either a 
node set or a RTF.

> The most important aspect of node-set function is to convert RTF to
> node-set, and that works fine with Xalan.
>
> Do you really need an identity conversion of a node-set to a similar
> node-set for practical needs? If yes, then is the type of input to

See above.

Besides that, consistency with other implementations, and conformance to 
the specification should be reasons enough, methinks.

> ...

Best regards, Julian

Re: exslt:node-set differs between Xalan-J and XSLTC

Posted by Mukul Gandhi <ga...@gmail.com>.
On Thu, Oct 21, 2010 at 8:35 PM, Julian Reschke <ju...@gmx.de> wrote:
> "The purpose of the exsl:node-set function is to return a node-set from a
> result tree fragment. If the argument is a node-set already, it is simply
> returned as is..."

If you've a node-set already then what's the use of passing that again
to node-set function? Why can't the original node-set be used as it
is?

The most important aspect of node-set function is to convert RTF to
node-set, and that works fine with Xalan.

Do you really need an identity conversion of a node-set to a similar
node-set for practical needs? If yes, then is the type of input to
node-set function known statically, before compilation of stylesheet
-- if yes then I believe, another call to node-set with node-set as
argument is not really needed; I think then we can just use the
original node-set reference.




-- 
Regards,
Mukul Gandhi

Re: exslt:node-set differs between Xalan-J and XSLTC

Posted by Julian Reschke <ju...@gmx.de>.
On 21.10.2010 16:30, Julian Reschke wrote:
> ...
> My expectation is that applying node-set() to a node set should be
> harmless, but
>
> <http://www.exslt.org/exsl/functions/node-set/index.html>
>
> indeed doesn't say -- but I'm ready to say it's the only sane thing to
> do...
> ...

Here we go:

<http://www.exslt.org/exsl/functions/node-set/exsl.node-set.html>:

"The purpose of the exsl:node-set function is to return a node-set from 
a result tree fragment. If the argument is a node-set already, it is 
simply returned as is..."

Conclusion: a bug in Xalan-J.

Best regards, Julian



Re: exslt:node-set differs between Xalan-J and XSLTC

Posted by Mukul Gandhi <ga...@gmail.com>.
On Thu, Oct 21, 2010 at 8:00 PM, Julian Reschke <ju...@gmx.de> wrote:
> At some point I got an error and thought that passing a nodeset as a
> parameter to a template would turn it into a RTF.

I believe that with XSLT 1.0, after passing an object (an XDM item
instance in XSLT 1.0 environment) to a template the type of object is
preserved when that object is assigned to the receiving template's
parameter.

So a node-set would remain a node-set when it reaches a template via
receiver template's parameter.




-- 
Regards,
Mukul Gandhi

Re: exslt:node-set differs between Xalan-J and XSLTC

Posted by Julian Reschke <ju...@gmx.de>.
On 21.10.2010 16:12, Mukul Gandhi wrote:
> Hi Julian,
>
> On Mon, Oct 18, 2010 at 8:28 PM, Julian Reschke<ju...@gmx.de>  wrote:
>>   <xsl:variable name="t">
>>     <root>
>>       <x>1</x>
>>       <x>2</x>
>>       <x>3</x>
>>     </root>
>>   </xsl:variable>
>>
>>   <xsl:variable name="tns" select="exslt:node-set($t)/root/x"/>    [1]
>
>>   <xsl:call-template name="foo">
>>     <xsl:with-param name="t" select="$tns"/>
>>     <xsl:with-param name="i" select="'1'"/>
>>   </xsl:call-template>
>
>> <xsl:template name="foo">
>>   <xsl:param name="t"/>
>>   <xsl:param name="i"/>
>>   <xsl:variable name="tns" select="exslt:node-set($t)"/>       [2]
>
> Since at line [1], you've already constructed a node-set then what's
> the need of doing again node-set($t) at [2] ?

At some point I got an error and thought that passing a nodeset as a 
parameter to a template would turn it into a RTF. (That code was more 
complex, so I'll have to investigate).

> At line [2] I believe, $t is already a node-set and must be accessed
> simply like $t and not node-set($t).
>
> Thought I haven't cross checked what's Xalan's behavior when we do for example:
>
> xx:node-set(xx:node-set($rtf))  which is what I understand you've
> intended to mean with your syntax. And this logically looks wrong to
> me.

My expectation is that applying node-set() to a node set should be 
harmless, but

   <http://www.exslt.org/exsl/functions/node-set/index.html>

indeed doesn't say -- but I'm ready to say it's the only sane thing to do...

Best regards, Julian

Re: exslt:node-set differs between Xalan-J and XSLTC

Posted by Mukul Gandhi <ga...@gmail.com>.
Hi Julian,

On Mon, Oct 18, 2010 at 8:28 PM, Julian Reschke <ju...@gmx.de> wrote:
>  <xsl:variable name="t">
>    <root>
>      <x>1</x>
>      <x>2</x>
>      <x>3</x>
>    </root>
>  </xsl:variable>
>
>  <xsl:variable name="tns" select="exslt:node-set($t)/root/x"/>   [1]

>  <xsl:call-template name="foo">
>    <xsl:with-param name="t" select="$tns"/>
>    <xsl:with-param name="i" select="'1'"/>
>  </xsl:call-template>

> <xsl:template name="foo">
>  <xsl:param name="t"/>
>  <xsl:param name="i"/>
>  <xsl:variable name="tns" select="exslt:node-set($t)"/>      [2]

Since at line [1], you've already constructed a node-set then what's
the need of doing again node-set($t) at [2] ?

At line [2] I believe, $t is already a node-set and must be accessed
simply like $t and not node-set($t).

Thought I haven't cross checked what's Xalan's behavior when we do for example:

xx:node-set(xx:node-set($rtf))  which is what I understand you've
intended to mean with your syntax. And this logically looks wrong to
me.




-- 
Regards,
Mukul Gandhi