2010-09-24 54 views
1

目前我使用解析一個引入nokogiri HTML文檔,並通過所有code標籤這樣的迭代:查找標籤的行數的HTML文檔中

html = Nokogiri::HTML(doc) 
html.css("code").each do |code| 
    # do something with code 
    if /^@@@@/.match(code.text.split("\n")[0]) 
    return "this code element is at line blah" 
    end  
end 

我不使用Nokogiri,使用迭代遍歷所有代碼元素非常方便。

如果code標籤以@@@@開頭,那麼我希望能夠引用發生該標籤的文檔中的行號。請記住,兩個代碼標籤可以是相同的。

回答

1

有幾個原因,引入nokogiri可能返回0行號節點使用HTML解析器檢索,既涉及lbxml。

  1. 在libxml的
  2. 的2.7.3版本

一個錯誤的信用:亞倫帕特森AKA tenderlove https://github.com/sparklemotion/nokogiri/issues/closed#issue/347

2。您正在使用的Nokogiri版本是針對不同於您目前在系統上使用的libxml版本而構建的。

這是我的問題。我有libxml版本2.7.8,並看到這種行爲。我沒有安裝寶石在本地,所以我繼續這樣做

$ sudo gem install nokogiri 

如果你已經有了創業板安裝它也不過是1個額外的步驟將其卸載

$ gem uninstall nokogiri 
$ gem install nokogiri 

信用 - Tin Man's Answer to this question

要確定的libxml版本您當前正在運行

$nokogiri -v 

我目前的設置(工作)

ruby: 
engine: mri 
version: 1.8.7 
platform: universal-darwin10.0 

libxml: 
loaded: 2.7.8 
binding: extension 
compiled: 2.7.8 
nokogiri: 1.4.4 
+0

謝謝你的回答,那就是我提出這個問題的人。對你花時間解釋它作爲SO上的答案很好。 – 2011-03-05 05:31:44

0

像這樣的東西可能會幫助你開始:

 
#!/usr/bin/env ruby 

require 'nokogiri' 

html = Nokogiri::HTML(File.open('./test.html', 'r')) 

code_nodes = html.css('code').select{ |node| node.text[/^@@@@/] } 
code_nodes.each do |node| 

    # point to the end of the current line 
    current_node = node.next 
    line_num = 0 

    while (current_node) do 
    # count line-endings 
    line_num += current_node.text.count("\n") 

    # get the previous node (AKA the one above this one.) 
    current_node = current_node.previous 
    end 

    puts line_num 
end 

其中test.html樣子:

 
<html> 
    <body> 
    <code>1</code> 
    <code>@@@@2</code> 
    <code>3</code> 
    </body> 
</html> 

這是快速「N髒的代碼,並沒有得到完全正確的,但我認爲基本想法是健全的。您需要在其中找到帶有「@@@@」的節點,然後向後計算包含行尾的文本節點,直到到達頂層節點。

由於使用.previous()似乎沒有得到previous_sibling()節點,這意味着<head>塊中的任何內容都不會被計數(如果存在)。因此,while循環中的邏輯可能需要了解previous_siblings()和parent()節點以及它們包含的節點。

0
doc = <<-HTML 
<html> 
<body> 
    <code>1</code> 
    <code>@@@@</code> 
    <code>3</code> 
    <code>@@@@</code> 
    <code> 
    @@@@ 
    </code> 
</body> 
</html> 
HTML 

puts doc.scan(/(.*?<code>)(\s*@@@@)/m).map { |match| match.first.scan(/\n/).size }.inject([1]){ |sum, n| sum << sum.last + n }[1..-1] 
0

我要指出的是一些未知的原因Nokogiri::HTML不會返回任何給定的元素的行號,當你調用line方法就可以了,但Nokogiri::XML。令人困惑,很多?

因此,該解決方案是這樣的:

html = Nokogiri::XML(html) 
html.css("code") do |code| 
    if /^@@@@/.match(code) 
    parse_code(code) 
    end 
end 

def parse_code(code) 
    # do something and report back using: 
    # Assume for a moment document.path exists. 
    puts "Parsed code block on: #{code.line} of #{document.path}" 
end