Technique 1: Rescue any mistake
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
Technique 2: Look before the jump (aka Do not Use 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
When using slop, the code (no-slop) some_node.at_xpath("foo")
is identical to some_node.foo
, except that it returns nil
when a child node with this name does not exist. Indeed, the Slop implementation simply calls xpath
for the element name: if it finds many elements, you get this Nodeset; if he finds only one element, he gives you that; if it does not find elements, it raises the value of NoMethodError
. Important bits look like this:
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
Here's what the Nokogiri docs say about Slop (in footnotes):
Do not use this.
No, really, do not use this. If you use it, do not report errors.
You have been warned!
In general, XPath is much more efficient and faster than a workaround. For example, if you want to iterate over all <two>
node, you can do:
d.xpath('/root/channel/two').each do |two|
If you describe what you really need to do at the end, we can help you improve the code. In my personal opinion, Slop is usually a less efficient way to go through a document.
Phrogz
source share