xsl-list
[Top] [All Lists]

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

2019-12-01 22:07:54
Dear Dimitre (cc xsl-list),

Thank you for the quick response. I had misunderstood that, as you write:
"'The context position is returned by the XPath 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 or xsl: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()." This distinction
between position() in XSLT and position() in XPath, which I had not
appreciated previously, explains why current() may continue to point to an
item selected within <xsl:for-each> even after the position of that item in
the original sequence is no longer accessible through any operation that
can be performed on current().

Sincerely,

David

On Sun, Dec 1, 2019 at 10:41 PM Dimitre Novatchev 
dnovatchev(_at_)gmail(_dot_)com <
xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

       <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(_at_)gmail(_dot_)com <
xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> 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)


XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/3318727> (by
email <>)

--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--
<Prev in Thread] Current Thread [Next in Thread>