Анализ SOAP-ответа Savon с помощью multiRef - PullRequest
2 голосов
/ 16 февраля 2011

Я пытаюсь получить доступ к SOAP-сервису, используя Ruby gem Savon. Я могу подключиться к услуге, сделать запрос и получить ответ, но не могу разобрать ответ.

Ответ содержит несколько ссылок href на элементы multiRef. Когда я пытаюсь декодировать его, используя

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 ]

1 голос
/ 11 апреля 2011

Кажется, на данный момент лучшим подходом было просто выполнить мой собственный анализ с использованием 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
0 голосов
/ 24 февраля 2011

Вам придется разрешить ссылки вручную:

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 хеш-значений их соответствующими ссылочными значениями оставлена ​​читателю в качестве упражнения;)

...