How to use not contains() in XPath?
Asked Answered
S

4

103

I have some XML that is structured like this:

<whatson>
  <productions>    
    <production>
      <category>Film</category>
    </production>
    <production>
      <category>Business</category>
    </production>
    <production>
      <category>Business training</category>
    </production>
  </productions>
</whatson>

And I need to select every production with a category that doesn't contain "Business" (so just the first production in this example).

Is this possible with XPath? I tried working along these lines but got nowhere:

//production[not(contains(category,'business'))]
Salomon answered 13/6, 2012 at 22:12 Comment(0)
M
178

XPath queries are case sensitive. Having looked at your example (which, by the way, is awesome, nobody seems to provide examples anymore!), I can get the result you want just by changing "business", to "Business"

//production[not(contains(category,'Business'))]

I have tested this by opening the XML file in Chrome, and using the Developer tools to execute that XPath queries, and it gave me just the Film category back.

Mol answered 13/6, 2012 at 22:18 Comment(3)
Thank you for suggestion to open XML in Chrome and use Developer tools for verifying if XPath is valid! I was just going to find an online checker and you suggestion is much simpler.Botanomancy
can you just use //production[not(@category='Business')] without the contains?Escallop
@YiXiangChong If you dont want to do a contains search, sure, but this original post was doing a contains search (because not all elements were explicitly equal to 'Business')Mol
M
30

I need to select every production with a category that doesn't contain "Business"

Although I upvoted @Arran's answer as correct, I would also add this... Strictly interpreted, the OP's specification would be implemented as

//production[category[not(contains(., 'Business'))]]

rather than

//production[not(contains(category, 'Business'))]

The latter selects every production whose first category child doesn't contain "Business". The two XPath expressions will behave differently when a production has no category children, or more than one.

It doesn't make any difference in practice as long as every <production> has exactly one <category> child, as in your short example XML. Whether you can always count on that being true or not, depends on various factors, such as whether you have a schema that enforces that constraint. Personally, I would go for the more robust option, since it doesn't "cost" much... assuming your requirement as stated in the question is really correct (as opposed to e.g. 'select every production that doesn't have a category that contains "Business"').

Milline answered 14/6, 2012 at 4:25 Comment(1)
@LoamyHound: Thanks for the correction! I finally saw your answer, and fixed the missing bracket, over 2 years later.Milline
F
10

You can use not(expression) function.

not() is a function in xpath (as opposed to an operator)

Example:

//a[not(contains(@id, 'xx'))]

OR

expression != true()
Fons answered 23/10, 2017 at 10:4 Comment(0)
C
3

Should be xpath with not contains() method, //production[not(contains(category,'business'))]

Colon answered 19/8, 2018 at 18:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.