改进 XPath 查询以正确区分文本节点
Improve XPath-query to distinguish text-nodes correctly
我过去广泛使用 XPath。目前我遇到了一个问题,我无法解决。
约束
- 纯 XPath 1.0
- 没有辅助功能(例如没有 "concat()")
HTML-标记
<span class="container">
Peter: Lorem Impsum
<i class="divider" role="img" aria-label="|"></i>
Paul Smith: Foo Bar BAZ
<i class="divider" role="img" aria-label="|"></i>
Mary: One Two Three
</span>
挑战
我想提取三个连贯的字符串:
- 彼得:Lorem Impsum
- 保罗·史密斯:Foo Bar BAZ
- 玛丽:一二三
XPath
以下 XPath 查询是我经过数小时的研究得出的最佳查询:
XPath 查询 1
//span[contains(@class, "container")]
=> Peter: Lorem ImpsumPaul Smith: Foo Bar BAZMary: One Two Three
XPath 查询 2
//span[contains(@class, "container")]//text()
Peter: Lorem Impsum Paul Smith: Foo Bar BAZ Mary: One Two Three
问题
尽管之后可以使用 (PHP) 字符串函数 post 处理结果字符串,但我无法将其拆分为正确的三个块:我需要一个 XPath 查询,它使我能够正确区分文本节点。
是否可以在文本节点之间整合一些 "artificial separators"?
您对 XPath 1.0 的期望过高。 XPath 1.0 本身可以帮助您达到 select
- 一个字符串,或者
- 一组文本节点
然后,您必须在 XPath 之外完成处理(如 Mads 在评论中所建议的那样)。
要了解您遇到的限制,您的第一个 XPath,
//span[contains(@class, "container")]
select 是 span
个元素的节点集。 XPath 1.0 运行的环境向您显示(某些变体)文档中单个此类节点的 字符串值 :
Peter: Lorem ImpsumPaul Smith: Foo Bar BAZMary: One Two Three
但要清楚:您的 XPath 是 selecting 一个 span
元素的节点集,而不是这里的字符串。
你的第二个 XPath,
//span[contains(@class, "container")]//text()
select 是 text()
个节点的节点集。 XPath 1.0 运行的环境显示每个 selected text()
节点的 字符串值 。
如果你可以使用 XPath 2.0,你可以直接在 XPath 中,select 一个 字符串序列 ,
//span[contains(@class, "container")]/text()/string()
或者你可以加入他们,
string-join(//span[contains(@class, "container")]/text(), "|")
直接得到
Peter: Lorem Impsum
|
Paul Smith: Foo Bar BAZ
|
Mary: One Two Three
或
string-join(//span[contains(@class, "container")]/text()/normalize-space(), "|")
获得
Peter: Lorem Impsum|Paul Smith: Foo Bar BAZ|Mary: One Two Three
我过去广泛使用 XPath。目前我遇到了一个问题,我无法解决。
约束
- 纯 XPath 1.0
- 没有辅助功能(例如没有 "concat()")
HTML-标记
<span class="container">
Peter: Lorem Impsum
<i class="divider" role="img" aria-label="|"></i>
Paul Smith: Foo Bar BAZ
<i class="divider" role="img" aria-label="|"></i>
Mary: One Two Three
</span>
挑战
我想提取三个连贯的字符串:
- 彼得:Lorem Impsum
- 保罗·史密斯:Foo Bar BAZ
- 玛丽:一二三
XPath
以下 XPath 查询是我经过数小时的研究得出的最佳查询:
XPath 查询 1
//span[contains(@class, "container")]
=> Peter: Lorem ImpsumPaul Smith: Foo Bar BAZMary: One Two Three
XPath 查询 2
//span[contains(@class, "container")]//text()
Peter: Lorem Impsum Paul Smith: Foo Bar BAZ Mary: One Two Three
问题
尽管之后可以使用 (PHP) 字符串函数 post 处理结果字符串,但我无法将其拆分为正确的三个块:我需要一个 XPath 查询,它使我能够正确区分文本节点。
是否可以在文本节点之间整合一些 "artificial separators"?
您对 XPath 1.0 的期望过高。 XPath 1.0 本身可以帮助您达到 select
- 一个字符串,或者
- 一组文本节点
然后,您必须在 XPath 之外完成处理(如 Mads 在评论中所建议的那样)。
要了解您遇到的限制,您的第一个 XPath,
//span[contains(@class, "container")]
select 是 span
个元素的节点集。 XPath 1.0 运行的环境向您显示(某些变体)文档中单个此类节点的 字符串值 :
Peter: Lorem ImpsumPaul Smith: Foo Bar BAZMary: One Two Three
但要清楚:您的 XPath 是 selecting 一个 span
元素的节点集,而不是这里的字符串。
你的第二个 XPath,
//span[contains(@class, "container")]//text()
select 是 text()
个节点的节点集。 XPath 1.0 运行的环境显示每个 selected text()
节点的 字符串值 。
如果你可以使用 XPath 2.0,你可以直接在 XPath 中,select 一个 字符串序列 ,
//span[contains(@class, "container")]/text()/string()
或者你可以加入他们,
string-join(//span[contains(@class, "container")]/text(), "|")
直接得到
Peter: Lorem Impsum
|
Paul Smith: Foo Bar BAZ
|
Mary: One Two Three
或
string-join(//span[contains(@class, "container")]/text()/normalize-space(), "|")
获得
Peter: Lorem Impsum|Paul Smith: Foo Bar BAZ|Mary: One Two Three