2014-03-28 83 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)中有介紹,請仔細閱讀。 –