I have the following XML:
<bookstore>
<books>
<book name="book1" title="Title 1" author="Author 1"/>
<book name="book2" title="Title 2" author="Author 2"/>
<book name="book3" title="Title 1" author="Author 2"/>
</books>
<myBooks>
<book name="Test1" title="Title 1" author="Author 1"/>
<book name="Test2" title="Title 2" author="Author 1"/>
<book name="Test3" title="Title 1" author="Author 2"/>
</myBooks>
</bookstore>
I want to get all name
of book
in myBooks
that have not a corresponding book
in books
(title and author).
So, for the example, I want to retrieve: the book "Test2"
because the pair ("Title 2", "Author 1")
does not exist in books
.
So far, I have:
//myBooks/book[not(@title = //books/book/@title and @author = //books/book/@author)]
But, of course, in that case, the above XPath does not work because the combination ("Title 2", "Author 1") exists (from "book2" and "book1").
How can I apply the and
operator on the same node?
It depends on the version of XPath.
You can't do this in a single XPath 1.0 expression because it would require a structure like
/bookstore/myBooks/book[/bookstore/books/book[
@title = _outer-predicate_/@title and
@author = _outer-predicate_/@author]]/@name
i.e. you'd need to capture the book being tested by the outer predicate so you can compare it to the inner one. Pure XPath 1.0 doesn't support this, you'd have to iterate over the content of myBooks
yourself (e.g. with an xsl:for-each
, as you've tagged your question "xslt").
In XPath 2.0 you can do it in one expression with an explicit quantifier
/bookstore/myBooks/book[not(some $book in /bookstore/books/book satisfies
($book/@author = @author and $book/@title = @title))]/@name
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With