1

我需要在 Ruby 中解析一些 XML-RPC 格式的 XML。我无权访问 XML-RPC 服务,我只想将从此类服务返回的 XML 字符串转换为相应的 Ruby 对象(散列、数组、字符串等)。

我玩过内置 XMLRPC 的东西(在 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}'

这让我的眼睛很痛。

4

5 回答 5

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

等等

于 2012-10-24T14:53:56.097 回答
1

这个问题可能已经过时了,但它仍然是谷歌搜索“ruby parse xml rpc”时的热门话题。

使用 ruby​​ XMLRPC 字符串可以更容易地解析XMLRPC::Marshal

require 'xmlrpc/marshal'

def parse_xml_rpc(xml_string)
  parser = XMLRPC::Marshal.new
  parser.load_call(xml_string)
end

上面的函数返回一个元组,其中首先包含函数的名称,然后是传递的参数数组。

str = "<?xml version=\"1.0\" ?><methodCall><methodName>function_name</methodName><params><param><value><string>arg1</string></value></param><param><value><boolean>1</boolean></value></param><param><value><double>27.5</double></value></param></params></methodCall>\n"

parse_xml_rpc(str)
=> ["function_name", ["arg1", true, 27.5]]
于 2019-08-07T13:10:14.243 回答
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}'

这让我的眼睛很痛。

于 2012-10-29T09:11:02.400 回答
0

与@mfojtik 一样,我打算推荐Nokogiri,因为它是一个出色的XML 解析器,但我通过谷歌搜索发现了Rapuncel。它是一个基于 Nokogiri 的 XML-RPC 客户端,专门用于发送/接收 XML-RPC 并对其进行解析。

不确定它是否已被维护,但可能值得一试。如果不是,您可以随时使用 Nokogiri 作为基础编写自己的代码,因为它看起来不太复杂。

于 2012-10-25T00:39:57.380 回答
0

xmlrpc库显然带有多个解析器,并且默认XMLTreeParser需要库xmltreebuilder(我不知道,它显然不是标准库的一部分)。但也许你可以尝试另一个解析器?使用XMLRPC::XMLParser.each_installed_parser {|p| puts p.class}您可以获得所有(可实例化的)解析器的列表。所以你可能会让其他人之一正常工作......

于 2012-10-22T14:30:02.280 回答