0

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'))]]

pppery
  • 3,731
  • 22
  • 33
  • 46
Jason Whalan
  • 17
  • 2
  • 6

2 Answers2

5

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.

Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
  • Thank you so much. Everything is now working as it should. You have no idea how much this has helped me. You saved me countless hours. I really do appreciate it. Thanks again. โ€“ Jason Whalan Jun 02 '14 at 12:28
0

Here's the correct way to structure (and a nicer way to format) your entire expression:

//item[
  SubCategory[
    contains(
      translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),
      '[data:row("title")]'
    )
  ]
  and Group[
    contains(
      translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),
      '[session:naroomashown]'
    )
    or contains(
      translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),
      '[session:moruyashown]'
    )
    or contains(
      translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),
      '[session:batemansshown]'
    )
  ]
]

There is no need to call translate() on fixed values like '[session:batemansShown]'. Just use lowercase right from the start.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • Thank you. As with my comment to Ian, you have helped me out a great deal. Just to have this formatted correctly I was able to get my head around it a whole lot easier. I really appreciate it. โ€“ Jason Whalan Jun 02 '14 at 12:30