No, the thing to remember is that the default axis is child::, not self::

(.//foo)[1] returns the same nodes as descendant::foo[1] because it is a
syntactic shorthand for the following:

(./descendant-or-self::node()/child::foo)[1]

Similarly, (.//@foo)[1] is shorthand for:

(./descendant-or-self::node()/attribute::foo)[1]

The only difference between the two examples is the axis of the last step
(child vs. attribute). The "self::" axis doesn't come into play at all.

For completeness, the correct expansion of .//foo[1] is (leaving out the
redundant "." step):

descendant-or-self::node()/child::foo[1]

(hence the interpretation as "every eldest child")

Another thing to observe is that whenever you see "//" the expression may
*look* like it only has one step but it actually has a minimum of two
steps. (An entire step is hidden between those two slashes).


So //foo is an expression not with one step, but with two:

/descendant-or-self::node()/child::foo

Again, the reason it enables //@foo is because it wouldn't work if "//"
were short for "/descendant::". If that were true, then //@foo would
expand to "/descendant::attribute::foo" (a syntax error - a step can't
have more than one axis). I'm pretty convinced that this is the only
reason it was ever defined this way - to enable //@*

Evan


On 5/12/11 12:58 PM, "Mike Sokolov" <[email protected]> wrote:

>
>
>On 05/12/2011 02:52 PM, Evan Lenz wrote:
>> I think most beginners expect .//foo to be short for descendant::foo
>> (which I'm guessing is what you meant), especially since in examples
>> like that they return the exact same results. // is only a gotcha when
>> you start using positional predicates (so be suspicious whenever you
>> see them together without parentheses).
>Actually I did mean ./descendant-or-self::foo, since
>
>./descendant-or-self::foo[1] is actually the same as (.//foo)[1]
>
>(isn't it?)
>
>whereas (as you pointed out)
>
>.//foo[1] is the same as ./descendant-or-self::node()/self::foo[1]
>
>I think I have it right :)
>>
>> Why was it defined this way (as it was originally in XPath 1.0)? I
>> don't think it was to make it easy to "find all the eldest descendant
>> foos" (I like how you put that :-)  I think the answer is so that
>> expressions like //@foo would work.
>I suppose that could be it
>
>> //@foo expands to /descendant-or-self::node/@foo, which means "get me
>> each @foo attribute attached to the current element or one of its
>> descendant elements." A clever specification trick. But if I had a
>> time machine, I'd point out the gotcha that would someday trip
>> everyone up and convince the XSL Working Group that users that want to
>> do that are just going to have to type (.|.//*)/@foo if that's what
>> they want.
>>
>> You're right that it's not likely to change.
>Yes, might as well complain about why bother with having both attributes
>and elements :)
>
>-Mike

_______________________________________________
General mailing list
[email protected]
http://developer.marklogic.com/mailman/listinfo/general

Reply via email to