簡體   English   中英

如何使用Ruby解析和打印XML文件

[英]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可以searchat at等效於search('some selector').first Nokogiri將嘗試為您選擇選擇器是CSS還是XPath。 還有CSS和XPath特定的方法cssxpathsearch類似,而at_cssat_xpathat版本。 根據輸出結果,Nokogiri似乎僅將*css*xpath變體用作提示,而不是對選擇器類型的絕對描述。 我必須仔細檢查代碼才能確定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM