Skip to content

Instantly share code, notes, and snippets.

@nickyp
Forked from elisehuard/gist:451523
Created June 24, 2010 14:49
Show Gist options
  • Save nickyp/451544 to your computer and use it in GitHub Desktop.
Save nickyp/451544 to your computer and use it in GitHub Desktop.
require 'nokogiri'
# \
# \
# \\
# \\
# >\/7
# _.-(6' \
# (=___._/` \
# ) \ |
# / / |
# / > /
# j < _\
# _.-' : ``.
# \ r=._\ `.
# <`\\_ \ .`-.
# \ r-7 `-. ._ ' . `\
# \`, `-.`7 7) )
# \/ \| \' / `-._
# || .'
# cjr \\ (
# 10mar02 >\ >
# ,.-' >.'
# <.'_.''
# <'
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment