Skip to content

Instantly share code, notes, and snippets.

@elisehuard
Created June 24, 2010 14:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save elisehuard/451523 to your computer and use it in GitHub Desktop.
Save elisehuard/451523 to your computer and use it in GitHub Desktop.
require 'nokogiri'
module Nokogiri
module XML
class Node
BLANK = /^[ \n]*$/
# Comparing with other node
# - same name
# - same attributes
# - same namespaces
# - order doesn't matter
# - recursively through all children
# This will allow to compare two documents.
def =~(other)
match_nodes(other) && other.match_nodes(self)
end
def match_nodes(other)
self.root.traverse do |elem|
xpath_without_index = elem.path.sub(/\[[0-9]+\]/,'')
other_nodes = other.xpath(xpath_without_index)
return false if other_nodes.empty?
# just compare highest level
same_element = elem.element? && elem.match_element(other_nodes)
same_text = elem.text? && elem.match_text(other_nodes)
return false unless same_element || same_text
end
true
end
def match_element(other_nodes)
other_nodes.any? do |node|
namespace == node.namespace and
name == node.name and
match_attributes(node)
end
end
# if both are blank, the number of spaces doesn't matter
def match_text(other_nodes)
other_nodes.first.text == text || ((other_nodes.first.text =~ BLANK && text =~ BLANK) == 0)
end
private
# the compared node has same attributes as self
def match_attributes(other)
attributes.inject(true) do |memo,attr|
memo && other.attributes.include?(attr[0]) &&
other.attributes[attr[0]].name == attr[1].name &&
other.attributes[attr[0]].value == attr[1].value
end
end
end
end
end
@nickyp
Copy link

nickyp commented Jun 24, 2010

Approved but also improved: http://gist.github.com/451544 ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment