2010-01-27 13 views
3

J'apprends Ruby et j'ai écrit le code suivant pour savoir comment utiliser les services SOAP:Comment analyser la réponse SOAP du client Ruby?

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

La réponse que je nous obtenons est:

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

J'ai beaucoup de la difficulté à comprendre comment analyser et afficher les informations renvoyées dans une bonne table, ou même comment faire une boucle dans les enregistrements et avoir accès à chaque élément (par exemple FullName, Age, etc.). Je suis allé à travers l'ensemble "getTodaysBirthdaysRethods - Object.new.methods" et a continué à travailler pour essayer de trouver comment accéder aux éléments, mais ensuite j'arrive au tableau et je me suis perdu.

Toute aide qui peut être offerte serait appréciée.

Répondre

5

Si vous voulez quand même analyser XML, vous pouvez aussi ignorer SOAP4r et utiliser Handsoap. Disclaimer: Je suis l'un des auteurs de Handsoap.

Un exemple d'implémentation:

# 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 

Utilisation:

DeadoraliveService.get_todays_birthdays 
+0

J'ai regardé brièvement Handsoap hier, est-ce juste un client de savon ou puis-je créer un serveur de savon juste Comme Soap4r StandaloneServer – nas

+0

Sur une autre note pouvez-vous me montrer quelque chose qui a une comparaison entre Soap4R et HandSoap. Je serais très intéressé à regarder les avantages et les inconvénients de HandSoap et Soap4R les uns sur les autres. Évidemment, ni l'un ni l'autre ne peut avoir que des avantages ou des inconvénients par rapport à un autre. – nas

+0

C'est juste un client. Il y a une certaine justification pour la bibliothèque sur la page du projet, mais une petite histoire: Handsoap prend plus d'effort à l'avance, mais facilite le débogage du code si/quand les choses échouent (ce que cela fait parce que SOAP est un cauchemar de protocole). Il fait également pour le code plus léger/plus rapide. – troelskn

3

soap4r retourne toujours SOAP :: Mapping :: Object qui est parfois un peu difficile de travailler avec, sauf si vous êtes juste les valeurs de hachage que vous pouvez accéder en utilisant la notation de hachage comme si

weather['fullName'] 

Cependant, cela ne fonctionne pas lorsque vous avez un tableau de hachages. Un travail autour est d'obtenir le résultat au format XML au lieu de SOAP :: Mapping :: Object. Pour ce faire, je vais modifier votre code comme

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

Maintenant, le serait au-dessus de vous donner une réponse xml que vous pouvez analyser en utilisant nokogiri ou REXML. Voici l'exemple utilisant 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} 

Ceci affichera tous les éléments contenant du texte. Donc, une fois que vous avez créé un document XML, vous pouvez pratiquement tout faire en fonction des méthodes que la bibliothèque que vous choisissez a. REXML ou Nokogiri

+0

Salut Nas, Pouvez-vous m'aider à la question suivante? http://stackoverflow.com/questions/29351329/connect-sybaseanywhere-for-ruby-1-8-7 – Learner

0

Eh bien, voici ma suggestion. Le problème est que vous devez vous accrocher à la partie droite du résultat, qui est quelque chose que vous pouvez effectivement faire passer par l'itérateur. Malheureusement, toutes les inspections dans le monde ne vous aideront pas parce que c'est un énorme tas de texte illisible.

Ce que je fais est la suivante:

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

Ce sera un format lisible beaucoup plus humain. Ce que vous cherchez probablement quelque chose comme ceci:

--- !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 

Ce qui précède est le résultat de l'API dotMailer, que je passé la dernière heure à essayer de comprendre comment énumérer sur les résultats. Ce qui précède est la technique que j'ai utilisée pour comprendre ce qui se passe.Je pense qu'il bat en utilisant REXML etc cette façon, je pouvais faire quelque chose comme ceci:

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

Eh bien, j'espère que cela aide quelqu'un d'autre qui est à la recherche.

/jason