XPath select based on child value(s)

You can go with //book[./genres/genre = 'Romance'] and //book[./genres/genre = 'Romance' and ./genres/genre = 'Politics'], respectively


All books in Romance genre:

//book[genres/genre = 'Romance']

All books in Romance and Politics genre:

//book[genres/genre = 'Romance' and genres/genre = 'Politics']

All books in Romance that are also in Politics genre (same as and above):

//book[genres/genre = 'Romance'][genres/genre = 'Politics']

All books in Romance or Politics genre:

//book[genres/genre = 'Romance' or genres/genre = 'Politics']

All books in Romance or Politics genre (XPath 2.0 only):

//book[genres/genre = ('Romance', 'Politics')]

Notes:

  1. //book finds all book elements anywhere beneath the root element; /books/book finds all book children of the books root element. For the given XML, they select the same elements.
  2. You can append /author to any of the above XPaths to select the author elements of the books of the specified criteria.

Having trouble making it work?

First, establish that a basic XPath works: //book should return two elements.

If it does not:

  1. Check spelling carefully of both the XPath expression and the XML.
  2. Check case. XML and XPath are case sensitive.
  3. Check that no namespaces are in play. Namespaces are effectively a part of the names of elements and attributes and must be accounted for. See How does XPath deal with XML namespaces?

Then, incrementally add XPath steps from there:

  1. //book[genres] should select book elements with any genres child element.

  2. //book[genres/genre] should select book elements with any genres child element, only if it in turn has a genre child element.

  3. //book[genres/genre = 'Romance'] should select all books in Romance genre, as requested. Note that 'Romance' must be quoted; otherwise, the expression would be testing against the string value of a Romance child element of book and will certainly fail.

Tags:

Xml

Xpath