从Savon XML响应中获取价值?

时间:2014-03-28 16:12:23

标签: ruby-on-rails ruby xml savon

我是Ruby on Rails的新手,并且正在与Savon连接到SOAP服务。我收到了以下回复:

<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <GetInformationsForCoordinatesResponse xmlns="http://tempuri.org/">
      <GetInformationsForCoordinatesResult>ABC14522</GetInformationsForCoordinatesResult>
    </GetInformationsForCoordinatesResponse>
  </s:Body>
</s:Envelope>

我需要获得GetInformationsForCoordinatesResult的值,即ABC14522

从Savon文档中,我知道Savon使用nori和Nokogiri。在我的脚本中,我添加了require 'nokogiri'

result = response.xpath("//GetInformationsForCoordinatesResult").first.inner_text

然而,当我运行代码时,我收到错误:

NoMethodError: undefined method `inner_text' for nil:NilClass

有人可以指出这里可能出现的问题,或者是否有更好的方法从响应中提取我需要的值?

1 个答案:

答案 0 :(得分:1)

&#34;问题&#34;是你的文档有名称空间。命名空间在需要帮助区分类似命名的节点时非常棒,但它们使得搜索节点更加困难。

以下是获取所需数据的几种方法:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <GetInformationsForCoordinatesResponse xmlns="http://tempuri.org/">
      <GetInformationsForCoordinatesResult>ABC14522</GetInformationsForCoordinatesResult>
    </GetInformationsForCoordinatesResponse>
  </s:Body>
</s:Envelope>
EOT

XML现在被解析为doc中的XML::Document对象。我使用at方法是为了方便,因为它允许使用CSS或XPath,就像使用search(...).firstat_xpathxpath(...).first一样。

doc.at('//xmlns:GetInformationsForCoordinatesResult', 'xmlns' => "http://tempuri.org/").text # => "ABC14522"

通过告诉Nokogiri我想要哪个命名空间,它检索了目标节点的文本。

或者,我可以使用collect_namespaces收集XML中的所有命名空间,然后将其作为哈希传递:

namespaces = doc.collect_namespaces
doc.at('//xmlns:GetInformationsForCoordinatesResult', namespaces).text # => "ABC14522"

或者,如果我知道没有特别的理由去打扰命名空间,我可以告诉Nokogiri使用remove_namespaces!方法忽略它们:

doc.remove_namespaces!
doc.at('//GetInformationsForCoordinatesResult').text # => "ABC14522"

阅读Nokogiri的教程&#34; Searching an HTML / XML Document&#34;了解更多信息。