2014-03-28 94 views
0

我是Ruby on Rails的新手,并且正在使用Savon连接到SOAP服务。我得到如下回应:从Savon XML响应中获取价值?

<?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

从莎翁的文档,我知道,萨翁用紫菜和引入nokogiri。在我的脚本中我包含了require 'nokogiri'

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

然而,当我跑我得到了错误代码:

NoMethodError: undefined method `inner_text' for nil:NilClass 

有人能指出这可能是错在这里或者表现出更好的方法来提取我从响应所需的值?

+0

你可以使用一个引入nokogiri或者,这是响应对象上的萨翁to_hash。你可以简单地遍历它(虽然我不记得它开始的级别)。响应[:Envelope] [:Body] [:Get ... Response] [:Get ... Result] –

+0

您应该使用Savon的Response对象方法。你不需要用Nokogiri推出自己的产品 - Savon的Response对象会自动委托给它。另外,不需要它。 –

+0

@MarkThomas - 好的,谢谢 - 我才意识到我可以叫response.doc的响应,然后我就能够使用从回答下面的代码让我的价值 –

回答

1

“问题”是您的文档的命名空间。当需要名称空间来帮助区分类似的命名节点时,命名空间非常棒,但是它们使得搜索节点变得更加困难。

这里有几个方法在你想要的数据获取:

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现在被解析成一个XML::Document对象doc。我使用的方便at方法,因为它允许使用任何CSS或XPath的,并且就像使用search(...).first,或at_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的教程“Searching an HTML/XML Document”的详细信息。

+0

由于铁皮 - 我用doc.remove_namespaces和doc.at和这工作。是我对响应多个结果会是什么来检索他们的最好办法 - 我的XML可以包含多个 ABC14522

+0

如果您需要捕获多个结果,用'search'或它的别名之一。如果您只想要第一个匹配结果,请使用'at'或其别名。这在[Nokogiri :: XML :: Node文档](http://nokogiri.org/Nokogiri/XML/Node.html)中有介绍,请仔细阅读。 –