使用multiRef解析Savon SOAP响应

时间:2011-02-16 19:39:26

标签: ruby soap savon

我试图使用Ruby gem Savon访问SOAP服务。我可以连接到服务并发出请求并收到响应,但我无法解析响应。

响应包含对multiRef元素的多个href引用。当我尝试使用

解码它时
response.to_hash[:get_user_risk_profile_response][:get_user_risk_profile_return][:href]

我得#id0。我如何遵循id0参考?

SOAP响应如下。谢谢!

<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>
    <getUserStatusResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
      <getUserStatusReturn href="#id0"/>
    </getUserStatusResponse>
    <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns1:UserRiskProfileBean" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://xrisk.api.example.com">
      <parameters xsi:type="ns2:ArrayOf_tns3_ParamBean" xsi:nil="true" xmlns:ns2="http://api.example.com"/>
      <siteID xsi:type="soapenc:string">UNKNOWN</siteID>
      <userID xsi:type="soapenc:string">sam.wiggins</userID>
      <userRiskScore href="#id1"/>
      <userRiskScoreDT xsi:type="xsd:dateTime">2011-02-16T18:15:50.012Z</userRiskScoreDT>
    </multiRef>
    <multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">640</multiRef>
  </soapenv:Body>
</soapenv:Envelope>

2 个答案:

答案 0 :(得分:1)

目前看来,最好的方法是使用XPath进行自己的解析。这是原始的,可能不是非常防弹,但会做好工作直到更好的事情出现。

class SavonResponseXMLParser

  def initialize(response_xml)
    @doc = REXML::Document.new(response_xml)
  end

  def get_property(property)
    property_value = nil
    elements = REXML::XPath.match(@doc, "//#{property}")
    if (elements.length == 1)
      element = elements[0]
      href = element.attributes['href']
      if (href)
        href =~ /^#id(\d+)/
        multiref_elements = REXML::XPath.match(@doc,"//multiRef[@id='id#{$1}']")
        if (multiref_elements.length == 1)
          multiref_element = multiref_elements[0]
          property_value = multiref_element.text 
        end
      else
        property_value = element.text
      end
    end
    return property_value
  end
end

答案 1 :(得分:0)

您必须手动解决参考:

id = response.to_hash[:get_user_risk_profile_response][:get_user_risk_profile_return][:href]
references = response.to_hash[:multi_ref]
result = references.select {|ref| ref[:id] == id.sub('#', '') }

我建议将上面的内容放在辅助方法/模块中:

module MultiRef
  def resolve_ref(id)
    references = to_hash[:multi_ref]
    references.select {|ref| ref[:id] == id.sub('#', '') }
  end
end
Savon::Response.send(:include, MultiRef)

然后只需:

response.resolve_ref("#id1")

以适当的引用值递归替换href哈希值作为练习留给读者;)