1

我正在尝试使用 Savon 与使用 SOAP 的旧式 Web 服务进行通信。关于 Savon 如何从响应信封中构造散列,我遇到了问题。

client = Savon.client("http://my-service-endpoint/?wsdl")

response = client.request :my_soap_operation do
  soap.body do |xml|
    xml.in("test")
  end
end

response.to_hash[:my_soap_operation_response][:out].each do |a|
   puts "Return element: #{a}"
   puts "Name #{a[:name]}"
   puts "Type #{a[:type]}"
   puts "Code #{a[:code]}"
end

结尾

如果 SOAP 响应包含超过 1 个“out”元素,例如:

<mySoapOperationResponse>
  <out>
   <code>C1947944</code>
   <name>Use</name>
   <type>type 1</type>
 </out>
 <out>
   <code>C1947946</code>
   <name>name 2</name>
   <type>type 2</type>
 </out>
 <out>
   <code>C1947947</code>
   <name>name 2</name>
   <type>type 3</type>
 </out>
</mySoapOperationResponse>

输出如预期:

Return element: {:code=>"C1947944", :name=>"Use", :type=>"type 1"}
Name Use
Type type 1
Code C1947944
Return element: {:code=>"C1947946", :name=>"name 2", :type=>"type 2"}
Name name 2
Type type 2
Code C1947946
Return element: {:code=>"C1947947", :name=>"name 2", :type=>"type 3"}
Name name 2
Type type 3
Code C1947947

但是,如果 SOAP 响应只包含一个“out”元素,例如:

<mySoapOperationResponse>
     <out>
        <code>C1947944</code>
        <name>name 1</name>
        <type>type 1</type>
     </out>
</mySoapOperationResponse>

我在控制台中看到了这个

Return element: [:code, "C1947944"]

...然后我收到错误消息

can't convert Symbol into Integer

看起来 :name 和 :type 元素似乎不存在于 SOAP 响应中,但是我可以通过响应 XML 消息看到它们。

我正在使用 Savon v1.2.0。

附录

我添加了以下代码以尝试进一步调试该问题:

 response = client.request :my_soap_operation do
  soap.body do |xml|
    xml.in("test")
  end
 end

pp response.to_hash

response.to_hash[:my_soap_operation_response][:out].each do |a|
   pp a
   puts "Return element: #{a}"
   puts "Name #{a[:name]}"
   puts "Type #{a[:type]}"
   puts "Code #{a[:code]}"

我可以看到响应哈希中的元素被打印得很漂亮。这是控制台的快照:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
    <mySoapOperationResponse>
        <out>
            <code>C1947944</code>
            <name>name 1</name>
            <type>type 1</type>
        </out>
    </mySoapOperationResponse>
 </soapenv:Body>
</soapenv:Envelope>

{:my_soap_operation_response=>
    {:out=>{:code=>"C1947944", :name=>"name 1", :type=>"type 1"},
        :@xmlns=>"http://namespace.removed.com/"}}

[:code, "C1947944"]
Return element: [:code, "C1947944"]

但是,似乎在 .each 循环内部(循环每个“out”元素),只能访问第一个元素?

4

1 回答 1

1

我认为问题在于,在第二种情况下,Savon 不会返回数组。您需要检查 [:out] 是数组还是单个值并采取相应措施。我所做的是将单个值包装到一个元素的数组中,以保持我的程序结构简单。

def wrapped_soap_call
  # prepare Savon::Client to your liking
  client = Savon::Client.new do
    # your stuff here
  end

  # call the SOAP WS
  result = client.request :wsdl, :function do
    # your stuff here
  end

  list = result.to_hash[:response][:out]
  # if there was only one item list is not an array!
  if list.is_a? Array
    return list
  else
    return Array.new << list
  end
end

这对我行得通。

于 2012-11-20T02:33:55.170 回答