【问题标题】:In Nokogiri, how do I find all the nodes that come before a certain node in my document?在 Nokogiri 中,如何找到文档中某个节点之前的所有节点?
【发布时间】:2017-08-30 07:37:15
【问题描述】:

使用 Rails 5、Ruby 2.4。如果我使用 Nokogiri 解析找到了一个节点,我将如何找到在我找到的节点之前出现的所有节点,这些节点不包括该找到的节点?也就是说,假设我的文档是

<outer>
    <p>Hello</p>
    <inner>
        <most_inner class="abc">Howdy</most_inner>
        <most_inner class="def">Next</most_inner>
    </inner>
</outer>

然后我运行一个类似的查询

node = doc.search('//*[contains(@class, "def")]').first

如何定位所有前面的节点(不包括我刚刚确定的节点)?我期望的节点是

<p>Hello</p>
<most_inner>Howdy</most_inner>

【问题讨论】:

  • 为什么没有选择&lt;inner&gt;?为什么要定位最后一个 &lt;most_inner&gt; 节点?您是否只想要&lt;inner&gt; 或该级别的所有其他人的前一个兄弟?你的问题没有显示出很多努力的证据。请阅读“How much research effort is expected of Stack Overflow users?”和“minimal reproducible example”。
  • inner 包括 most_inner 节点,他想排除它,正如我理解的那样
  • 嗨@TheChamp,你是对的——无论有问题的节点是什么,我都希望找到不包含该节点的所有先前节点。
  • 如果.abc 实际上是&lt;really_inner class="abc"&gt;&lt;most_inner&gt;Howdy&lt;/most_inner&gt;&lt;/really_inner&gt;,您对答案有何期望? most_inner、really_inner,还是两者兼而有之?
  • 在您的示例中,整个文档是“Howdy”吗?如果是这样,则在“abc”类的节点之前没有节点,所以我希望答案什么都不是。如果文档是“StuffhiHowdy”,并且有问题的节点是一个具有“abc”类的人,我希望答案是“Stuffhi”

标签: ruby parsing nokogiri ruby-on-rails-5


【解决方案1】:

您只需要遍历叶子节点,直到到达目标节点。

# Node to exclude
node = doc.search('//*[contains(@class, "def")]').first
preceding_nodes = []

# Find all leaf nodes
leaf_nodes = doc.xpath("//*[not(child::*)]")

leaf_nodes.each do |leaf|
  if leaf == node
    break
  else
    preceding_nodes.push(leaf)
  end
end

preceding_nodes # => Contains all preceding leaf nodes

【讨论】:

  • 我只是以一个节点为 class="def" 为例 -- 有问题的节点可能没有 class="def"。但是您的示例无论如何都行不通,对吧-因为它会挑选出出现在具有 class="def" 的节点之后的叶节点?我知道我的示例没有任何此类节点,但另一个文档可能。
  • 啊,你是对的!不太清楚你想要什么。我已经相应地更新了答案!
  • 嗨,我仍然没有得到想要的结果。如果我使用“ doc = Nokogiri.XML(' ', nil, 'EUC-JP') ",运行您的代码会返回 "" 节点,我不希望它出现在我正在查看的节点之后。我只想返回在问题中的节点之前(之前)的节点。
  • 我误会了第二次!您只需要遍历节点集,直到到达目标节点。答案已更新。
  • 感谢您对您的回答进行改进。问题是由于某种原因你只考虑叶节点。这不是我的要求。我想在有问题的节点之前找到所有不包含该节点的节点。所以,这个文档,'doc = Nokogiri.XML('This is Bold text ', nil, 'EUC-JP')' 不包含使用您的逻辑的“”元素——可能是因为“”节点中有一个“”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-02
  • 2022-08-27
  • 1970-01-01
  • 1970-01-01
  • 2011-05-22
  • 1970-01-01
相关资源
最近更新 更多