[英]How to parse and print an XML file using Ruby
我正在嘗試使用Ruby解析XML文件。 它解析成功,但不打印我想要打印的內容:
require 'rubygems'
require 'nokogiri'
def parseXML(filename)
page = Nokogiri::XML(open(filename))
puts page.class
page.css('//ssn//p').each do |a|
puts a['qn']
page.css('//ssn//p//v').each do |e|
puts e['fans']
end
end
end
if __FILE__ == $0
parseXML('CS 141 FALL 2016/SessionData/L1611021411.xml')
end
XML文件的格式為:
<ssn >
<p strt="14:13:09" qn="Question 1" stp="14:14:20">
<v fans="C" id="#00A4DB7F" ans="C" fanst="33.59"/>
<v fans="A" id="#3910072E" ans="D" fanst="50.71"/>
<v fans="A" id="#3C44F58D" ans="A" fanst="20.71"/>
<v fans="B" id="#3C62633D" ans="B" fanst="10.78"/>
</p>
<p strt="14:20:17" qn="Question 2" stp="14:21:24">
<v fans="A" id="#00A4DB7F" ans="D" fanst="33.59"/>
<v fans="E" id="#3910072E" ans="C" fanst="50.71"/>
<v fans="E" id="#3C44F58D" ans="B" fanst="20.71"/>
<v fans="C" id="#3C62633D" ans="A" fanst="10.78"/>
</p>
<p strt="14:22:17" qn="Question 3" stp="14:23:24">
<v fans="A" id="#00A4DB7F" ans="A" fanst="33.59"/>
<v fans="B" id="#3910072E" ans="B" fanst="50.71"/>
<v fans="C" id="#3C44F58D" ans="C" fanst="20.71"/>
<v fans="D" id="#3C62633D" ans="D" fanst="10.78"/>
</p>
</ssn>
我要打印:
Question 1:
C
A
A
B
Question 2:
A
E
E
C
Question 3:
A
B
C
D
但相反,它打印的是:
Question 1:
C
A
A
B
A
E
E
C
A
B
C
D
Question 2:
C
A
A
B
A
E
E
C
A
B
C
D
Question 3:
C
A
A
B
A
E
E
C
A
B
C
D
問題是您的CSS選擇器不是CSS,也不是正確的XPath:
'//ssn//p'
'//ssn//p//v'
Nokogiri在使用它們之前對其進行了測試,並認為它們是XPath,因此將它們視為XPath。
為了獲得想要的輸出,我將使用CSS:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<ssn>
<p qn="Question 1">
<v ans="C"/>
<v ans="D"/>
<v ans="A"/>
<v ans="B"/>
</p>
<p qn="Question 2">
<v ans="D"/>
<v ans="C"/>
<v ans="B"/>
<v ans="A"/>
</p>
<p qn="Question 3">
<v ans="A"/>
<v ans="B"/>
<v ans="C"/>
<v ans="D"/>
</p>
</ssn>
EOT
doc.search('p').each { |p|
puts "#{ p['qn'] }:"
puts p.search('v').map { |v| v['ans'] }
puts
}
會產生:
Question 1:
C
D
A
B
Question 2:
D
C
B
A
Question 3:
A
B
C
D
您使用的XPath選擇器的問題是輔助//
。 在XPath中,ese //
表示從文檔的頂部開始並在各處搜索。 所以//ssn//p
意思是“從頂部開始,找到<ssn>
然后從頂部開始,找到<p>
。相反,您想要//ssn/p
,這意味着“從頂部開始,然后找到<ssn>
在其中找到<p>
”。
上面的選擇器可能被編寫為:
doc.search('//p').each { |p|
puts "#{ p['qn'] }:"
puts p.search('./v').map { |v| v['ans'] }
puts
}
這將輸出相同的東西。
我建議使用CSS,因為它通常會使選擇器更具可讀性,但是有時我會使用XPath,因為它功能更強大。
Nokogiri可以search
並at
; at
等效於search('some selector').first
。 Nokogiri將嘗試為您選擇選擇器是CSS還是XPath。 還有CSS和XPath特定的方法css
和xpath
與search
類似,而at_css
和at_xpath
是at
版本。 根據輸出結果,Nokogiri似乎僅將*css
或*xpath
變體用作提示,而不是對選擇器類型的絕對描述。 我必須仔細檢查代碼才能確定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.