xml XPath 中的多个条件(和运算符)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24373490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 12:03:23  来源:igfitidea点击:

Multiple conditions (and operator) in XPath

xmlxsltxpath

提问by Cédric Bignon

I have the following XML:

我有以下 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 nameof bookin myBooksthat have not a corresponding bookin books(title and author).

我想所有namebookmyBooks那没有一个相应bookbooks(标题和作者)。

So, for the example, I want to retrieve: the book "Test2"because the pair ("Title 2", "Author 1")does not exist in books.

因此,例如,我想检索:这本书,"Test2"因为这对("Title 2", "Author 1")不存在于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").

但是,当然,在这种情况下,上述 XPath 不起作用,因为存在组合(“标题 2”、“作者 1”)(来自“book2”和“book1”)。

How can I apply the andoperator on the same node?

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

采纳答案by Ian Roberts

It depends on the version of XPath.

这取决于 XPath 的版本。

You can't do this in a single XPath 1.0 expression because it would require a structure like

您不能在单个 XPath 1.0 表达式中执行此操作,因为它需要类似的结构

/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 myBooksyourself (e.g. with an xsl:for-each, as you've tagged your question "xslt").

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

In XPath 2.0 you cando it in one expression with an explicit quantifier

在 XPath 2.0 中,您可以在一个带有显式量词的表达式中完成

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

回答by alecxe

You can concatenate attribute values using concat()and compare them:

您可以使用concat()并比较它们来连接属性值:

//myBooks/book[not(concat(@*[name() = "title" or name() = "author"], ",") = concat(//books/book/@*[name() = "title" or name() = "author"], ","))]

For every bookin myBookit gets the concatenation of titleand authorattributes and compares it with the same concatenation for every bookin books.

For each bookin myBookit 获得titleauthor属性的串联,并将它与每个bookin的相同串联进行比较books

Demo (using xmllint):

演示(使用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"/>

回答by Martin Honnen

Assuming XSLT I would define a key <xsl:key name="book" match="books/book" use="concat(@title, '|', @author)"/>and then in the predicate you can check [not(key('book', concat(@title, '|', @author)))].

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