2014-07-15 27 views
0

我試圖解析一個xml看起來像這樣:引入nokogiri:趿拉訪問節點名爲name

<lesson> 
    <name>toto</name> 
    <version>42</version> 
</lesson> 

使用Nokogiri::Slop

我可以通過lesson.version輕鬆訪問課程,但無法訪問lesson.name,因爲名稱在本例中指的是節點(課程)的名稱。

有什麼方法可以訪問孩子嗎?

回答

1

您可以使用search並給予節點的XPath或CSS選擇器:

doc.lesson.search('name').first 
+0

號。問題是關於'Slop'。 –

+0

它仍然與普通的選擇器混合在一起。 – hakcho

+0

是的。但我正在關注* Slop裝飾器實現了method_missing,因此可以使用方法而不是CSS或XPath。* :-)沒問題,你是對的。 –

1

做使用元編程有點破解

require 'nokogiri' 

doc = Nokogiri::Slop <<-HTML 
<lesson> 
    <name>toto</name> 
    <version>42</version> 
</lesson> 
HTML 


name_val = doc.lesson.instance_eval do 
    self.class.send :undef_method, :name 
    self.name 
end.text 
p name_val # => toto 
p doc.lesson.version.text # => '42' 

Nokogiri::XML::Node#name被定義爲獲得Nokogiri::XML::Node名稱的方法。只需一段時間,從#instance_eval範圍內的類Nokogiri::XML::Node中刪除該方法。

+0

我喜歡它,並且在這種情況下會更好,但是,在這種特定情況下,我更喜歡單行:) – Antzi

2

作爲一個變體,你可以試試這個:

doc.lesson.elements.select{|el| el.name == "name"} 

爲什麼?正因爲如此基準:

require 'nokogiri' 
require 'benchmark' 

str = '<lesson> 
    <name>toto</name> 
    <version>42</version> 
</lesson>' 

doc = Nokogiri::Slop(str) 

n = 50000 
Benchmark.bm do |x| 
    x.report("select") { n.times do; doc.lesson.elements.select{|el| el.name == "name"}; end } 
    x.report("search") { n.times do; doc.lesson.search('name'); end } 
end 

這給我們的結果:

#=>   user  system  total  real 
#=> select 1.466000 0.047000 1.513000 ( 1.528153) 
#=> search 2.637000 0.125000 2.762000 ( 2.777278) 
+0

也可以加我..讓我看看meta編程的*缺點* ..: - ) –

+0

缺點是'el.name'不起作用,強制轉換''method_missing':未定義的方法'name'爲#';) –

+0

什麼?我的代碼拋出錯誤? :-(我沒有... –