Как разобрать SOAP-ответ от клиента ruby? - PullRequest
3 голосов
/ 27 января 2010

Я изучаю 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» и продолжал работать, пытаясь выяснить, как получить доступ к элементам, но затем я попал в массив, и я потерялся.

Буду признателен за любую помощь, которая может быть предложена.

Ответы [ 3 ]

5 голосов
/ 27 января 2010

Если вы все равно собираетесь анализировать 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
3 голосов
/ 27 января 2010

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 или Нокогири

0 голосов
/ 13 мая 2010

Ну, вот мое предложение.

Проблема в том, что вам нужно поймать правильную часть результата, которую вы действительно можете перебрать. К сожалению, все проверки в мире не помогут вам, потому что это огромный кусок нечитаемого текста.

Что я делаю, это:

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

Выше приведен результат API DotMailer, который я провел последний час, пытаясь выяснить, как перечислять результаты. Выше - техника, которую я использовал, чтобы выяснить, что, черт возьми, происходит. Я думаю, что это лучше, чем использовать REXML и т.д., я мог бы сделать что-то вроде этого:

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

Ну, я надеюсь, что это поможет любому, кто смотрит.

/ * Ясон 1016 *

...