163

How can I do with XPath:

//bookstore/book/title or //bookstore/city/zipcode/title

Just //title won't work because I also have //bookstore/magazine/title

p.s. I saw a lot of or examples but mainly with attributes or single node structure.

dur
  • 13,039
  • 20
  • 66
  • 96
user569008
  • 1,713
  • 2
  • 10
  • 10
  • 5
    OR is inclusive of both sides. What you're looking for is the XOR operator. You're conflating the English usage of the word OR with logical operators. – Zoran Pavlovic Oct 21 '12 at 22:32
  • 12
    In this case it makes no difference whether you use *or* or *xor* as it's not possible to match both sides. – Dan Hulme Apr 18 '13 at 13:08

3 Answers3

241

All title nodes with zipcode or book node as parent:

Version 1:

//title[parent::zipcode|parent::book]

Version 2:

//bookstore/book/title|//bookstore/city/zipcode/title

Version 3: (results are sorted based on source data rather than the order of book then zipcode)

//title[../../../*[book or magazine] or ../../../../*[city/zipcode]]

or - used within true/false - a Boolean operator in xpath

| - a Union operator in xpath that appends the query to the right of the operator to the result set from the left query.

skaviouz
  • 45
  • 6
Stephan
  • 37,597
  • 55
  • 216
  • 310
  • I marked it as answer because it worked for me but i just saw something. Isn't "|" operator AND? So, XPath like (//book | //cd) will return a node-set with all book and cd elements? Isn't there OR, but not AND. In my case it worked, because in the node-set i have the one or the other, but not both, if I have both it will double the results. – user569008 Mar 18 '11 at 15:27
  • 6
    "|" is not really an "OR operator" in XPath.It permits you to build a nodeset composed from substrees of a whole XML tree. "//book|//cd" means among all child nodes and descendant of the root node find all ones named 'book' then find also all named 'cd'. If in the descendance of the root node there are only book nodes,your node-set will contain book nodes only. If in the descendance of the root node there are only cd nodes,your node-set will contain cd nodes only. If in the descendance of the root node there are both book and cd nodes,your node-set will contain both book and cd nodes. – Stephan Mar 18 '11 at 16:03
  • 1
    Yes, i understood what "|" operator is. My initial question is about the OR operator. So, if there are books & cds it will find only books, if there are no books, but only cds, it will find cds. – user569008 Mar 18 '11 at 17:44
  • 19
    @user569008: `|` is the [union set operator](http://www.w3.org/TR/xpath/#node-sets). –  Mar 18 '11 at 19:35
  • 1
    So, there's no answer for my question / no OR operator in XPath for nodes? – user569008 Mar 19 '11 at 08:09
  • 3
    Logical operators (OR, XOR, AND) are the same in every programming language but natural language interprets them slightly different. It's best to remove ambiguity when discussing issues related to them. Furthermore, with XPath it's best not to think of your result as **being _a or b_**, but rather that it **could be located by _a or b_**. Logical `or` means it could be located by `a or b or both`. [Logical `xor` (eXclusive OR)](https://stackoverflow.com/a/6501151/426371) means it could be located by `either a or b, but not both`. Logical `and` means it could be located by `both a and b`. – neXus Nov 24 '17 at 14:17
62

If you want to select only one of two nodes with union operator, you can use this solution: (//bookstore/book/title | //bookstore/city/zipcode/title)[1]

azurkin
  • 1,614
  • 2
  • 17
  • 19
  • really the `(` and `)[1]` means to select only one of the two?!?! – oldboy Jul 09 '18 at 02:25
  • @Anthony Yes, it will select one of the two, if both nodes exists, or it will select the only one that exists. – azurkin Jul 10 '18 at 07:57
  • okay, i misinterpreted your statement. it operates like any other "or" operator, so that if the first condition returns true, then the second is bypassed, yeah? – oldboy Jul 10 '18 at 21:07
  • @Anthony No. There are no conditions here. There are nodes. And "|" - is a nodes union operator. It creates a nodeset from specified paths, and does not guarantee nodes order. If node with specified path does not exists, it's simply missing in a nodeset. Then, "[1]" construct get first node from a nodeset. – azurkin Jul 11 '18 at 10:37
  • my point is that it functions similarly to an `or` or in other languages an `|` operator, so that if both nodes existed, it would always return the first node? – oldboy Jul 11 '18 at 16:47
  • 1
    @Anthony The whole construct "(path1 | path2)[1]" acts like an or operator in some programming languages - it will return the first found node (not necessarily the node from path1). – azurkin Jul 12 '18 at 12:19
  • yeah ok thats what i thought – oldboy Jul 12 '18 at 17:02
8

It the element has two xpath. Then you can write two xpaths like below:

xpath1 | xpath2

Eg:

//input[@name="username"] | //input[@id="wm_login-username"]
frianH
  • 5,901
  • 6
  • 13
  • 36
Subrahmanya Prasad
  • 566
  • 1
  • 8
  • 14