在Nokogiri中选择子节点的绝对最便宜的方法是什么?

时间:2010-01-22 10:37:15

标签: xml ruby nokogiri

我知道有几十种方法可以选择Nokogiri的第一个子元素,但哪个最便宜? 我无法使用Node#children,这听起来非常昂贵。假设有10000个子节点,我不想触及9999个其他节点......

3 个答案:

答案 0 :(得分:2)

您可以自己尝试并对结果进行基准测试。

我创建了一个快速基准:http://gist.github.com/283825

$ ruby test.rb 
Rehearsal ---------------------------------------------------
xpath/first()     3.290000   0.030000   3.320000 (  3.321197)
xpath.first       3.360000   0.010000   3.370000 (  3.381171)
at                4.540000   0.020000   4.560000 (  4.564249)
at_xpath          3.420000   0.010000   3.430000 (  3.430933)
children.second   0.220000   0.010000   0.230000 (  0.233090)
----------------------------------------- total: 14.910000sec

                      user     system      total        real
xpath/first()     3.280000   0.000000   3.280000 (  3.288647)
xpath.first       3.350000   0.020000   3.370000 (  3.374778)
at                4.530000   0.040000   4.570000 (  4.580512)
at_xpath          3.410000   0.010000   3.420000 (  3.421551)
children.second   0.220000   0.010000   0.230000 (  0.226846)

从我的测试来看,children似乎是最快的方法。

答案 1 :(得分:1)

Node#child是获取第一个子元素的最快方法。

但是,如果您要查找的节点不是第一个节点(例如,第99个节点),则没有更快的方法来选择该节点,而不是调用#children并将其编入索引。

你说的是,如果你只想要第一个孩子,为所有孩子建立一个NodeSet是很昂贵的。

一个限制因素是libxml2(Nokogiri底层的XML库)将节点的子节点存储为链接列表。因此,您需要遍历列表(O(n))以选择所需的子节点。

编写一个简单地返回第n个子节点的方法是可行的,而不需要为所有其他子节点实例化NodeSet甚至ruby对象。我的建议是在http://github.com/tenderlove/nokogiri/issues打开功能请求,或发送电子邮件到nokogiri邮件列表。

答案 2 :(得分:0)

既不使用XPath也不导致解析整个父节点的方法是同时使用Node#child(),Node#next_sibling()和Node#元素?()

像这样......

def first(node)
    element = node.child
    while element
       if element.element?
           return element
       else
           element = element.next
       end
    end
    nil
end