【问题标题】:What XPath can I use to get all text nodes after and including the first paragraph node?我可以使用什么 XPath 来获取包含第一段节点之后的所有文本节点?
【发布时间】:2013-03-29 19:21:03
【问题描述】:

我是 Nokogiri 的新手,一般来说是 Ruby。

我想获取文档中所有节点的文本,从第一个段落节点开始并包括在内。

我使用 XPath 尝试了以下操作,但无济于事:

 puts page.search("//p[0]/text()[next-sibling::node()]")

这不起作用。我需要改变什么?

【问题讨论】:

  • 提供相关 XML 的小样本很重要。
  • 不,不是指向您的示例的链接,请在问题中放置一个示例,大到足以证明问题,而不是更大。一个链接使我们能够追踪我们需要帮助您的信息,而且,因为我们是自愿这样做的,在我们的业余时间,您让我们做额外的工作来帮助您。不要那样做。此外,链接断开,使您的问题对于将来搜索相同问题的人毫无价值。
  • @theTinMan ,好吧,对不起,链接,我正在使用该页面作为示例,所以我按原样提供了整个页面,无论如何在未来,请确保我按照你说的做. Jens Erat 已经为我提供了一个可行的解决方案,所以我认为您不需要再花时间在上面了。我还想说,我从您处理 Nokogiri 和 Xpath 的各种答案中学到了很多东西,所以我一定会回来为您提出更多问题。再次感谢,再见。
  • @theTinMan,正如我所承诺的那样,我对 Nokogiri 有另一个令人困惑的问题,希望你能帮助我。这是问题的链接*.com/questions/15931848/…

标签: ruby xpath nokogiri


【解决方案1】:

您必须找到<p/> 节点并返回所有text() 节点,包括内部和后续。根据 Nokogiri 的 XPath 功能,使用以下查询之一:

//p[1]/(descendant::text() | following::text())

如果它不起作用,请改用它,它需要找到第一段两次,并且可能会有点,但可能不明显,更慢:

(//p[1]/descendant::text() | //p[1]/following::text())

一个可能不受支持的 XPath 2.0 替代方案是:

//text()[//p[1] << .]

表示“文档中第一个 &lt;p/&gt; 节点之前的所有文本节点”。

【讨论】:

  • +1,但请注意,只有您的第二个表达式适用于 Nokogiri。
  • 这是我的预期,因此我提供了多个。我不确定第一个是否是有效的 XPath 1.0 但在 nokogiri 上不受支持,或者它是否也是 XPath 2.0。由于最后一个是编写该查询的最优雅的版本,所以我还是将其包含在内。
  • @JensErat ,谢谢老兄,它就像一个魅力。还有一件事,我的任务是解析这些德语网页,然后基本上将文章内容分成句子和单词,我的问题是面向正则表达式的。我可以用英语完成工作,但我不知道用德语做什么,拆分德语字符时的最佳做法是什么。 (我的正则表达式被变音符号和 eszets 弄乱了,)我在 php 中尝试了 \p{l} 和 \X 修饰符,但没有运气。如果您或其他任何人认为他们可以帮助我解决这个问题,我会提供完整的示例。thnx
  • 我想你应该问一个新问题来让一些人更熟悉 PHP 中的 XPath。如果您能够使用另一个 XPath/XQuery 引擎,请考虑使用 BaseX 提供的 XQuery Full Text 和许多其他 XQuery 引擎。它可以为您省去很多标记化的麻烦。
【解决方案2】:

这适用于 Nokogiri(位于 libxml2 之上并支持 XPath 1.0 表达式):

//p[1]//text() | //p[1]/following::text()

证明:

require 'nokogiri'

html = '<body><h1>A</h1><p>B <b>C</b></p><p>D <b>E</b></p></body>'
doc = Nokogiri.HTML(html)

p doc.xpath('//p[1]//text() | //p[1]/following::text()').map(&:text)
#=> ["B ", "C", "D ", "E"]

请注意,仅选择文本节点本身会返回 Nokogiri::XML::Text 对象中的 NodeSet,因此如果您只想要它们的文本内容,则必须通过 .text(或 .content)方法映射它们。

【讨论】:

  • 这看起来是对的,但我不认为 [1] 是必要的
  • @Phrogz,+1,谢谢这也有效。请你帮我解决我的其他问题(我将它添加为评论,在 jens erat 的回答下方)
最近更新 更多