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 Adam Jenkins <ad...@yahoo.com.au> on 2009/04/20 23:46:55 UTC

odd NodeSet behavior

Hi All,

I have notice some really odd behavior when using org.apache.xpath.NodeSet.

I use it in two different ways.  The first, is I have some custom extension functions that return a NodeSet, that I can then loop over.  They work fine.  Then, when I had to collect a range of different nodes to work with (kind of like a preprocessing step) I created one directly and added nodes to it.  They added correctly, however I can no longer use xsl:for-each.  I'll explain more below:

I have a function (let's call it myfunction) that does some stuff and returns an instance of org.apache.xpath.NodeSet.

When I have the following:

<xsl:for-each select="prefix:myfunction(.)">
   <!-- Do something here -->
</xsl:for-each>

I have no problems at all.  for-each iterates over my node set without a problem (for information purposes, it's a NodeSet of text nodes).

I then had a requirement for some preprocessing of a file, and collecting a bunch of nodes, so I thought I'd use NodeSet again, but this time I did the following:

<xsl:variable name="nodebucket" select="java:org.apache.xpath.NodeSet.new()"/>

<!--
   next I have a range of apply-templates that pass the variable nodebucket as a parameter, that performs the following at various places

   <xsl:variable name="tmp" select="java:addNode($nodebucket, .)"/>

  this works fine, as is indicated by the logging statement below
-->

<log:debug message="number of nodes to process {java:size($nodebucket) + 1}"/> <!--this prints out the correct value of 33 -->

<xsl:for-each select="$nodebucket">
   <!--this never executes! -->
   <log:debug message="processing page"/>
</xsl:for-each>

<log:debug message="processing complete"/>

I'm wondering why in one situation using NodeSet works fine, but in the other it's ignored (the contents of the second xsl:for-each is never executed, i.e. the loop doesn't iterate over the NodeSet.  No errors, it just doesn't iterate over it.

Can anyone shed some light into why using NodeSet works in one situation but not in the other?

Cheers
Adam


      Enjoy a better web experience. Upgrade to the new Internet Explorer 8 optimised for Yahoo!7. Get it now.

Re: odd NodeSet behavior

Posted by ke...@us.ibm.com.
> Then, when I had to collect a range of different nodes to work with
> (kind of like a preprocessing step) I created one directly and added
> nodes to it.  They added correctly, however I can no longer use
> xsl:for-each.

> <xsl:variable name="nodebucket"
> select="java:org.apache.xpath.NodeSet.new()"/>

A more idiomatic and more portable approach would be to write an XPath 
which gathers those nodes, assign that into a variable, then use the exslt 
nodeset function to make that variable accessible as an XSLT node set 
which you could then for-each over.

General tip: Try to avoid the temptation to force XSLT into using stateful 
non-XSLT objects. Remember that order of execution of a stylesheet is not 
guaranteed; optimizers may rearrange things. At best, relying on 
extensions may hamstring optimization; at worst, they may not be executed 
in the order you expect. You may get away with it in one release of a 
processor only to have it behave correctly-but-differently in the next 
release. In most cases, there really are XSLT-native ways of saying the 
same things, or ways which need only the well-standardized exslt 
extensions.



______________________________________
"... Three things see no end: A loop with exit code done wrong,
A semaphore untested, And the change that comes along. ..."
  -- "Threes" Rev 1.1 - Duane Elms / Leslie Fish (
http://www.ovff.org/pegasus/songs/threes-rev-11.html)

Re: odd NodeSet behavior

Posted by Michael Ludwig <mi...@gmx.de>.
Adam Jenkins schrieb am 20.04.2009 um 14:46:55 (-0700):
> 
> I have notice some really odd behavior when using
> org.apache.xpath.NodeSet.

> Then, when I had to collect a range of different nodes to work with
> (kind of like a preprocessing step) I created one directly and added
> nodes to it.  They added correctly, however I can no longer use
> xsl:for-each.

> <xsl:variable name="nodebucket"
> select="java:org.apache.xpath.NodeSet.new()"/>

Hi Adam,

this is an interesting case. At this point, the variable is bound and
should never change as far as XSLT is concerned. (Remember, variables
aren't.)

> <!--
>    next I have a range of apply-templates that pass the variable
>    nodebucket as a parameter, that performs the following at various
>    places
> 
>    <xsl:variable name="tmp" select="java:addNode($nodebucket, .)"/>

You're submitting data that is supposed to be immutable to a series of
changes. Looks suspicious to me.

>   this works fine, as is indicated by the logging statement below
> -->
> 
> <log:debug message="number of nodes to process {java:size($nodebucket)
> + 1}"/> <!--this prints out the correct value of 33 -->

Really? Surprising. But then, it's a bizarre case.

> <xsl:for-each select="$nodebucket">
>    <!--this never executes! -->

And it shouldn't - this *is* an empty node-set!

My theory: The XSLT variable is frozen for the purpose of XSLT
processing, but the underlying data structure continues to be subject
to (undue) manipulation by Java. A case for the experts to comment!

You could also consider posting a small but complete test case that
exposes the problem while being easy to understand.

Best,

Michael Ludwig