bouncingHippo
bouncingHippo

Reputation: 6040

Use XPath to compare values of multiple elements with the same name

Given the following XML:

<Fruits>
  <TreeBearing>
      <Name>Apple</Name>
  </TreeBearing>
  <TreeBearing>
      <Name>Orange</Name>
  </TreeBearing>
  <TreeBearing>
      <Name>Grape</Name>
  </TreeBearing>
  <TreeBearing>
      <Name>Apple</Name>
  </TreeBearing>
</Fruits>

What should the XPath be to check if each <Name> contains the word ple?

I tried /Fruits/TreeBearing/Name/text() and I keep getting the first item (ie Apple) only. How do I traverse and get all elements that contain ple?

Upvotes: 1

Views: 2223

Answers (2)

Mathias M&#252;ller
Mathias M&#252;ller

Reputation: 22617

Given exactly this input XML, an expression like

/Fruits/TreeBearing/Name[contains(text(),'ple')]

will retrieve all Name elements

  • whose first child text node contains ple (XPath 1.0)
  • whose only text node contains ple (XPath 2.0). If there is more than one child text node, this will cause an error, and you'd need to use contains(.,'ple') instead.

Yet, in your input XML, there is only one such element. Additionally, if there were many of them, your XPath engine might only return the first result.

Completely unrelated, but "Fruits" is not a correct English plural form - it should read "Fruit".


also will your xpath return a boolean or Apple?

Assuming the following input:

<Fruits>
  <TreeBearing>
      <Name>Apple1</Name>
  </TreeBearing>
  <TreeBearing>
      <Name>Orange</Name>
  </TreeBearing>
  <TreeBearing>
      <Name>Grape</Name>
  </TreeBearing>
  <TreeBearing>
      <Name>Apple2</Name>
  </TreeBearing>
</Fruits>

This path expression:

/Fruits/TreeBearing/Name[contains(text(),'ple')]

returns element nodes:

<Name>Apple1</Name>
-----------------------
<Name>Apple2</Name>

On the other hand,

/Fruits/TreeBearing/Name[contains(text(),'ple')]/text()

only returns the text content of those nodes:

Apple1
-----------------------
Apple2

Finally, to return a Boolean that expresses whether such a node exists in your input, use

boolean(/Fruits/TreeBearing/Name[contains(text(),'ple')])

Upvotes: 3

JLRishe
JLRishe

Reputation: 101652

If you want to check whether all of them contain the value ple, you can use:

not(/Fruits/TreeBearing/Name[not(contains(., 'ple'))])

If you want to check whether any of them contain the value ple, you can use:

/Fruits/TreeBearing/Name[contains(., 'ple')]

The last one will also work for selecting all elements that contain the value ple.

Upvotes: 2

Related Questions