2012-10-19 45 views
1

我需要在Ruby中解析一些XML-RPC格式的XML。我沒有訪問XML-RPC服務的權限,我只想將從此類服務返回的XML字符串轉換爲相應的Ruby對象(散列,數組,字符串等)。如何在Ruby中解析XML-RPC格式的XML?

我周圍玩內置XML-RPC的東西(用Ruby 1.9.3),但我不走得很遠:

require 'xmlrpc/parser' 
parser = XMLRPC::XMLParser::XMLParser.new 

導致此異常:

LoadError: cannot load such file -- xmltreebuilder 
from /Users/johannes/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require' 
from /Users/johannes/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require' 
from /Users/johannes/.rvm/rubies/ruby-1.9.3-p0/lib/ruby/1.9.1/xmlrpc/parser.rb:620:in `initialize' 
from (irb):2:in `new' 
from (irb):2 
from /Users/johannes/.rvm/rubies/ruby-1.9.3-p0/bin/irb:16:in `<main>' 

然後我試圖實例化不同的XMLParser子類,都無濟於事。

你有什麼關於如何讓這個工作的指針?是否有可能在不使用帶有內置庫的XMLRPC :: Client的情況下解析RPC XML?

謝謝!

更新:

這工作,但它是哦,所以,非常難看。這不可能是正確的:

require 'xmlrpc/client' 
require "rexml/document" 

xml = %{<answer> 
<value> 
<struct> 
    <member><name>test</name><value><string>hello</string></value></member> 
    <member><name>age</name><value><i4>12</i4></value></member> 
    <member> 
    <name>requirements</name> 
    <value> 
     <struct> 
     <member> 
      <name>confirmation</name> 
      <value> 
      <array> 
       <data> 
       <value><string>Bread</string></value> 
       <value><string>Butter</string></value> 
       </data> 
      </array> 
      </value> 
     </member> 
     <member> 
      <name>document</name> 
      <value> 
      <array> 
       <data> 
       <value><string>Tic</string></value> 
       <value><string>Tac</string></value> 
       <value><string>Toe</string></value> 
       </data> 
      </array> 
      </value> 
     </member> 
     </struct> 
    </value> 
    </member> 
    <member><name>width</name><value><i4>10</i4></value></member> 
    <member><name>height</name><value><i4>2</i4></value></member> 
</struct> 
</value> 
</answer>} 

parser = XMLRPC::XMLParser::REXMLStreamParser::StreamListener.new 
parser.parse(xml) 

puts "Value (accessor): '#{parser.value}'" 
puts "Values (accessor): '#{parser.values}'" 
puts "Value (instance_variable_get): '#{parser.instance_variable_get('@value')}'" 

必須有更好的方法!

這是輸出:

Value (accessor): '' 
Values (accessor): '' 
Value (instance_variable_get): '{"test"=>"hello", "age"=>12, "requirements"=>{"confirmation"=>["Bread", "Butter"], "document"=>["Tic", "Tac", "Toe"]}, "width"=>10, "height"=>2}' 

這使得我的眼睛受傷了。

回答

0

這是最接近的一個解決方案,我能找到的:

這工作,但它是哦,所以,非常難看。這不可能是正確的:

require 'xmlrpc/client' 
require "rexml/document" 

xml = %{<answer> 
<value> 
<struct> 
    <member><name>test</name><value><string>hello</string></value></member> 
    <member><name>age</name><value><i4>12</i4></value></member> 
    <member> 
    <name>requirements</name> 
    <value> 
     <struct> 
     <member> 
      <name>confirmation</name> 
      <value> 
      <array> 
       <data> 
       <value><string>Bread</string></value> 
       <value><string>Butter</string></value> 
       </data> 
      </array> 
      </value> 
     </member> 
     <member> 
      <name>document</name> 
      <value> 
      <array> 
       <data> 
       <value><string>Tic</string></value> 
       <value><string>Tac</string></value> 
       <value><string>Toe</string></value> 
       </data> 
      </array> 
      </value> 
     </member> 
     </struct> 
    </value> 
    </member> 
    <member><name>width</name><value><i4>10</i4></value></member> 
    <member><name>height</name><value><i4>2</i4></value></member> 
</struct> 
</value> 
</answer>} 

parser = XMLRPC::XMLParser::REXMLStreamParser::StreamListener.new 
parser.parse(xml) 

puts "Value (accessor): '#{parser.value}'" 
puts "Values (accessor): '#{parser.values}'" 
puts "Value (instance_variable_get): '#{parser.instance_variable_get('@value')}'" 

必須有更好的方法!

這是輸出:

Value (accessor): '' 
Values (accessor): '' 
Value (instance_variable_get): '{"test"=>"hello", "age"=>12, "requirements"=>{"confirmation"=>["Bread", "Butter"], "document"=>["Tic", "Tac", "Toe"]}, "width"=>10, "height"=>2}' 

這使得我的眼睛受傷了。

0

XMLRPC庫明顯帶有多個解析器和默認是XMLTreeParser這就要求圖書館xmltreebuilder(我不知道和這顯然不是標準庫的一部分)。 但也許你可以嘗試另一個解析器?使用XMLRPC::XMLParser.each_installed_parser {|p| puts p.class},您將獲得所有(可實例化)解析器的列表。所以,你可能會得到別人的一個正常工作......

+0

謝謝,我試過了。唯一不引發異常的是'REXMLStreamParser',即使那個不能按預期工作(請參閱更新後的問題)。 –

1

檢查 '引入nokogiri' 寶石:

irb> require 'nokogiri' 
irb> doc = Nokogiri::XML('<root><a>test</a></root>') 
irb> puts (doc/'root/a').first.text # => 'test' 

irb> puts doc.xpath('doc/root/a').first.text 

+0

謝謝,我已經廣泛地使用Nokogiri,並且我用Nokogiri編寫了自己的XML-RPC解析器。不過,我不想重新發明輪子。這就是爲什麼我想了解如何使用現有的解決方案來解析XML-RPC。 –

0

與@mfojtik我打算推薦Nokogiri,因爲它是一款出色的XML解析器,但我通過Google搜索幾乎找到了Rapuncel。它是一個基於Nokogiri的XML-RPC客戶端,專門用於發送/接收XML-RPC並解析它。

不知道它是否被維護了,但它可能值得一試。如果沒有,你可以使用Nokogiri作爲基礎,因爲它看起來不太複雜。