【问题标题】:Why does XPath contains() select an unexpected node?为什么 XPath contains() 选择了一个意外的节点?
【发布时间】:2022-01-04 16:19:36
【问题描述】:

我正在尝试找到正确的 XPath 表达式以仅从我的所有文档中获取 URL,无论标签是什么。我正在尝试这个:

<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://url
    </loc>
    <lastmod>2019-08-07T15:01:51+00:00
    </lastmod>
  </url>
</urlset>

下面的表达式给了我这些结果:

//*[contains(.,'http')]//text()
  1. https://url
  2. 2019-08-07T15:01:51+00:00

我正在寻找的是摆脱第二行。我需要能够从任何 XML 文件中获取仅 URL

【问题讨论】:

    标签: xml xpath


    【解决方案1】:

    你的 XPath 的原因,

    //*[contains(.,'http')]//text()
    

    选择令人惊讶的第二个结果是,此 XPath 表示选择所有 string-value 包含 "http" 子字符串的元素,并返回所有后代文本节点。这些元素不仅包括目标文本节点的直接父元素,还包括其祖先:

    1. loc 元素,如您所料。
    2. urlseturl 也如您所料。 (urlseturl 元素也有一个 2019-08-07T15:01:51+00:00 后代文本节点,因此是它们的字符串值的一部分。)

    实现预期结果的替代方案

    • * 所有元素通配符缩小为单个命名元素:

      //loc[contains(.,'http')]/text()
      
    • * all-elements 通配符缩小为多个命名元素:

      //*[(self::loc or self::e2) and contains(.,'http')]/text()
      
    • 选择包含子字符串"http"as noted by Michael Kay的所有文本节点:

      //text()[contains(., 'http')]
      

    另见

    【讨论】:

    • 谢谢。我已经看过这些主题,但没有找到我搜索的正确语法(这是最后一个)。我面临的问题是我不确定我会在我的 xml 文档中找到的标签。这就是为什么我需要在文本中搜索标签是什么。如果我的 xml 中没有任何 标签,我不确定你的第一个和第二个选择是否有效(如果我错了,我很想知道为什么)。
    • 第一个和第二个选项确实假定命名元素的存在。请记住,精心设计的标记消除了对文本进行模式匹配的需要,因为标记的全部意义在于识别文档部分。
    【解决方案2】:

    好吧,让我们忽略一个事实,即并非所有 URL 都包含“http”,也不是所有包含“http”的东西都是 URL...

    要查找所有包含“http”的文本节点,只需使用//text()[contains(., 'http')]

    【讨论】:

    • 如果我使用 www 会更合理吗?
    • 我不知道什么对你来说是合理的——你知道你的数据,我不知道。检测像 'index.html' 这样的相对 URI 很困难!通常最好利用 XML 标记而不是依赖匹配内容。
    • 我没关系。我只是事先不知道我会找到哪些标签。但谢谢你,它帮助了我。
    猜你喜欢
    • 2017-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    相关资源
    最近更新 更多