测试子节点是否存在(不会出现NoMethodError) [英] Test if a child node exists (without getting NoMethodError)

查看:20
本文介绍了测试子节点是否存在(不会出现NoMethodError)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

推荐答案

技巧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:三思而后行(也称为不要使用Slop)

%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

(no-slop)代码some_node.at_xpath("foo")与使用slop时的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文件对斯洛普的评价(在脚注中):

不要使用此选项。
不,真的,别用这个。如果您使用它,请不要报告错误。
您已收到警告!

总的来说,XPath比SLOP遍历功能更强大、速度更快。例如,如果您想遍历每个<two>节点,您可以这样做:

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

如果您描述了最终真正需要做的事情,我们可以帮助您编写更好的代码。在我个人看来,SLOP通常是一种效率较低的遍历文档的方式。

这篇关于测试子节点是否存在(不会出现NoMethodError)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆