我是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
有人可以指出这里可能出现的问题,或者是否有更好的方法从响应中提取我需要的值?
答案 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(...).first
或at_xpath
或xpath(...).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;了解更多信息。