Re: [saxon] position() changes value if context node is accessed From: Andrew Welch - 2008-10-23 14:29 ```> Andrew> Thinking about it, its easier to understand with brackets: > > Andrew> (for \$x in /foolist/foo return \$x)/position() > > Andrew> vs > > Andrew> for \$x in /foolist/foo return \$x/position() > > Andrew> Looking at that, its clearer that \$x/position() will > Andrew> always return 1 (although its still a little > Andrew> counter-intuitive to me... ) > > If you use that parenthesized version, then you WILL get 1 2 3 4 (at > least, that's how I understand it, and it's what Gestalt does). sure, that was my understanding: /foo/bar/position() is actually equivalent to (for \$x in /foo/bar return \$x)/position() and not for \$x in /foo/bar return \$x/position() It's a lot clearer to me now, thanks. (took a while though ;) -- Andrew Welch http://andrewjwelch.com Kernow: http://kernowforsaxon.sf.net/ ```

[saxon] position() changes value if context node is accessed Andrew Welch <andrew.welch@gm...>
 Re: [saxon] position() changes value if context node is accessed From: Michael Kay - 2008-10-23 09:59 ```> > I'm getting some odd looking results - if I do this: > > > > I get what I would expect: > > 1 2 3 4 This one looks wrong to me. If \$x is a singleton, then \$x/position() should always be 1. Basically \$x/position() means "for each item in \$x return its position within \$x", and the position of an item within a singleton sequence should always be 1. > > However, if I do this: > > > > I get: > > alpha 1 beta 1 gamma 1 delta 1 That's the result I would expect. Michael Kay http://www.saxonica.com/ ```

 Re: [saxon] position() changes value if context node is accessed From: Andrew Welch - 2008-10-23 10:22 ```2008/10/23 Michael Kay : >> >> I'm getting some odd looking results - if I do this: >> >> >> >> I get what I would expect: >> >> 1 2 3 4 > > This one looks wrong to me. If \$x is a singleton, then \$x/position() should > always be 1. Basically \$x/position() means "for each item in \$x return its > position within \$x", and the position of an item within a singleton sequence > should always be 1. hmmm that would make it different to: /foolist/foo/position() I thought the two were equivalent, eg position() called on each node in turn. /foolist/foo is the sequence, \$x is the pointer to each item in sequence and position() is the function applied to each \$x (rather than \$x becoming the sequence each time?) -- Andrew Welch http://andrewjwelch.com Kernow: http://kernowforsaxon.sf.net/ ```

 Re: [saxon] position() changes value if context node is accessed From: Florent Georges - 2008-10-23 11:03 ```Andrew Welch wrote: Hi Andrew, > > This one looks wrong to me. If \$x is a singleton, then > \$x/position() should > > always be 1. Basically \$x/position() means "for each item in \$x > return its > > position within \$x", and the position of an item within a singleton > sequence > > should always be 1. > hmmm that would make it different to: > /foolist/foo/position() > I thought the two were equivalent, eg position() called on each node > in turn. > /foolist/foo is the sequence, \$x is the pointer to each item in > sequence and position() is the function applied to each \$x (rather > than \$x becoming the sequence each time?) The key here is that the "/foolist/foo/position()" expression is evaluated once, while the "\$x/position()" expression is evaluated once per foo element. Each step in the expression change the current position. /foolist/foo evaluates to a sequence of 4 elements, for each of which the rest of the expression is evaluated, each with a different position in this sequence. \$x evaluates to a sequence of 1 element, so the rest of the expression has the current position 1. And this same expression is evaluated 4 times (with \$x bound to each foo element in turn.) BTW that is why XQuery has the variant "for \$var at \$pos in ..." Regards, -- Florent Georges http://www.fgeorges.org/ ```

 Re: [saxon] position() changes value if context node is accessed From: Andrew Welch - 2008-10-23 12:59 ```>> /foolist/foo/position() > >> I thought the two were equivalent, eg position() called on each node >> in turn. > >> /foolist/foo is the sequence, \$x is the pointer to each item in >> sequence and position() is the function applied to each \$x (rather >> than \$x becoming the sequence each time?) > > The key here is that the "/foolist/foo/position()" expression is > evaluated once, while the "\$x/position()" expression is evaluated once > per foo element. Each step in the expression change the current > position. Hi Florent, Quoting from http://www.w3.org/TR/xpath20/#id-for-expressions "In a single-variable for expression, the variable is called the range variable, the value of the expression that follows the in keyword is called the binding sequence, and the expression that follows the return keyword is called the return expression. The result of the for expression is obtained by evaluating the return expression once for each item in the binding sequence, with the range variable bound to that item. " So the key sentence is: "The result of the for expression is obtained by evaluating the return expression once for each item in the binding sequence, with the range variable bound to that item." which for me says the "range variable" (\$x) is just a pointer to the item in the "binding sequence" (/foolist/foo) so the return expression does know about the size of the binding sequence and therefore the item's position() within it. ...but it's easy to understand both perspectives here. > /foolist/foo evaluates to a sequence of 4 elements, for each of which > the rest of the expression is evaluated, each with a different position > in this sequence. > > \$x evaluates to a sequence of 1 element, so the rest of the > expression has the current position 1. And this same expression is > evaluated 4 times (with \$x bound to each foo element in turn.) I don't agree that the two are different... I would expect them to both expand to the same code. It will be interesting to see how this pans out :) -- Andrew Welch http://andrewjwelch.com Kernow: http://kernowforsaxon.sf.net/ ```

 Re: [saxon] position() changes value if context node is accessed From: Michael Kay - 2008-10-23 13:13 ```> > hmmm that would make it different to: > > /foolist/foo/position() > > I thought the two were equivalent, eg position() called on > each node in turn. Yes, the bug occurs because the optimizer thinks they're equivalent. But they aren't. In one case the LH operand of "/" is a sequence with four items, in the other case it is a sequence with one item. Now raised at https://sourceforge.net/tracker2/index.php?func=detail&aid=2189091&group_id= 29872&atid=397617 and a patch will be committed shortly. Michael Kay http://www.saxonica.com/ ```

 Re: [saxon] position() changes value if context node is accessed From: Michael Kay - 2008-10-23 13:18 ```> > "In a single-variable for expression, the variable is called > the range variable, the value of the expression that follows > the in keyword is called the binding sequence, and the > expression that follows the return keyword is called the > return expression. The result of the for expression is > obtained by evaluating the return expression once for each > item in the binding sequence, with the range variable bound > to that item. " > > So the key sentence is: > > "The result of the for expression is obtained by evaluating > the return expression once for each item in the binding > sequence, with the range variable bound to that item." > > which for me says the "range variable" (\$x) is just a pointer > to the item in the "binding sequence" (/foolist/foo) so the > return expression does know about the size of the binding > sequence and therefore the item's position() within it. > > ...but it's easy to understand both perspectives here. \$x isn't a pointer to anything, it is an expression whose value is a single item. It's not the meaning of a for expression that matters here, it's the meaning of \$x/position(). 3.2 Path Expressions says: "Each operation E1/E2 is evaluated as follows: Expression E1 is evaluated, and ... Each node resulting from the evaluation of E1 then serves in turn to provide an inner focus for an evaluation of E2, as described in 2.1.2 Dynamic Context. 2.1.2 Dynamic context says: When an expression E1/E2 or E1[E2] is evaluated, the context position in the inner focus for an evaluation of E2 is the position of the context item in the sequence obtained by evaluating E1. Since E1 is a singleton (that is, count(\$x) is 1), the context position while evaluating E2 can only be 1. Note that E1/E2 behaves exactly the same as E1[E2], a construct where it is much more likely that E2 will depend on position(). If you wrote for \$x in /foolist/foo return \$x[1] then you would get all four foo elements back, which is again because position() within E2 is always 1 when E1 is a singleton. Michael Kay http://www.saxonica.com/ ```

 Re: [saxon] position() changes value if context node is accessed From: Andrew Welch - 2008-10-23 13:35 ```> Maybe we should switch to XSL List? If you like, but Saxon can't be right in both cases... -- Andrew Welch http://andrewjwelch.com Kernow: http://kernowforsaxon.sf.net/ ```

 Re: [saxon] position() changes value if context node is accessed From: Florent Georges - 2008-10-23 13:49 ```Andrew Welch wrote: > "The result of the for expression is obtained by evaluating the > return > expression once for each item in the binding sequence, with the range > variable bound to that item." > which for me says the "range variable" (\$x) is just a pointer to the > item in the "binding sequence" (/foolist/foo) so the return > expression > does know about the size of the binding sequence and therefore the > item's position() within it. I don't know what is a pointer in XPath ;-) But when you evaluate the return expression, say "\$x/position()", the normal XPath rules apply, in particular the operator "/". And this operator change the current sequence and the current position. I don't really see why (nor how) this case should be treated differently. The context in XPath is not a property of items, but depends on the expression being evaluated (that is why the context has been introduced.) Maybe we should switch to XSL List? Regards, -- Florent Georges http://www.fgeorges.org/ ```

 Re: [saxon] position() changes value if context node is accessed From: Andrew Welch - 2008-10-23 14:06 ```> \$x isn't a pointer to anything, it is an expression whose value is a single > item. It's not the meaning of a for expression that matters here, it's the > meaning of \$x/position(). yeah "pointer" was a poor choice of word it seems... I meant how \$x in this example: for \$x in /foolist/foo return \$x/count(preceding-sibling::*) just "points" to the element in the input and will count all preceding siblings (not just the elements selected) > 3.2 Path Expressions says: "Each operation E1/E2 is evaluated as follows: > Expression E1 is evaluated, and ... Each node resulting from the evaluation > of E1 then serves in turn to provide an inner focus for an evaluation of E2, > as described in 2.1.2 Dynamic Context. > > 2.1.2 Dynamic context says: When an expression E1/E2 or E1[E2] is evaluated, > the context position in the inner focus for an evaluation of E2 is the > position of the context item in the sequence obtained by evaluating E1. > > Since E1 is a singleton (that is, count(\$x) is 1), the context position > while evaluating E2 can only be 1. > > Note that E1/E2 behaves exactly the same as E1[E2], a construct where it is > much more likely that E2 will depend on position(). If you wrote > > for \$x in /foolist/foo return \$x[1] That's not very useful then :) reminds me of //*[1] Thinking about it, its easier to understand with brackets: (for \$x in /foolist/foo return \$x)/position() vs for \$x in /foolist/foo return \$x/position() Looking at that, its clearer that \$x/position() will always return 1 (although its still a little counter-intuitive to me... ) -- Andrew Welch http://andrewjwelch.com Kernow: http://kernowforsaxon.sf.net/ ```

 Re: [saxon] position() changes value if context node is accessed From: Colin Paul Adams - 2008-10-23 14:16 ```>>>>> "Andrew" == Andrew Welch writes: Andrew> Thinking about it, its easier to understand with brackets: Andrew> (for \$x in /foolist/foo return \$x)/position() Andrew> vs Andrew> for \$x in /foolist/foo return \$x/position() Andrew> Looking at that, its clearer that \$x/position() will Andrew> always return 1 (although its still a little Andrew> counter-intuitive to me... ) If you use that parenthesized version, then you WILL get 1 2 3 4 (at least, that's how I understand it, and it's what Gestalt does). -- Colin Adams Preston Lancashire ```

 Re: [saxon] position() changes value if context node is accessed From: Andrew Welch - 2008-10-23 14:29 ```> Andrew> Thinking about it, its easier to understand with brackets: > > Andrew> (for \$x in /foolist/foo return \$x)/position() > > Andrew> vs > > Andrew> for \$x in /foolist/foo return \$x/position() > > Andrew> Looking at that, its clearer that \$x/position() will > Andrew> always return 1 (although its still a little > Andrew> counter-intuitive to me... ) > > If you use that parenthesized version, then you WILL get 1 2 3 4 (at > least, that's how I understand it, and it's what Gestalt does). sure, that was my understanding: /foo/bar/position() is actually equivalent to (for \$x in /foo/bar return \$x)/position() and not for \$x in /foo/bar return \$x/position() It's a lot clearer to me now, thanks. (took a while though ;) -- Andrew Welch http://andrewjwelch.com Kernow: http://kernowforsaxon.sf.net/ ```