如何在Ruby中解析XML-RPC格式的XML?

问题描述:

我需要在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}' 

这使得我的眼睛受伤了。

这是最接近的一个解决方案,我能找到的:

这工作,但它是哦,所以,非常难看。这不可能是正确的:

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}' 

这使得我的眼睛受伤了。

XMLRPC库明显带有多个解析器和默认是XMLTreeParser这就要求图书馆xmltreebuilder(我不知道和这显然不是标准库的一部分)。 但也许你可以尝试另一个解析器?使用XMLRPC::XMLParser.each_installed_parser {|p| puts p.class},您将获得所有(可实例化)解析器的列表。所以,你可能会得到别人的一个正常工作......

+0

谢谢,我试过了。唯一不引发异常的是'REXMLStreamParser',即使那个不能按预期工作(请参阅更新后的问题)。 –

检查 '引入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。 –

与@mfojtik我打算推荐Nokogiri,因为它是一款出色的XML解析器,但我通过Google搜索几乎找到了Rapuncel。它是一个基于Nokogiri的XML-RPC客户端,专门用于发送/接收XML-RPC并解析它。

不知道它是否被维护了,但它可能值得一试。如果没有,你可以使用Nokogiri作为基础,因为它看起来不太复杂。