Reputation: 520
Let's look at the following XML file:
<a>
<b w="w">
<b1 x="x" />
<b2 y="y" />
</b>
</a>
The following XPath query returns elements b1
and b2
:
/*/*//*
From this I conclude that //*
means to select all elements that are descendants of b
not including b
itself.
However the following XPath query returns attributes w
, x
, y
:
/*/*//@*
So from this I conclude that //@*
means to select all attributes that appear in descendants of b
including b
itself.
How does this work? Does //
work differently for elements vs attributes, or is there something I'm missing?
Upvotes: 4
Views: 72
Reputation: 113242
//
is short for /descendant-or-self::node()/
/*
meanwhile identifies all child nodes from the current position.
Starting from the root, /*/*//
therefore moves us to <a>
(child of root) and then to <b>
(all children of that <a>
being that single <b>
) and then selects descendant-or-self::node()
, which is to say, <b>
, <b1>
and <b2>
.
It's from that starting point of <b>
, <b1>
and <b2>
matched by /*/*//
that your two paths differ.
/*/*//*
matches all child nodes of those nodes. Since <b1>
and <b2>
don't have child nodes, this matches only the child nodes of <b>
: <b1>
and <b2>
.
/*/*//@*
matches all attributes of those nodes. Since <b>
, <b1>
and <b2>
all have attributes, all of those attributes are matched.
From this I conclude that
//*
means to select all elements that are descendants ofb
not includingb
itself.
Yes, but only indirectly. It means "select all elements that are descendants of b
including b
itself, and then find their children". This amounts to "all descendants of b
but not b
" but it went through "including b
" to get there.
Upvotes: 2
Reputation: 17238
The apparent contradiction stems from the interpretations of the shorthand notation for xpath expressions.
//
in xpath expressions is a shorthand for the xpath axis //descendant-or-self::node()/
. Specifying an element in an xpath, eg. by its tag name actually queries the element on the child
axis.
The child
axis does not apply when querying attributes - @
represents its own axis, namely attributes
.
Therefore the matching appears to include one more level in the tre representation.
Upvotes: 2