2010-01-27 50 views
3

我學習Ruby和我寫了下面的代碼,找出如何消費SOAP服務:如何解析來自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」並一直在努力嘗試並研究如何訪問元素,但是後來我進入陣列並且迷路了。

任何可以提供的幫助將不勝感激。

回答

5

如果你打算解析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 
+0

昨天我簡要介紹了Handsoap,這僅僅是一個肥皂客戶端,還是我可以創建一個Soap服務器像Soap4r StandaloneServer – nas 2010-01-27 10:11:34

+0

在另一張紙上,你可以指點一下Soap4R和HandSoap之間的比較。我會非常感興趣的看待HandSoap和Soap4R的優點和缺點。顯然,任何一方都不能只有優點或缺點。 – nas 2010-01-27 10:14:56

+0

這只是一個客戶。項目頁面上的庫有一些理由,但是小故事:Handsoap事先做了更多的努力,但是如果/當事情失敗時它更容易調試代碼(這是因爲SOAP是協議的惡夢)。它也使得更精簡/更快的代碼。 – troelskn 2010-01-27 10:41:57

3

SOAP4R總是返回一個SOAP ::映射::對象,它有時是有點困難,除非有你是剛開始,你可以使用哈希符號,像這樣

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

+0

嗨Nas,你能幫我解答下面的問題嗎? http://stackoverflow.com/questions/29351329/connect-sybaseanywhere-for-ruby-1-8-7 – Learner 2015-03-31 08:28:59

0

好,這裏是我的建議。

問題是,你必須阻止結果的正確部分,這是你實際上可以迭代的東西。不幸的是,世界上所有的檢查都無法幫助你,因爲它是一大堆難以理解的文字。

我做的是這樣的:

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"]} 

嗯,我希望這可以幫助別人誰正在尋找。

/jason