Nokogiri:根据HTML文档中的顺序对ID数组进行排序

时间:2009-05-06 15:22:03

标签: javascript ruby-on-rails ruby dom nokogiri

我有一个未排序的数组,其中包含以下ID:

@un_array = ['bar', 'para-3', 'para-2', 'para-7']

是否有一种使用Nokogiri(或普通Javascript)根据下面示例HTML文档中ID的顺序对数组进行排序的智能方法?

require 'rubygems'
require 'nokogiri'

value = Nokogiri::HTML.parse(<<-HTML_END)
  "<html>
    <head>
    </head>
    <body>
        <p id='para-1'>A</p>
        <div id='foo'>
            <p id='para-2'>B</p>
        <p id='para-3'>C</p>
            <div id='bar'>
                <p id='para-4'>D</p>
                <p id='para-5'>E</p>
                <p id='para-6'>F</p>
        </div>
         <p id='para-7'>G</p>
        </div>
        <p id='para-8'>H</p>
    </body>
    </html>"
HTML_END

在这种情况下,生成的排序数组应为:

['para-2', 'para-3', 'bar', 'para-7']

3 个答案:

答案 0 :(得分:1)

我不知道Nokogiri是什么,但如果您将HTML代码作为字符串,则可以通过regexp匹配获得订单,例如:

var str = '<html>...</html>'; // the HTML code to check
var ids = ['bar', 'para-3', 'para-2', 'para-7']; // the array with all IDs to check
var reg = new RegExp('(?:id=[\'"])('+ids.join('|')+')(?:[\'"])','g') // the regexp
var result = [], tmp; // array holding the result and a temporary variable
while((tmp = reg.exec(str))!==null)result.push(tmp[1]); // matching the IDs
console.log(result); // ['para-2', 'para-3', 'bar', 'para-7']

使用此代码时,您必须小心包含正则表达式元字符的ID。他们应该先逃脱。

答案 1 :(得分:0)

这是在Nokogiri中实现这一目标的一种方法 - 可能还有其他更有效的方法,因为这最终导致了整个DOM。

require 'set'

#Using a set here to make lookup O(1), because we don't care about the initial order
id_set = ['bar', 'para-3', 'para-2', 'para-7'].to_set
sorted = []

value.root.traverse do |node|
  node_id = node['id']
  sorted << node_id if node_id && id_set.delete?(node_id)
end
# sorted is now ['para-2', 'para-3', 'bar', 'para-7']

编辑:这是一个获得相同结果的单线程,但我没有做基准测试以确定哪个更快。

ids = ['bar', 'para-3', 'para-2', 'para-7']
value.xpath("//*[@id]").collect {|node| node['id']} & ids

答案 2 :(得分:0)

这是同事和我提出的解决方案:

parent = value.css('body').first
indexes = []
parent.children.each do |child|
  indexes << child['id']
end

puts @un_array.sort! { |x,y| indexes.index(x) <=> indexes.index(y) }

首先,我将HTML文档的所有ID都提取到一个数组中,而不是根据我之前创建的ID-Array对@un_array进行排序。