[xpath] How to use not contains() in xpath?

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

This question is related to xpath contains

The answer is


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


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()

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"').