xpath filtering extension function called too many times

Adrian Herscu <[email protected]> Tue, 22 Jun 2010 11:33:19 +0300
Newsgroups gmane.text.xml.xalan.java.user
Message-ID <[email protected]>
Hi all,

Consider the following XML:

<?xml version="1.0" encoding="UTF-8"?>
<document>
   <chapter name="a">
     <section ref="1" />
     <section ref="2" />
   </chapter>
   <chapter name="b">
     <section ref="1" />
     <section ref="2" />
   </chapter>
</document>

I have implemented the following extension function, just to trace the 
extension calls:

	public static boolean dummy(final boolean flag) {
		System.out.println(flag);
		return flag;
	}


and the following XSL:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:utils="my.XslUtils"
   xmlns:xalan="http://xml.apache.org/xalan"
   extension-element-prefixes="utils">

   <xsl:output method="xml" indent="yes" encoding="UTF-8"
     media-type="text/xml" xalan:indent-amount="2" />

   <xsl:strip-space elements="*" />

   <xsl:template match="/document">
     <document-report>
       <xsl:for-each select="descendant::section[utils:dummy(true())][1]">
         <section-report ref="{@ref}" 
proc-ref="{ancestor::chapter/@name}" />
       </xsl:for-each>
     </document-report>
   </xsl:template>

</xsl:stylesheet>


In this case the console will show that dummy() was called *once* and 
the output report will be:

<?xml version="1.0" encoding="UTF-8"?>
<document-report xmlns:xalan="http://xml.apache.org/xalan">
   <section-report proc-ref="a" ref="1"/>
</document-report>


The problem is with the variants of 
descendant::section[utils:dummy(true())][1]:

  1. xsl variables:

<xsl:variable name="sections" select="descendant::section" />

and then use this XPath expression instead

xalan:nodeset($sections)[utils:dummy(true())][1]

then the dummy() function will be called 4 times (while the output xml 
will remain the same) !


  2. paths with more than one fragments:

(chapter/section[utils:dummy(true())])[1]
(chapter/section)[utils:dummy(true())][1]
((chapter/section)[utils:dummy(true())])[1]

in these cases the dummy() function is called 4 times too (while the 
output xml still remains the same) !


What is the reason of this behavior?
Do I miss something?

Regards,
Adrian.