3 Stimmen

Wie parse ich die SOAP-Antwort vom Ruby-Client?

Ich lerne Ruby und habe den folgenden Code geschrieben, um herauszufinden, wie man SOAP-Dienste konsumiert:

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

Die Antwort, die ich zurückbekomme, ist:

#, 
#, 
#, 
#, 
#, 
#]
>>>>>>> {urn:schemas-microsoft-com:xml-diffgram-v1}diffgram=#, 
# 
{}Age="81" 
{}KnownFor="Cartoonists" 
{}DeadOrAlive="Alive">]>>>>

Ich habe große Schwierigkeiten herauszufinden, wie ich die zurückgegebenen Informationen in einer schönen Tabelle analysieren und anzeigen kann, oder einfach wie ich durch die Datensätze iterieren und auf jedes Element (z.B. Vollständiger Name, Alter, usw.) zugreifen kann. Ich habe mir die gesamten "getTodaysBirthdaysResult.methods - Object.new.methods" angesehen und bin weitergegangen, um herauszufinden, wie ich auf die Elemente zugreifen kann, aber dann bin ich zum Array gekommen und habe mich verirrt.

Jede Hilfe, die angeboten werden kann, wäre geschätzt.

5voto

troelskn Punkte 110542

Wenn Sie das XML ohnehin parsen werden, können Sie gleich SOAP4r überspringen und sich für Handsoap entscheiden. Haftungsausschluss: Ich bin einer der Autoren von Handsoap.

Ein Beispiel für die Implementierung:

# 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)
    # Registrieren von Namespaces für die Anfrage
    doc.alias 'tns', 'http://www.abundanttech.com/webservices/deadoralive'
  end

  def on_response_document(doc)
    # Registrieren von Namespaces für die Antwort
    doc.add_namespace 'ns', 'http://www.abundanttech.com/webservices/deadoralive'
  end

  # Öffentliche Methoden

  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

Verwendung:

DeadoraliveService.get_todays_birthdays

3voto

nas Punkte 3676

SOAP4R gibt immer ein SOAP::Mapping::Object zurück, was manchmal etwas schwierig zu handhaben ist, es sei denn, man bekommt nur die Hash-Werte, auf die man mit einer Hash-Notation zugreifen kann, wie folgt

weather['fullName']

Es funktioniert jedoch nicht, wenn Sie ein Array von Hashes haben. Ein Workaround besteht darin, das Ergebnis im XML-Format anstelle von SOAP::Mapping::Object zu erhalten. Um das zu erreichen, werde ich Ihren Code wie folgt ändern

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

Jetzt würden Sie eine XML-Antwort erhalten, die Sie mit Nokogiri oder REXML parsen können. Hier ist ein Beispiel mit 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}

Dies druckt alle Elemente aus, die irgendeinen Text haben.

Also, sobald Sie ein XML-Dokument erstellt haben, können Sie im Grunde genommen alles mit den Methoden tun, die die von Ihnen gewählte Bibliothek hat, d.h. REXML oder Nokogiri

0voto

J. Martin Punkte 1665

Nun, hier ist mein Vorschlag.

Das Problem ist, dass du den richtigen Teil des Ergebnisses ergreifen musst, einen, über den du tatsächlich iterieren kannst. Leider wird dir all das Inspektionieren der Welt nicht helfen, weil es sich um einen riesigen Textbrocken handelt, den man nicht lesen kann.

Was ich mache, ist folgendes:

Datei öffnen ('myresult.yaml', 'w') {|f| f.write(result.to_yaml) }

Dies wird ein viel menschenlesbareres Format sein. Was du wahrscheinlich suchst, ist etwas wie das hier:

    --- !ruby/object:SOAP::Mapping::Object 

    __xmlattr: {}

      __xmlele: 

  - - & id024! Ruby / Objekt: XSD :: QName  
      Name: ListAddressBooksResult <-- Hash-Name, also result["ListAddressBooksResult"]
      namespace: http://apiconnector.com
      source: 
    -! Ruby / Objekt: SOAP :: Mapping :: Object 
      __xmlattr: {}

      __xmlele: 
      - - & id023! Ruby / Objekt: XSD :: QName  
          Name: APIAddressBook <-- dieser Schuft ist durchzählig :) YAY! also result["ListAddressBooksResult"]["APIAddressBook"].each
          namespace: http://apiconnector.com
          source: 
        - -! Ruby / Objekt: SOAP :: Mapping :: Object

Das oben ist ein Ergebnis aus der API von DotMailer, über die ich die letzte Stunde damit verbracht habe, zu versuchen herauszufinden, wie man über die Ergebnisse durchzählen kann. Die obige Technik ist die, die ich verwendet habe, um herauszufinden, was zum Teufel hier passiert. Ich denke, das ist besser als REXML etc. auf diese Weise konnte ich etwas wie das hier machen:

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

Nun, ich hoffe, das hilft jedem weiter, der danach sucht.

/ jason

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X