Search code examples
xmlxpathpredicate

Xpath multiple AND OR operators


Hi I am trying to select XML items using xpath with multiple AND OR operators with no success.

I need to filter where a field equals a certain value and also one ore more other fields equals another value eg.

field1[contains[value1]] and field2[contains[value2]] or field3[contains[value3]] or field4[contains[value4]]

The problem I am having is this still gives result where field one DOES NOT contain value1 because field3 contains value3. I need it to only give results if field1 DOES contain value1 and any one or more of the other fields contain there respective value.

This is what I currently have (note some elements in square brackets are variables)... //item[SubCategory[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),translate('[data:row("Title")]', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'))] and Group[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),translate('[session:naroomaShown]', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'))]|Group[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),translate('[session:moruyaShown]', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'))]|Group[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),translate('[session:batemansShown]', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'))]]


Solution

  • The and operator binds more tightly than or in XPath (see the note at the end of §3.4 in the spec), so

    cond1 and cond2 or cond3 or cond4
    

    is treated as

    (cond1 and cond2) or cond3 or cond4
    

    You need to use explicit parentheses to control the precedence

    cond1 and (cond2 or cond3 or cond4)
    

    Also, as noted by Tomalak in the comments, the | is not actually the boolean OR operator in XPath, but rather the union operator between node sets. In this particular case it won't make a difference, because for node sets X and Y the boolean value of X or Y (== "either X is not empty or Y is not empty or both") will be the same as the boolean value of X | Y (== "the set which is the union of all the nodes in X and all the nodes in Y is not empty") but they are different operators.