[oXygen-user] Odd behavior of position() in a predicate

G. Ken Holman gkholman at CraneSoftwrights.com
Sat Jan 5 11:45:18 CST 2013


At 2013-01-05 11:35 -0500, Mark Baker wrote:
>Content-Type: multipart/alternative;
>         boundary="----=_NextPart_000_000A_01CDEB38.BF304500"
>Content-Language: en-ca
>
>Can anyone account for the behavior exhibited by the position 
>function in a predicate in the following code sample:
>
><xsl:variable name="x" select="'A', 'B', 'C'" as="xs:string*"/>
><xsl:variable name="y" select="'a', 'b', 'c'" as="xs:string*"/>
><xsl:for-each select="$x">
>                 <xsl:variable name="pos" select="position()"/>
>                 <xsl:message select="position()"/>
>                 <xsl:message select="., $y[position()]"/>
>                 <xsl:message select="., $y[$pos]"/>
></xsl:for-each>
>
>As the output below shows, when the value of position is stored in a 
>variable and the variable is used in a predicate, you get what you 
>would expect, the selection of a single item corresponding to the 
>current position. But when position() is used directly in the 
>predicate, it returns all the items in the sequence:
>
>[Saxon-PE] 1
>[Saxon-PE] A a b c
>[Saxon-PE] A a
>[Saxon-PE] 2
>[Saxon-PE] B a b c
>[Saxon-PE] B b
>[Saxon-PE] 3
>[Saxon-PE] C a b c
>[Saxon-PE] C c
>
>Any ideas, or is this simply a bug?

I don't see a bug.  position() is being re-evaluated *inside* the 
predicate, whereas $pos is not being re-evaluated inside the predicate.

In XPath, position() is always calculated based on the current 
context.  In the predicate, that context is the node test.  So when you write:

    $y[position()]

... the data type of the predicate evaluation is numeric, so that is 
an abbreviation for position()={value}, where {value} is the current 
position.  Thus, it is evaluated as the sequence:

    'a'[position()=1], 'b'[position()=2], 'c'[position()=3]

... which is:

    'a'[true()], 'b'[true()], 'c'[true()]

... which is:

    'a', 'b', 'c'

So, I would expect the result you are seeing.

Note for $y[$pos], the data type of $pos is numeric so that also is 
an abbreviation for $y[position()=$pos], which is true only once in 
each of the three iterations.  You get 'a' for the first, 'b' for the 
second and 'c' for the third iteration.

I hope this has helped.

. . . . . . . . . Ken

--
Contact us for world-wide XML consulting and instructor-led training
Free 5-hour lecture: http://www.CraneSoftwrights.com/links/udemy.htm
Crane Softwrights Ltd.            http://www.CraneSoftwrights.com/z/
G. Ken Holman                   mailto:gkholman at CraneSoftwrights.com
Google+ profile: https://plus.google.com/116832879756988317389/about
Legal business disclaimers:    http://www.CraneSoftwrights.com/legal



More information about the oXygen-user mailing list