Savon数组/哈希混淆



当 Savon 解析 XML 时:

<MessageList>
<TradeMessage ID="4850644"/>
<TradeMessage ID="4850666"/>
<TradeMessage ID="4850667"/>
<TradeMessage ID="4850712"/>
</MessageList>

它返回一个哈希

{MessageList: TradeMessage: [{@id: '123'},...,{@id: '456'}]}

但是如果 XML 是这样的

<MessageList>
<TradeMessage ID="4850644"/>
</MessageList>

它会返回

{MessageList: TradeMessage: {@id: '123'}}

所以我无法循环浏览消息列表,因为它可以是哈希或数组。

我循环数组的代码是:

t[:message_list][:trade_message].each do |m|
TradeMessage.create(id: m[:@id])
end

在这种情况下我该怎么办?我应该将XML解析器从默认的Nokogiri更改为其他东西吗?

我注意到Hash.from_xml(string)返回一个类似于 Savon 的哈希,如果有多个标签,则返回一个数组,如果一个标签,则返回一个哈希。


我决定使用Nokogiri文档来解析Savon的响应response.doc

你可以使用 Ruby 的 splat 运算符。它将始终返回一个数组。请参阅下面的一个非常简单的示例:

require 'awesome_print'
def return_array(elements)
return *elements
end
ap return_array([:a, :b, :c])
ap return_array(:d)

如果这是 Savon 的默认行为,我建议查看您获得的结果类型并从那里解析:

if t[:message_list][:trade_message].is_a?(Array) # or perhaps `t[:message_list][:trade_message].respond_to?(:each)`
t[:message_list][:trade_message].each { |m| TradeMessage.create(id: m[:@id]) }
else
TradeMessage.create(id: t[:message_list][:trade_message][:@id])
end

或者,您可以将结果包装在一个数组中(如果它还没有一个(,并以类似的方式处理:

t[:message_list][:trade_message].is_a?(Array) ? t[:message_list][:trade_message] : [t[:message_list][:trade_message]]
t[:message_list][:trade_message].each { |m| TradeMessage.create(id: m[:@id]) }

不过,这是来自宝石的奇怪行为,可能值得查看他们的文档,看看是否有可以用来改变这种行为的东西。

最新更新