On Feb 4, 2008 6:41 AM, Hussein Shafie <hussein at xmlmind.com> wrote:
> --> This bug is fixed now. The bug fix will be available in next release.
Thank you.
> --> The search you have described is translated to:
>
> (descendant::*|following::*)[contains(@*,'bar')][1]
>
> It seems that "[contains(@*, 'bar')]" means:
> - Having an attribute (any attribute will do).
> - This attribute containing 'bar'.
>
> That is, "[contains(@*, 'bar')]" does not iterate over attributes. Not
> intuitive, but probably the correct behavior.
>
> Note that if you restart XXE a dozen times, this search will work as
> expected 2 or 3 times, because this depends on the random order of the
> attributes.
>
> --> The search should have been translated to:
>
> (descendant::*|following::*)[./@*[contains(.,'bar')]][1]
Wow, that's a reasonably subtle aspect of XPath that completely
tripped me up. I had looked at, and tried to manipulate the
corresponding XPath expression, and I couldn't figure out why it
wasn't working as expected. Now that I understand what's going on, I
wanted to elaborate on your explanation for the benefit of anyone else
who might be interested. The important expression is `contains(@*,
'bar')`. The `contains` function[0] takes two strings as arguments;
since our first argument is not a string, it is first converted to a
string using the `string` function[1]. The `string` function will
convert our node-set into a string by converting the first node from
the node-set into a string; determining the first node (in document
order) from a set "of attribute nodes is implementation-dependent"[2],
so, as you mentioned, it will be an arbitrary one of those attributes.
The lesson to be learned is to be careful of thinking that the same
existential semantics applies to function application as it does to
location steps, particularly with a node-set consisting entirely of
attribute nodes.
Thanks for helping me arrive at this insight!
Take care,
John L. Clark
[0] http://www.w3.org/TR/xpath#function-contains
[1] http://www.w3.org/TR/xpath#function-string