0

My XML

<r>
  <ul>
    <li>ModelA</li>
    <bi>Foo</bi>
  </ul>
  <ul>
    <li>ModelB</li>
    <bi>boo</bi>
  </ul>
</r>

For specific node value I want to extract the value of the successor node.

Example when li = ModelA get the value of bi which is Foo

My Xpath : //ul[li[contains(.,'ModelA')]]

MokiNex
  • 857
  • 1
  • 8
  • 21

4 Answers4

1

Your XPath does not contain bi, so it will not select a bi-Node.

Start with

//ul/bi

which selects the bi-node. Now add the conditions in square brackets. The first condition is "the parent node has a li-subnode:

//ul/bi[../li]

The second condition is: that li-node contains text:

//ul/bi[../li[contains(.,'ModelA')]]

However, this might not do what you want in case of multiple bi nodes. If you really need the next bi node only, the answer of @Jack Fleeting is probably best.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
1

If I understand your question correctly, this may do the trick:

//ul/li[contains(.,'ModelA')]/following-sibling::bi

Edit: Following @Thomas Weller's correct observation in the comments below, here's a simple explanation of this xpath expression:

Your target <bi> is a child of the target <ul> which itself has another child (<li>, hence, the //ul/li part), which itself (i.e., the <li>) contains the text li[contains(.,'ModelA')]). Since both <li> and <bi>, as children of the same <ul>,are siblings, once that <li> is located, the next stop is to locate its sibling <bi> (hence the final /following-sibling::bi).

Jack Fleeting
  • 24,385
  • 6
  • 23
  • 45
  • If you add some explanations, the answer may achieve some learning effect on OP's side. Otherwise it's just a copy/paste fix my issue. – Thomas Weller Nov 21 '19 at 17:54
  • @ThomasWeller - In the light of a new day (and more coffee) it seems you are right; I shouldn't have rushed the answer. Sorry about that. See edit above. – Jack Fleeting Nov 22 '19 at 16:53
0

If it needn't be a successor – if sibling suffices – just add the bi to the end of your XPath:

//ul[li[contains(.,'ModelA')]]/bi

will select all bi elements with li siblings that have a string value that contains a 'ModelA substring. If you actually want an equality rather than a substring test, you can simplify this to

//ul[li='ModelA']/bi

See also What does contains() do in XPath?

kjhughes
  • 106,133
  • 27
  • 181
  • 240
0

Why do you want to use contains() for this? Just use "=".

//ul/li[. = 'ModelA')]/following-sibling::bi

The contains() function is needed only if you want to match a substring, for example if you also want to match a node whose value is SuperModelA2

Michael Kay
  • 156,231
  • 11
  • 92
  • 164