2009-09-28 111 views
1

說我有從一組xpath中找到共同的祖先?

html/body/span/div/p/h1/i/font 
html/body/span/div/div/div/div/table/tr/p/h1 
html/body/span/p/h1/b 
html/body/span/div 

我怎樣才能得到共同的祖先?在這種情況下,跨度將是的共同祖先「字型,H1,B,格」「跨度」

+0

什麼是你想怎麼辦:

(node1.ancestors & node2.ancestors).first 

與多個節點的工作更廣義函數? – Tomalak 2009-09-28 09:50:52

+0

試着給我們一個你想要解決的問題的大圖。 – Javier 2009-09-28 14:02:05

回答

3

要找到共同的祖先兩個節點之間:

# accepts node objects or selector strings 
class Nokogiri::XML::Element 
    def common_ancestor(*nodes) 
    nodes = nodes.map do |node| 
     String === node ? self.document.at(node) : node 
    end 

    nodes.inject(self.ancestors) do |common, node| 
     common & node.ancestors 
    end.first 
    end 
end 

# usage: 

node1.common_ancestor(node2, '//foo/bar') 
# => <ancestor node> 
0

了以下功能common_ancestor你想要做什麼。

require 'rubygems' 
require 'nokogiri' 

doc = Nokogiri::XML(DATA) 

def common_ancestor *elements 
    return nil if elements.empty? 
    elements.map! do |e| [ e, [e] ] end #prepare array 
    elements.map! do |e| # build array of ancestors for each given element 
    e[1].unshift e[0] while e[0].respond_to?(:parent) and e[0] = e[0].parent 
    e[1] 
    end 
    # merge corresponding ancestors and find the last where all ancestors are the same 
    elements[0].zip(*elements[1..-1]).select { |e| e.uniq.length == 1 }.flatten.last 
end 

i = doc.xpath('//*[@id="i"]').first 
div = doc.xpath('//*[@id="div"]').first 
h1 = doc.xpath('//*[@id="h1"]').first 

p common_ancestor i, div, h1 # => gives the p element 

__END__ 
<html> 
    <body> 
    <span> 
     <p id="common-ancestor"> 
     <div> 
      <p><h1><i id="i"></i></h1></p> 
      <div id="div"></div> 
     </div> 
     <p> 
      <h1 id="h1"></h1> 
     </p> 
     <div></div> 
     </p> 
    </span> 
    </body> 
</html> 
相關問題