Syntax of the xml document:
Z
Z__2
Z__3
Instead of traversing back to the parent, just find the right parent to begin with:
//x
will select all x
elements.//x[//z]
will select all x
elements which have z
elements as descendants.//x[//z]/@name
will get the name
attribute of each of those elements.I dont have a reputation, so I cannot add comment to accepted answer by Blender. But his answer will not work in general. Correct version is
//x[.//z]/@name
Explanation is simple - when you use filter like [//z]
it will search for 'z' in global context, i.e. it returns true if xml contains at least one node z anywhere in xml. For example, it will select both names from xml below:
<root>
<x name="NOT-THIS">
</x>
<x name="GET-THIS">
<y>
<z>Z</z>
<z>Z__2</z>
<z>Z__3</z>
</y>
</x>
</root>
Filter [.//z]
use context of current node (.) which is x
and return only 2nd name.
You already have a good accepted answer, but here are some other helpful expressions:
//z/ancestor::x/@name
- Find <z>
elements anywhere, then find all the ancestor <x>
elements, and then the name="…"
attributes of them.
//z/../../@name
- Find the <z>
elements, and then find the parent node(s) of those, and then the parent node(s) of those, and then the name
attribute(s) of the final set.
//z/parent::*/parent::*/@name
, where the *
means "an element with any name".The //
is useful, but inefficient. If you know that the hierarchy is x/y/z
, then it is more efficient to do something like //x[y/z]/@name