XPath中的多重条件(与运算符)

13

我有以下的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>

我想获取在myBooks中所有没有对应的书名和作者(books中不存在相应的书)的book名称。

所以,根据这个例子,我想检索出:"Test2" ,因为在books中没有这个书名以及对应的作者("Title 2" 和 "Author 1")。

目前,我已经有:

//myBooks/book[not(@title = //books/book/@title and @author = //books/book/@author)]

当然,在这种情况下,由于组合(“Title 2”,“Author 1”)存在(来自“book2”和“book1”),上述XPath无法工作。

我如何在同一节点上应用and运算符?

3个回答

15

这取决于XPath的版本。

在单个XPath 1.0表达式中无法完成此操作,因为它需要类似于以下结构的结构:

/bookstore/myBooks/book[/bookstore/books/book[
                  @title = _outer-predicate_/@title and
                  @author = _outer-predicate_/@author]]/@name

即,您需要捕获外谓词正在测试的书籍,以便将其与内部谓词进行比较。纯XPath 1.0不支持此功能,您必须自己遍历myBooks的内容(例如使用xsl:for-each,因为您已经将问题标记为“xslt”)。

在XPath 2.0中,您可以使用显式量词在一个表达式中完成此操作。

/bookstore/myBooks/book[not(some $book in /bookstore/books/book satisfies
       ($book/@author = @author and $book/@title = @title))]/@name

XPath 2.0版本正是我所需要的。谢谢。 - Cédric Bignon

4
您可以使用concat()连接属性值并进行比较:
//myBooks/book[not(concat(@*[name() = "title" or name() = "author"], ",") = concat(//books/book/@*[name() = "title" or name() = "author"], ","))]

对于myBook中的每一本书,它会获取titleauthor属性的拼接,并将其与books中每一本书的相同拼接进行比较。

Demo(使用xmllint):

$ xmllint input.xml --xpath '//myBooks/book[not(concat(@*[name() = "title" or name() = "author"], ",") = concat(//books/book/@*[name() = "title" or name() = "author"], ","))]'
<book name="Test2" title="Title 2" author="Author 1"/>

3
假设使用XSLT,我会定义一个键 <xsl:key name="book" match="books/book" use="concat(@title, '|', @author)"/>,然后在谓词中可以检查 [not(key('book', concat(@title, '|', @author)))]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接