23

I have the following sample XML structure:

<SavingAccounts>
    <SavingAccount>
       <ServiceOnline>yes</ServiceOnline>
       <ServiceViaPhone>no</ServiceViaPhone>
    </SavingAccount>
    <SavingAccount>
       <ServiceOnline>no</ServiceOnline>
       <ServiceViaPhone>yes</ServiceViaPhone>
    </SavingAccount>
</SavingAccounts>

What I need to do is filter the 'SavingAccount' nodes using XPATH where the value of 'ServiceOnline' is 'yes' or the value of 'ServiceViaPhone' is yes.

The XPATH should return me two rows!! I can filter 'SavingAccount' nodes where both of the element values are yes like the following XPATH sample, but what I want to do is an or element value comparison???

/SavingAccounts/SavingAccount/ServiceOnline[text()='yes']/../ServiceViaPhone[text()='yes']/..
Alex Angas
  • 59,219
  • 41
  • 137
  • 210

3 Answers3

64

This is a very fundamental XPath feature: composing a number of conditions with the logical operators and, or, and the function not().

and has a higher priority than or and both operators have lower priority than the relational and equality operators (=, !=, >, >=, &lt; and &lt;=).

So, it is safe to write: A = B and C = D

Some most frequent mistakes made:

  1. People write AND and/or OR. Remember, XPath is case-sensitive.

  2. People use the | (union) operator instead of or

Lastly, here is my solution:

/SavingAccounts/SavingAccount
           [ServiceOnLine='yes' or ServiceViaPhone='yes']

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
10
/SavingAccounts/SavingAccount[(ServiceOnLine='yes') or (ServiceViaPhone='yes')]
AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
4

Will

/SavingAccounts/SavingAccount[ServiceOnline/text()='yes' or ServiceViaPhone/text()='yes']

do the trick?

I have no XPath evaluator handy at the moment.

EDIT:
If I remember correctly, you don't need the text(), so

[ServiceOnline='yes' or ServiceViaPhone='yes']

should be sufficient, and more readable.

EDIT:
Yes, of course, 'or' for predicate expressions, my bad.

falstro
  • 34,597
  • 9
  • 72
  • 86
  • 1
    /SavingAccounts/SavingAccount[ServiceOnline/text()='yes' or ServiceByPhone/text()='yes'] –  Jan 23 '09 at 14:11
  • So the XPATH was correct, except you need "or" instead of "|". But that might be a peculiarity of the .NET XML/XPATH parser. – gilles27 Jan 23 '09 at 14:13