【问题标题】:How to parse SOAP response from ruby client?如何解析来自 ruby​​ 客户端的 SOAP 响应?
【发布时间】:2010-01-27 03:31:58
【问题描述】:

我正在学习 Ruby,我编写了以下代码来了解如何使用 SOAP 服务:

require 'soap/wsdlDriver'
wsdl="http://www.abundanttech.com/webservices/deadoralive/deadoralive.wsdl"
service=SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
weather=service.getTodaysBirthdays('1/26/2010')

我得到的回复是:

#<SOAP::Mapping::Object:0x80ac3714 
{http://www.abundanttech.com/webservices/deadoralive} getTodaysBirthdaysResult=#<SOAP::Mapping::Object:0x80ac34a8 
{http://www.w3.org/2001/XMLSchema}schema=#<SOAP::Mapping::Object:0x80ac3214 
{http://www.w3.org/2001/XMLSchema}element=#<SOAP::Mapping::Object:0x80ac2f6c 
{http://www.w3.org/2001/XMLSchema}complexType=#<SOAP::Mapping::Object:0x80ac2cc4 
{http://www.w3.org/2001/XMLSchema}choice=#<SOAP::Mapping::Object:0x80ac2a1c 
{http://www.w3.org/2001/XMLSchema}element=#<SOAP::Mapping::Object:0x80ac2774 
{http://www.w3.org/2001/XMLSchema}complexType=#<SOAP::Mapping::Object:0x80ac24cc 
{http://www.w3.org/2001/XMLSchema}sequence=#<SOAP::Mapping::Object:0x80ac2224 
{http://www.w3.org/2001/XMLSchema}element=[#<SOAP::Mapping::Object:0x80ac1f7c>, 
#<SOAP::Mapping::Object:0x80ac13ec>, 
#<SOAP::Mapping::Object:0x80ac0a28>, 
#<SOAP::Mapping::Object:0x80ac0078>, 
#<SOAP::Mapping::Object:0x80abf6c8>, 
#<SOAP::Mapping::Object:0x80abed18>]
>>>>>>> {urn:schemas-microsoft-com:xml-diffgram-v1}diffgram=#<SOAP::Mapping::Object:0x80abe6c4 
{}NewDataSet=#<SOAP::Mapping::Object:0x80ac1220 
{}Table=[#<SOAP::Mapping::Object:0x80ac75e4 
{}FullName="Cully,  Zara" 
{}BirthDate="01/26/1892" 
{}DeathDate="02/28/1979" 
{}Age="(87)" 
{}KnownFor="The Jeffersons" 
{}DeadOrAlive="Dead">, 
#<SOAP::Mapping::Object:0x80b778f4 
{}FullName="Feiffer, Jules" 
{}BirthDate="01/26/1929" 
{}DeathDate=#<SOAP::Mapping::Object:0x80c7eaf4> 
{}Age="81" 
{}KnownFor="Cartoonists" 
{}DeadOrAlive="Alive">]>>>>

我很难弄清楚如何在一个漂亮的表格中解析和显示返回的信息,或者甚至只是如何遍历记录并访问每个元素(即 FullName、Age 等) .我浏览了整个“getTodaysBirthdaysResult.methods - Object.new.methods”,并继续努力尝试找出如何访问元素,但后来我到达了数组,我迷路了。

我们将不胜感激。

【问题讨论】:

    标签: ruby soap wsdl request response


    【解决方案1】:

    如果您仍然要解析 XML,您不妨跳过 SOAP4r 并使用 Handsoap。免责声明:我是 Handsoap 的作者之一。

    一个示例实现:

    # wsdl: http://www.abundanttech.com/webservices/deadoralive/deadoralive.wsdl
    DEADORALIVE_SERVICE_ENDPOINT = {
      :uri => 'http://www.abundanttech.com/WebServices/DeadOrAlive/DeadOrAlive.asmx',
      :version => 1
    }
    
    class DeadoraliveService < Handsoap::Service
      endpoint DEADORALIVE_SERVICE_ENDPOINT
      def on_create_document(doc)
        # register namespaces for the request
        doc.alias 'tns', 'http://www.abundanttech.com/webservices/deadoralive'
      end
    
      def on_response_document(doc)
        # register namespaces for the response
        doc.add_namespace 'ns', 'http://www.abundanttech.com/webservices/deadoralive'
      end
    
      # public methods
    
      def get_todays_birthdays
        soap_action = 'http://www.abundanttech.com/webservices/deadoralive/getTodaysBirthdays'
        response = invoke('tns:getTodaysBirthdays', soap_action)
        (response/"//NewDataSet/Table").map do |table|
          {
            :full_name => (table/"FullName").to_s,
            :birth_date => Date.strptime((table/"BirthDate").to_s, "%m/%d/%Y"),
            :death_date => Date.strptime((table/"DeathDate").to_s, "%m/%d/%Y"),
            :age => (table/"Age").to_s.gsub(/^\(([\d]+)\)$/, '\1').to_i,
            :known_for => (table/"KnownFor").to_s,
            :alive? => (table/"DeadOrAlive").to_s == "Alive"
          }
        end
      end
    end
    

    用法:

    DeadoraliveService.get_todays_birthdays
    

    【讨论】:

    • 我昨天简要了解了Handsoap,它只是一个soap客户端还是我可以像Soap4r StandaloneServer一样创建一个Soap服务器
    • 在另一个说明中,您能否指出我在 Soap4R 和 HandSoap 之间进行比较的内容。我非常有兴趣了解 HandSoap 和 Soap4R 的优缺点。显然,两者都不能只比另一个有优势或劣势。
    • 只是一个客户。项目页面上的库有一些理由,但简短的故事:Handsoap 需要更多的努力,但是如果/当事情失败时,它可以更容易地调试代码(这样做是因为 SOAP 是协议的噩梦)。它还使代码更精简/更快。
    • @troelskn 你能建议使用 Handsoap 解决以下问题吗? stackoverflow.com/questions/29344780/…
    【解决方案2】:

    SOAP4R 总是返回一个 SOAP::Mapping::Object ,这有时有点难以使用,除非您只是获取可以使用这样的哈希表示法访问的哈希值

    weather['fullName']
    

    但是,当您有散列数组时,它不起作用。一种解决方法是以 xml 格式而不是 SOAP::Mapping::Object 获取结果。为此,我会将您的代码修改为

     require 'soap/wsdlDriver'
     wsdl="http://www.abundanttech.com/webservices/deadoralive/deadoralive.wsdl"
     service=SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver
     service.return_response_as_xml = true
     weather=service.getTodaysBirthdays('1/26/2010')
    

    现在上面将为您提供一个 xml 响应,您可以使用 nokogiri 或 REXML 对其进行解析。这是使用 REXML 的示例

      require 'rexml/document'
      rexml = REXML::Document.new(weather)
      birthdays = nil
      rexml.each_recursive {|element| birthdays = element if element.name == 'getTodaysBirthdaysResult'}
      birthdays.each_recursive{|element| puts "#{element.name} = #{element.text}" if element.text}
    

    这将打印出所有包含任何文本的元素。

    因此,一旦您创建了一个 xml 文档,您几乎可以根据您选择的库所具有的方法来做任何事情,即。 REXML 或 Nokogiri

    【讨论】:

    【解决方案3】:

    好吧,这是我的建议。

    问题是,您必须抓住结果的正确部分,即您可以实际迭代的部分。不幸的是,世界上所有的检查都对你没有帮助,因为它是一大堆不可读的文本。

    我要做的是:

    File.open('myresult.yaml', 'w') {|f| f.write(result.to_yaml) }
    

    这将是一种更易于阅读的格式。您可能正在寻找的是这样的:

        --- !ruby/object:SOAP::Mapping::Object 
    
    
        __xmlattr: {}
    
          __xmlele: 
    
      - - &id024 !ruby/object:XSD::QName 
          name: ListAddressBooksResult <-- Hash name, so it's resul["ListAddressBooksResult"]
          namespace: http://apiconnector.com
          source: 
        - !ruby/object:SOAP::Mapping::Object 
          __xmlattr: {}
    
          __xmlele: 
          - - &id023 !ruby/object:XSD::QName 
              name: APIAddressBook <-- this bastard is enumerable :) YAY! so it's result["ListAddressBooksResult"]["APIAddressBook"].each
              namespace: http://apiconnector.com
              source: 
            - - !ruby/object:SOAP::Mapping::Object
    

    以上是 DotMailer 的 API 的结果,我花了最后一个小时试图弄清楚如何枚举结果。以上是我用来弄清楚到底发生了什么的技术。我认为它比使用 REXML 等方式更好,我可以这样做:

    result['ListAddressBooksResult']['APIAddressBook'].each {|book| puts book["Name"]}
    

    嗯,我希望这可以帮助其他正在寻找的人。

    /杰森

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-17
      • 1970-01-01
      • 2012-07-14
      • 1970-01-01
      相关资源
      最近更新 更多