HOE SENGKIANG
HOE SENGKIANG

Reputation: 1189

How to select a node using XPath if sibling node has a specific value?

I have the following document:

<a>
  <bb>abc</bb>
  <cc>ccc</cc>
  <dd>ddd</dd>
</a>
<a>
  <bb>zz</bb>
  <cc>1</cc>
  <dd>2</dd>
</a>

How can I get the value of <cc> using XPath if <bb> is zz?

Upvotes: 118

Views: 131212

Answers (6)

Jens Erat
Jens Erat

Reputation: 38662

Not sure why everybody is querying for siblings, you can also check for <bb/>-elements matching the predicate from <a/>'s predicate:

//a[bb/text() = "zz"]/cc/text()

Upvotes: 128

Saleh Mahmood
Saleh Mahmood

Reputation: 2063

Another solution for this problem is

//bb[contains(.,'zz')]/../cc/text()

Explanation: Any bb that contains 'zz' string in all the child nodes of bb then going to parent node of that bb using .., now that we can access the cc so returning text.

I hope that explanation isn't complex.

Upvotes: 8

hr_117
hr_117

Reputation: 9627

Q: How to select a node using XPath if sibling node has a specific value?
Because there are only "XPath Axes" for following-siblings and preceding-siblings, you can use one of them if the position is fixed.

But better: Look for cc were the parent has child bb with value 'zz':

//cc[../bb='zz']

Upvotes: 33

Bae Cheol Shin
Bae Cheol Shin

Reputation: 1528

//a/cc[../bb='zz']/text()

//a : Selects all 'a' elements no matter where it is.

//a/cc : Selects 'cc' elements that are children of the 'a' element (no matter where a is).

.. : Selects the parent of the current node.

[../bb='zz'] : where value of sibling 'bb' element is zz.

Reference: http://www.w3schools.com/xsl/xpath_syntax.asp

Upvotes: 4

Petr Janeček
Petr Janeček

Reputation: 38414

First off, your example is not well-formed XML. Overlooking that and that you didn't describe your intents very well (What exactly do you want to select on which condition?), I assume you want to do this:

//cc[preceding-sibling::bb[text()="zz"]]/text()

It selects

TEXT VALUES OF ALL <CC> ELEMENTS
//cc                                    /text()
    THAT HAVE A PRECEDING SIBLING <BB>
    [preceding-sibling::bb             ]
                          THAT HAS TEXT VALUE EQUAL TO "zz"
                          [text()="zz"]

You could write is also as

//bb[text()="zz"]/following-sibling::cc/text()

Please look at the spec, it has some very well readable examples from which you'll learn a lot.

Upvotes: 10

Stanley
Stanley

Reputation: 5127

What you need is following-sibling XPath axis

//a/bb[text()="zz"]/following-sibling::cc[1]/text()

Test the Xpath here: http://www.xpathtester.com/obj/b55ec3ac-dfa4-4f44-81e8-f963ea4a0625

Upvotes: 51

Related Questions