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 Sam Prokop <sp...@4tek.de> on 2010/02/12 14:53:39 UTC

Different Current-Node-Set

Hi,

why does Xalan process different current-node-sets, when one node set is sorted?

Example:

XML:

<AAA>
    <BBB>
        <CCC>A</CCC>
    </BBB>
    <BBB>
        <CCC>B</CCC>
    </BBB>
    <BBB>
        <CCC>A</CCC>
    </BBB>
    <BBB>
        <CCC>C</CCC>
    </BBB>
    <BBB>
        <CCC>B</CCC>
    </BBB>
    <BBB>
        <CCC>B</CCC>
    </BBB>
    <BBB>
        <CCC>A</CCC>
    </BBB>
</AAA>

XSL:

    <xsl:template match="/">
        <xsl:apply-templates select="//AAA/BBB">
            <xsl:sort select="CCC"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="BBB">
         <xsl:value-of select="CCC"/> = <xsl:value-of select="preceding::CCC"/> : <xsl:value-of select="CCC = preceding::CCC"/><br/>
    </xsl:template>

Result:
A=:false
A=A:true
A=A:true
B=A:false
B=A:true
B=A:true
C=A:false

Does the comparison "CCC = preceding::CCC" use the sorted Node-Set for preceding and  the select "preceding::CCC" use the document node set?






Thanks

Sam

Re: Different Current-Node-Set

Posted by Michael Ludwig <mi...@gmx.de>.
Sam Prokop schrieb am 15.02.2010 um 11:41:21 (+0100):

> I wasn´t aware that compare in Xpath compares to any preceding nodes
> not only the first one.

But of course nothing stops you from going preceding::CCC[1] if that's
what you want - the preceding-axis in in reverse document order, so [1]
will get the closest node to the context node.

-- 
Michael Ludwig

AW: Different Current-Node-Set

Posted by Sam Prokop <sp...@4tek.de>.

Thanks,

this made things clear. I wasn´t aware that compare in Xpath compares to any preceding nodes not only the first one.

I wanted to archive an Index like:

a | a_c
   | a_d
   | a_a
b| b_a
   | b_d
…
As long as I don´t use substring it worked, if I use substring in the comparison (substring(preceding::CCC,1,2)) it does not work.
Because of, as you described, substring is a string operation and uses only the first node.

So things get a little bit more complicated here.

Cheers

Sam





Hi, Sam.

Sam Prokop <sp...@4tek.de> wrote on 02/12/2010 08:53:39 AM:
>     <xsl:template match="/">
>         <xsl:apply-templates select="//AAA/BBB">
>             <xsl:sort select="CCC"/>
>         </xsl:apply-templates>
>     </xsl:template>
>
>     <xsl:template match="BBB">
>          <xsl:value-of select="CCC"/> = <xsl:value-of
> select="preceding::CCC"/> : <xsl:value-of select="CCC = preceding::CCC"/><br/>
>     </xsl:template>
>
> Result:
> A=:false
> A=A:true
> A=A:true
> B=A:false
> B=A:true
> B=A:true
> C=A:false
>
> Does the comparison “CCC = preceding::CCC” use the sorted Node-Set
> for preceding and  the select “preceding::CCC” use the document node set?

I think this has more to do with the differences in the meaning of the relational operators and of conversion to string than the effect of sorting.

xsl:value-of converts the selected value to string and uses that string value to construct a new text node.  That conversion is performed as if the XPath string function was applied to the value.[1]  "A node-set is converted to a string by returning the string-value of the node in the node-set that is first in document order. If the node-set is empty, an empty string is returned."

So when you write xsl:value-of select="preceding::CCC" that selects the all the CCC elements that precede the context node (the BBB element) in document order, and the conversion to string selects the first of those.  So, except when the context node is the first BBB element which has no preceding CCC elements, the xsl:value-of is always getting the string value of the very first CCC node - that is, "A".

From section 3.4 of XPath 1.0,[2] "If both objects to be compared are node-sets, then the comparison will be true if and only if there is a node in the first node-set and a node in the second node-set such that the result of performing the comparison on the string-values of the two nodes is true."

So when you write, <xsl:value-of select="CCC = preceding::CCC"/>, that selects two sets of nodes:  the CCC element children of the BBB element, and all the CCC elements that precede that BBB element in document order.  Then, if there is node in the first set and a node in the second set whose string values are equal, the result of the comparison is true.  When you come to the first BBB node that has a CCC child with string value "B", for instance, the result of the comparison will be false, but for all subsequent BBB elements with a CCC child with string value "B", the result of the comparison must be true.

I hope that helps to clarify things.  If you can describe what you're actually trying to do, somebody might be able to suggest how you could write that in XSLT.

Thanks,

Henry
[1] http://www.w3.org/TR/xpath/#function-string
[2] http://www.w3.org/TR/xpath/#booleans
------------------------------------------------------------------
Henry Zongaro
XML Transformation & Query Development
IBM Canada Lab   T/L 313-6044;  Phone +1 905 413-6044
mailto:zongaro@ca.ibm.com

Re: Different Current-Node-Set

Posted by Henry Zongaro <zo...@ca.ibm.com>.
Hi, Sam.

Sam Prokop <sp...@4tek.de> wrote on 02/12/2010 08:53:39 AM:
>     <xsl:template match="/">
>         <xsl:apply-templates select="//AAA/BBB">
>             <xsl:sort select="CCC"/>
>         </xsl:apply-templates>
>     </xsl:template>
> 
>     <xsl:template match="BBB">
>          <xsl:value-of select="CCC"/> = <xsl:value-of 
> select="preceding::CCC"/> : <xsl:value-of select="CCC = 
preceding::CCC"/><br/>
>     </xsl:template>
> 
> Result:
> A=:false
> A=A:true
> A=A:true
> B=A:false
> B=A:true
> B=A:true
> C=A:false
> 
> Does the comparison “CCC = preceding::CCC” use the sorted Node-Set 
> for preceding and  the select “preceding::CCC” use the document node 
set?

I think this has more to do with the differences in the meaning of the 
relational operators and of conversion to string than the effect of 
sorting.

xsl:value-of converts the selected value to string and uses that string 
value to construct a new text node.  That conversion is performed as if 
the XPath string function was applied to the value.[1]  "A node-set is 
converted to a string by returning the string-value of the node in the 
node-set that is first in document order. If the node-set is empty, an 
empty string is returned."

So when you write xsl:value-of select="preceding::CCC" that selects the 
all the CCC elements that precede the context node (the BBB element) in 
document order, and the conversion to string selects the first of those. 
So, except when the context node is the first BBB element which has no 
preceding CCC elements, the xsl:value-of is always getting the string 
value of the very first CCC node - that is, "A".

From section 3.4 of XPath 1.0,[2] "If both objects to be compared are 
node-sets, then the comparison will be true if and only if there is a node 
in the first node-set and a node in the second node-set such that the 
result of performing the comparison on the string-values of the two nodes 
is true."

So when you write, <xsl:value-of select="CCC = preceding::CCC"/>, that 
selects two sets of nodes:  the CCC element children of the BBB element, 
and all the CCC elements that precede that BBB element in document order. 
Then, if there is node in the first set and a node in the second set whose 
string values are equal, the result of the comparison is true.  When you 
come to the first BBB node that has a CCC child with string value "B", for 
instance, the result of the comparison will be false, but for all 
subsequent BBB elements with a CCC child with string value "B", the result 
of the comparison must be true.

I hope that helps to clarify things.  If you can describe what you're 
actually trying to do, somebody might be able to suggest how you could 
write that in XSLT.

Thanks,

Henry
[1] http://www.w3.org/TR/xpath/#function-string
[2] http://www.w3.org/TR/xpath/#booleans
------------------------------------------------------------------
Henry Zongaro
XML Transformation & Query Development
IBM Canada Lab   T/L 313-6044;  Phone +1 905 413-6044
mailto:zongaro@ca.ibm.com