xml - 使用XPATH,如何选择包含特定字符串的任何节点

标签 xml xpath contains

假设我有一个像这样的 XML 文件:

<books>
  <book>
    <title>John is alive</title>
    <abstract>
        A man is found alive after having disappeared for 10 years.
    </abstract>
    <description>
        <en> John disappeared 10 years ago. Lorem ipsum dolor sit amet ...</en>
        <fr> Il y a 10 ans, John disparaissait. Lorem ipsum dolor sit amet ...</fr>
    </description>
    <notes>First book in the series, where the character is introduced</notes>
  </book>
  <book>
    <title>The disappearance of John</title>
    <abstract>
        A prequel to the book "John is alive".
    </abstract>
    <description>
        <en> He lead an ordinary life, but then ... lorem ipsum dolor sit amet ...</en>
        <fr> Sa vie était tout à fait ordinaire, mais ... lorem ipsum dolor sit amet ...</fr>
    </description>
    <notes>Second book in the "John" series, but first in chronological order</notes>
  </book>
</books>

我的问题很简单:如何使用 XPATH 获取包含单词 John 的所有节点的集合?

显然,我可以指定一系列节点并且效果很好:

(//title | //abstract | //description/* | //notes)[contains(lower-case(text()),"john")]

但是,如果我的 XML 增长(而且它会增长!),并且在结构的各个级别添加新元素,我不想经常返回并调整我的 XPATH。

我不明白的是为什么像这样的通用声明

//*[contains(lower-case(text()),"john")]

失败并显示此错误消息 Required cardinality of first argument of lower-case() is one or zero .

然而,并非所有带星号的语句都会失败。

例如:

//books/book/*[contains(lower-case(text()),"john")]失败并显示上述错误消息

同时

//books/book/*/*[contains(lower-case(text()),"john")]成功并检索 <en><fr>从第一个 <description> 开始的节点元素

如果不可能,那好吧,我会列出 XPATH 中的所有元素,但我仍然想清楚地了解 * 的行为。 contains() 上下文中的选择器操作。

最佳答案

当不太精确时,术语节点(请参阅 XPath difference between child::* and child::node() )和术语包含(请参阅 How to use XPath contains() for specific text? )存在一些歧义,但其中之一以下 XPath 可能会满足您的需求:

  1. 所有节点,其 string value包含子字符串 "John":

    //node()[contains(.,"John")]
    
  2. 所有此类元素:

    //*[contains(.,"John")]
    
  3. 所有此类属性:

    //@*[contains(.,"John")]
    
  4. 所有此类文本节点:

    //text()[contains(.,"John")]
    
  5. 所有带有包含子字符串 "John" 的文本节点子节点的元素:

    //*[text()[contains(.,"John")]]
    

请注意,#1 将包含 books,但 #5 将排除它。请参阅Testing text() nodes vs string values in XPath .

您可以将上述任何 XPath 中的 contains(.,"John") 替换为 contains(lower-case(.),"john") 如果您正在使用 XPath 2.0。另请参阅Case insensitive XPath contains() possible?

关于xml - 使用XPATH,如何选择包含特定字符串的任何节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65850091/

相关文章:

xpath - 每个无结果文本

java - 如何搜索内容与另一个数组匹配的一个数组?

String::contains(String) 给出 "the trait bound String: FnMut<(char,)>` 不满足”

c# - .NET 中的 XPath 选择节点

java - 在 WebView 中打开所需的链接

java - 具有嵌套元素的 JAXB

c# - 使用C#XMLDocument读取YouTube channel XML文件

xpath - Google表格中的ImportXML函数产生错误“导入的内容为空”!

xpath - 使用XPATH之前的::更像是数组

python 如何查找一个字典是否包含其他字典中的数据