Reputation: 138
I have the following xml and I need to select the only b's having type "desc" under the element having type of "header".
<?xml version="1.0" encoding="UTF-8"?>
<x>
<a>
<b type="header" text="A." />
</a>
<a>
<b type="desc" text="A1." />
</a>
<a>
<b type="desc" text="A2." />
</a>
<a>
<b type="desc" text="A3." />
</a>
<a>
<b type="desc" text="A4." />
</a>
<a>
<b type="header" text="B." />
</a>
<a>
<b type="desc" text="B1." />
</a>
Code should be something like that: /x/a/b/[@type='desc']....
output must be:
A1.
A2.
A3.
A4.
Thanks in advance...
Upvotes: 0
Views: 1383
Reputation: 19482
By default XPath uses the children axis, but in this case you need to check the preceding and following siblings.
First you need to specify the starting a
node. It has to contain an b
node of the type
header
and with the text
A.
.
a[b[@type="header" and @text = "A."]]
It has to be a preceding sibling of the nodes you want to fetch.
preceding-sibling::a[b[@type="header" and @text = "A."]]
The second limit is the first following sibling of this node with the type
header
:
preceding-sibling::a[b[@type="header" and @text = "A."]]/following-sibling::a[b[@type="header"]][1]
Next make it a condition for the a
nodes. So you select only nodes between these two:
/x/a[
preceding-sibling::a[b[@type="header" and @text = "A."]] and
preceding-sibling::a[b[@type="header" and @text = "A."]]/following-sibling::a[b[@type="header"]][1]
]
Last select the text
attribute nodes of b
child nodes with the type
attribute desc
/x/a[
preceding-sibling::a[b[@type="header" and @text = "A."]] and
preceding-sibling::a[b[@type="header" and @text = "A."]]/following-sibling::a[b[@type="header"]][1]
]/b[@type = "desc"]/@text
Upvotes: 1
Reputation: 2761
/x/a/b[@type="header"]/../following-sibling::*[0][name()='a']/b[@type="desc"]/@text
Untested but you find the header, go back up to a, take the first following element, check that it's an a, then look for a child of b, type desc and take the text attribute.
......
Upvotes: 1
Reputation: 89285
You can try this way :
/x/a[following-sibling::a[b[@type='header']] and preceding-sibling::a[b[@type='header']]]/b[@type='desc']/@text
Upvotes: 2