为什么 XPath contains() select 一个意外的节点?

Why does XPath contains() select an unexpected node?

我正在尝试找到正确的 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

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

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

你的 XPath 的原因,

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

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

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

实现预期结果的备选方案

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

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

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

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

另见