Re: [xsl] current() and position()?

Subject: Re: [xsl] current() and position()?
From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 2 Dec 2019 03:41:08 -0000
>        <xsl:variable name="letters" as="xs:string+" select="'a', 'b',
'c'"/>
>         <xsl:for-each select="$letters">
>             <xsl:message select="position(), current() ! position()"/>
  >       </xsl:for-each>

The XPath 2.0 Specification (
https://www.w3.org/TR/xpath20/#dt-dynamic-context ) says:
"The position of the first item in a sequence is always 1 (one). The
context position is always less than or equal to the context size.'

The expression is:

    current() ! position()

Do note that the current() function returns at most one item.

So, we have a sequence of one item and according to the XPath 2.0
specification, quoted above), the position of the first item in this
one-item-only sequence "is always 1 (one)".

In XSLT (https://www.w3.org/TR/xslt20/#focus) the *context-position *is
defined as:

"[Definition: The *context position* is the position of the context item
within the sequence of items currently being processed. It changes whenever
the context item changes. When an instruction such as xsl:apply-templates
<https://www.w3.org/TR/xslt20/#element-apply-templates> or xsl:for-each
<https://www.w3.org/TR/xslt20/#element-for-each> is used to process a
sequence of items, the first item in the sequence is processed with a
context position of 1, the second item with a context position of 2, and so
on.] The context position is returned by the XPath expression
<https://www.w3.org/TR/xslt20/#dt-expression> position()."

This has a different, narrower meaning than the definition of position() in
XPath, as XPath doesn't know about any XSLT instructions (such as
xsl:apply-templates <https://www.w3.org/TR/xslt20/#element-apply-templates>
 or xsl:for-each <https://www.w3.org/TR/xslt20/#element-for-each> ).

Note also, that the context position by definition is returned by the XPath
expression: position()  -- not by expression of the kind:
someItem!position()

If, on the other hand we have an expression like:

   $Items!position()

Where $Items is a sequence of more than one item, then the result of
evaluating this is the sequence:

   1 to count($Items)

Here is a simple XSLT 3.0 transformation to verify this:

<xsl:stylesheet version="2.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform";
  xmlns:xs="http://www.w3.org/2001/XMLSchema";>
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:variable name="vLetters" as="xs:string+" select="('a', 'b', 'c')"/>

  <xsl:template match="/">
    <xsl:sequence select="$vLetters!position()"/>
  </xsl:template>
</xsl:stylesheet>

When this transformation is applied on any XML document (not used), the
result is:

1 2 3

Cheers,
Dimitre


On Sun, Dec 1, 2019 at 5:05 PM David Birnbaum djbpitt@xxxxxxxxx <
xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

> Dear xsl-list,
>
> With apologies for what I suspect is a naive question, I am confused about
> the context position in:
>
>         <xsl:variable name="letters" as="xs:string+" select="'a', 'b',
> 'c'"/>
>         <xsl:for-each select="$letters">
>             <xsl:message select="position(), current() ! position()"/>
>         </xsl:for-each>
>
> position() returns what I expect (1, then 2, then 3), but the value of
> current() ! position() is always 1. In this test it doesn't matter because
> I can just use position(), but the real use case requires me to refer the
> position of the item selected by the <xsl:for-each> at a lower depth
> (inside a predicate on a different sequence). I can save the value of
> position() to a variable and use it at that lower depth, so as far as
> getting the job done there isn't a problem, but getting the job done is
> less interesting than understanding why my expectation was wrong.
>
> I thought that inside an <xsl:for-each> the function current() would refer
> to the sequence item being processed at the moment (that is, within the
> parent <xsl:for-each>), and its position would be the context position,
> that is, its offset into the sequence over which <xsl:for-each> was ranging
> by means of its @select attribute. I think what I'm seeing instead is that
> current() ! position() returns the position of the current item inside the
> one-item sequence being processed at the moment, which is why the value is
> always 1. Does this mean that the context position (within the sequence
> selected by the @select attribute on <xsl:for-each>) of the item being
> processed is not accessible once the processing is deep enough that
> position() by itself is not longer suitable? If current() is still the
> current context *item*, where and why does it lose contact with its
> original context *position*?
>
> Best,
>
> David
>
> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
> EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/782854> (by
> email <>)

Current Thread