测试子节点是否存在(没有得到NoM​​ethodError)

时间:2011-12-14 21:01:02

标签: ruby nokogiri

<root>
  <channel>
    <one>example</one>
    <two>example2</two>
  </channel>
  <channel>
    <one>example</one>
  </channel>
</root>

在第二个节点中,我没有<two>节点。如果我使用它:root.channel.two显然我得到错误“方法缺失”。如何检查以避免此错误?我将使用的条件语句是什么?

2 个答案:

答案 0 :(得分:7)

技术1:救援任何错误

require 'nokogiri'
d = Nokogiri.XML("<foo><bar /></foo>")
bad = d.root.bar            #=> undefined method `bar' for #<...> (NoMethodError)
d.slop!           
yay = d.root.bar            #=> #<... name="bar">
bad = d.root.xxx            #=> undefined method `xxx' for #<...> (NoMethodError)
yay = d.root.xxx rescue nil #=> nil

技术2:跳跃前看(又名不要使用斜坡)

%w[ bar xxx ].each do |node_name|
  if n = d.root.at_xpath(node_name)
    puts "Yay! #{n}"
  else
    puts "No node named #{node_name}"
  end
end
#=> Yay! <bar/>
#=> No node named xxx

使用slop时,(no-slop)代码some_node.at_xpath("foo")some_node.foo相同,但在没有具有该名称的子节点时返回nil。实际上,Slop的实现只是为元素名称调用xpath:如果它找到了很多元素,那么你就得到了Nodeset;如果它只找到一个元素,它会给你那个;如果它没有找到任何元素,则会引发NoMethodError。重要的部分看起来像这样:

def method_missing( name )
  list = xpath(name)
  if list.empty?
    super                 # NoMethodError unless someone else handles this
  elsif list.length == 1
    list.first            # Since we only found one element, return that
  else
    list                  # ...otherwise return the whole list
  end
end

以下是Nokogiri文件中关于Slop的内容(在脚注中):

  

不要使用它。
  不,真的,不要使用它。如果您使用它,请不要报告错误   你已被警告过了!

一般来说,XPath比slop遍历更强大,更快。例如,如果要迭代每个<two>节点,则可以执行以下操作:

d.xpath('/root/channel/two').each do |two|
  # This will only find nodes that exist
end

如果您最终描述了您真正需要做的事情,我们可以帮助您制作更好的代码。在我个人看来,Slop通常是一种不太有效的遍历文档的方式。

答案 1 :(得分:3)

这是一种简单的方法:

  xml = Nokogiri::XML(open("http://www.google.com/ig/api?weather=Auckland+New+Zealand"))

  @current_conditions = xml.xpath("//current_conditions")

  if @current_conditions.empty?
    @display_weather = 0
  else
    @display_weather = 1
  end