【问题标题】:Cannot access SOAP xml nested id= attribute using Savon 2无法使用 Savon 2 访问 SOAP xml 嵌套 id= 属性
【发布时间】:2015-07-02 12:43:32
【问题描述】:

在下面的soap响应中(来自SoapUI),在父SearchForReservationResponse标签下,我试图用Savon 2提取Reservation idRestaurant idLocation id的值。

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <soap:Body>
      <SearchForReservationResponse xmlns="http://schemas.livebookings.net/OneFormat/Aggregator/Internal/1/0/">
         <Reservation id="34639536" status="Confirmed">
            <DiningDateAndTime>2015-07-01T17:00:00</DiningDateAndTime>
            <Restaurant id="25200">
               <Name>Eat Food - UK Demo Website - Bookatable.com</Name>
               <Location id="35839">
                  <Name>Bar</Name>
               </Location>
            </Restaurant>
            <Size>2</Size>
            <Created>2015-07-01T13:22:17.41</Created>
            <SessionId>DINNER</SessionId>
            <FirstName>John</FirstName>
            <LastName>Smith</LastName>
            <ConfirmationNumber>JWRW5HR5</ConfirmationNumber>
            <AllowedToCancelOnline>true</AllowedToCancelOnline>
            <RestaurantPhoneNumber type="Main">+44 7951300529</RestaurantPhoneNumber>
         </Reservation>
      </SearchForReservationResponse>
   </soap:Body>
</soap:Envelope>

以下是我尝试访问Reservation id 的尝试。经过大量谷歌搜索后,我发现新的 Savon 2 语法使用了@attrib,但我不断收到错误,因为我认为我没有正确使用这种 Ruby 嵌套哈希语法 - 我发现它非常令人困惑,而且对 Ruby 来说还很陌生。如果您能在这里帮助我,将不胜感激!

require 'savon'

class SearchReservation
  attr_reader :reservation_id

  def client
    client = Savon.client(wsdl: "http://example-wsdl-url", follow_redirects: :follow_redirects)
  end

  def main_method(confirm_number, email)
    message = {'ConfirmationNumber' => "JWRW5HR5", 'EMail' => "jon@" }
    response = client.call(:search_for_reservation, message: message)
    data = response.body(:search_for_reservation_response => { @attrib => {:reservation => :id} })   
    if data
      @reservation_id = data[:id]
  end
end

end

search = SearchReservation.new
puts search.main_method("JWRW5HR5", "jon@")

注意电子邮件值 jon@ 不必是有效的电子邮件地址(仅用于测试目的) - 它在 SoapUI 中返回有效响应。

我在终端/控制台中的最后一个语法错误跟踪:

/~/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/savon-2.11.1/lib/savon/response.rb:36:in `body': wrong number of arguments (1 for 0) (ArgumentError)
    from search.rb:13:in `main_method'
    from search.rb:22:in `<main>'

【问题讨论】:

  • puts response.body 将引导您走向正确的方向。我打赌JSON.parse(response.body) 会给你一个现成的哈希值。
  • 感谢@mudasobwa,这是非常好的建议,但我如何将我想要提取的对象表示为实例变量,以便以后在 Rails 应用程序中使用。这就是我之前的做法:gist.github.com/daneasterman/90bb3d29cefba38e5e10
  • 澄清一下:我应该如何表示键的值(通常是字符串),例如::name=&gt;"Eat Food - UK Demo Website - Bookatable.com" - 我可以将其表示为我选择的简单变量,如 restarurant_name
  • 这完全取决于您:您甚至可以分配 @all_data_from_service = JSON.parse(response.body) 并将其用作哈希,或者基于每个变量分配所有内容,例如 @restrnt_name = parsed_response[:name]
  • JSON.parse 不起作用,因为它给出了这个错误:/Users/dan14/.rbenv/versions/2.1.4/lib/ruby/gems/2.1.0/gems/json-1.8.3/lib/json/common.rb:155:in initialize: no implicit conversion of Hash into String (TypeError)

标签: ruby xml soap savon


【解决方案1】:

我的最终解决方案是提取我需要的所有值。注意:即使dining_date_and_time 在放置response.body 时显示为xml,但当使用@dining_date_and_time = data[:dining_date_and_time] 提取它时,日期和时间值会被清晰地打印出来。这是移植到成熟的 Rails 应用程序后的关键。

尽管网上有关于属性的所有讨论,但只要确保您在“树”下足够远(即位置 id 位于位置标签下)然后指定键,就可以拉出 xml 标记中的 id:在这种情况下对于每个嵌套案例,api 将其显示为 :@id。

注意,这只会返回每次在控制台中调用的最后一个值。但是一旦集成到 Rails 中,所有值都应该在视图中提取。 (希望如此!)

require 'savon'

class SearchClass

  def client
  client = Savon.client(wsdl: "http://wsdl-example-url", follow_redirects: :follow_redirects)
  end

  def return_data(confirm_number, email)
    message = {'ConfirmationNumber' => confirm_number, 'EMail' => email  }
    response = client.call(:search_for_reservation, message: message)
    data = response.to_hash[:search_for_reservation_response][:reservation]
    @reservation_id = data[:@id]
    @dining_date_and_time = data[:dining_date_and_time]
    @size = data[:size]
    @session_id = data[:session_id]
    @first_name = data[:first_name]
    @last_name = data[:last_name]
    @confirm_number = data[:confirmation_number]
    @allowed_to_cancel_online = data[:allowed_to_cancel_online]
    @restaurant_phone_number = data[:restaurant_phone_number]

    data2 = response.to_hash[:search_for_reservation_response][:reservation][:restaurant]
    @restaurant_id = data2[:@id]
    @restaurant_name = data2[:name]

    data3 = response.to_hash[:search_for_reservation_response][:reservation][:restaurant][:location]
    @location_id = data3[:@id]
    @location_name = data3[:name]

  end  

end

search = SearchClass.new
puts search.return_data("JWRW5HR5", "jon@")

【讨论】:

    猜你喜欢
    • 2016-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多