如何计算Nokogiri节点后代的"levels"数?



您可以调用Nokogiri::XML::Node#ancestors.size来查看节点嵌套的深度。但是,是否有一种方法可以确定节点的最深层子节点的嵌套深度有多深?

或者,你如何找到从一个节点下来的所有叶节点?

下面的代码只是为了好玩而对Nokogiri::XML::Node进行了修补,当然,如果您愿意,也可以将它们提取为单独的方法,并接受一个节点参数。(只有height方法是你问题的一部分,但我认为deepest_leaves方法可能会很有趣。)

require 'nokogiri'
class Nokogiri::XML::Node
  def depth
    ancestors.size
    # The following is ~10x slower: xpath('count(ancestor::node())').to_i
  end
  def leaves
    xpath('.//*[not(*)]').to_a
  end
  def height
    tallest = leaves.map{ |leaf| leaf.depth }.max
    tallest ? tallest - depth : 0
  end
  def deepest_leaves
    by_height = leaves.group_by{ |leaf| leaf.depth }
    by_height[ by_height.keys.max ]
  end
end
doc = Nokogiri::XML "<root>
  <a1>
    <b1></b1>
    <b2><c1><d1 /><d2><e1 /><e2 /></d2></c1><c2><d3><e3/></d3></c2></b2>
  </a1>
  <a2><b><c><d><e><f /></e></d></c></b></a2>
</root>"
a1 = doc.at_xpath('//a1')
p a1.height                      #=> 4
p a1.deepest_leaves.map(&:name)  #=> ["e1", "e2", "e3"]
p a1.leaves.map(&:name)          #=> ["b1", "d1", "e1", "e2", "e3"]

编辑:简短地回答所问的问题,而不是将其包装成可重用的部分:

p a1.xpath('.//*[not(*)]').map{ |n| n.ancestors.size }.max - a1.ancestors.size

你可以打电话Nokogiri: XML:: #祖先节点。大小查看节点的嵌套深度。但有没有办法确定深度有多深的最深层嵌套子节点一个节点是?

使用

:

count(ancestor::node())

这个表达式表示上下文(当前)节点在文档层次结构中拥有的祖先节点的数目。

查找"嵌套最深的子节点"的嵌套级别。一个人必须首先确定所有的"叶子"。节点:

descendant-or-self::node()[not(node())]

,并使用上面的XPath表达式获得它们的嵌套级别。

然后必须计算最大嵌套级别(生成的所有数字的最大值),而最后的计算对于纯XPath 1.0是不可能的。

可以用单个XPath 2.0表达式表示:

max(for $leaf in /descendant-or-self::node()[not(node())],
        $depth in count($leaf/ancestor::node())
      return
        $depth
    )

:

可以进一步缩短XPath 2.0表达式:

max(/descendant-or-self::node()[not(node())]/count(ancestor::node()))

相关内容

  • 没有找到相关文章

最新更新