121

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?

1
  • 1
    the problem is i know how to access a specific node, but i have no idea of accessing a node if a sibling having specific value. Can it be something like this /a/cc/contains(/a/bb='zz') ? Commented Jun 11, 2013 at 9:13

6 Answers 6

130

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()
Sign up to request clarification or add additional context in comments.

4 Comments

"Not sure why everybody is querying for siblings": Perhaps because the question was for sibling.. ;-)
Seems I actually didn't read the title. :) Answer stays valid anyway.
Your answer queries for siblings too. You just didn't use a *-sibling axis. +1 though.
This doesn't answer the question but it answers my actual question that I formulated badly. Thank you!
51

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

1 Comment

@HOESENGKIANG: you should click the check mark to "accept" this answer, or whichever one you think answers the question best.
33

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']

3 Comments

Either that or //a[bb = 'zz']/cc.
Not sure what you mean by 'only "XPath Axes" for following-sibling and preceding-sibling'. Are you referring to the fact that there is no single axis for all siblings?
@LarsH :Yes sorry, (excuse my bad English :-( ) - that was what I was trying to say. (Because the question was for siblings.)
10

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.

1 Comment

@LarsH Thanks for the correction from "not valid" to "not well-formed". I learnt something new today.
8

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.

Comments

4
//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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.