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).

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. 
//@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.

Evan

From: Mike Sokolov <[email protected]<mailto:[email protected]>>
Date: Thu, 12 May 2011 11:02:50 -0700
To: General MarkLogic Developer Discussion 
<[email protected]<mailto:[email protected]>>
Cc: Evan Lenz <[email protected]<mailto:[email protected]>>
Subject: Re: [MarkLogic Dev General] How To Get The "Content" of An Index?

I've always been baffled by this interpretation - thanks for explaining.

Doesn't it seem as if .//foo *should* mean "descendant-or-self::foo" ?  At 
least that is what every newcomer's interpretation seems to be. I guess one 
can't change the spec if that's not the case.

If it did, then .//foo[1] would do the thing that everybody seems to expect it 
to, and the parentheses wouldn't be necessary.  In any case,this points out 
another idiom that can be used here, as an alternative to parentheses.

I can't help wondering is there some other case that would have been fouled up 
by this sort of elision?

I guess it would become more difficult to find all the eldest descendant foos, 
but that really does seem like an edge case.

-Mike

On 05/11/2011 04:16 PM, Evan Lenz wrote:
Just to explain why Geert's suggestion to add parentheses around 
$song-doc//ts:Value works, this doesn't really have anything to do with 
document vs. sequence order (they're one and the same), but with which 
sequence(s) the predicate (the part in square brackets) is being applied to. 
The key is understanding what "//" is short for: "/descendant-or-self::node()/"

(.//foo)[1] means "get me all descendant <foo> elements and then return just 
the first one" (returning a maximum of one node). In this case, the predicate 
"[1]" applies to the whole (parenthesized) expression to its left.

.//foo[1] means "get me every descendant <foo> element that is the first <foo> 
child of its parent". This expression could return many <foo> elements (which 
is what you were experiencing with all those <ts:Value> elements). In this 
case, the predicate "[1]" is tightly bound to "foo" and applies only to the 
third step of the expression (where the steps are, respectively, ".", 
"descendant-or-self::node()", and "foo[1]").

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

Reply via email to