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
