Module: EquivalentXml

Defined in:
lib/equivalent-xml.rb

Constant Summary collapse

ELEMENT_NODE =
1
ATTRIBUTE_NODE =
2
TEXT_NODE =
3
CDATA_SECTION_NODE =
4
ENTITY_REFERENCE_NODE =
5
ENTITY_NODE =
6
PROCESSING_INSTRUCTION_NODE =
7
COMMENT_NODE =
8
DOCUMENT_NODE =
9
DOCUMENT_TYPE_NODE =
10
DOCUMENT_FRAGMENT_NODE =
11
NOTATION_NODE =
12
DEFAULT_OPTS =
{ :element_order => false, :normalize_whitespace => true }

Class Method Summary collapse

Class Method Details

.compare_attributes(node_1, node_2, opts) ⇒ Object



54
55
56
# File 'lib/equivalent-xml.rb', line 54

def compare_attributes(node_1, node_2, opts)
  (node_1.name == node_2.name) && (node_1.value == node_2.value)
end

.compare_cdata(node_1, node_2, opts) ⇒ Object



66
67
68
# File 'lib/equivalent-xml.rb', line 66

def compare_cdata(node_1, node_2, opts)
  node_1.text == node_2.text
end

.compare_children(node_1, node_2, opts) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/equivalent-xml.rb', line 70

def compare_children(node_1, node_2, opts)
  ignore_proc = lambda do |child|
    child.is_a?(Nokogiri::XML::Comment) ||
    child.is_a?(Nokogiri::XML::ProcessingInstruction) ||
    (child.class == Nokogiri::XML::Text && child.text.strip.empty?)
  end

  nodeset_1 = node_1.children.reject { |child| ignore_proc.call(child) }
  nodeset_2 = node_2.children.reject { |child| ignore_proc.call(child) }
  result = self.compare_nodesets(nodeset_1,nodeset_2,opts)
  
  if node_1.respond_to?(:attribute_nodes)
    attributes_1 = node_1.attribute_nodes
    attributes_2 = node_2.attribute_nodes
    result = result && self.compare_nodesets(attributes_1,attributes_2,opts)
  end
  result
end

.compare_documents(node_1, node_2, opts) ⇒ Object



46
47
48
# File 'lib/equivalent-xml.rb', line 46

def compare_documents(node_1, node_2, opts)
  self.equivalent?(node_1.root,node_2.root,opts)
end

.compare_elements(node_1, node_2, opts) ⇒ Object



50
51
52
# File 'lib/equivalent-xml.rb', line 50

def compare_elements(node_1, node_2, opts)
  (node_1.name == node_2.name) && self.compare_children(node_1,node_2,opts)
end

.compare_nodes(node_1, node_2, opts) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/equivalent-xml.rb', line 25

def compare_nodes(node_1, node_2, opts)
  if (node_1.class != node_2.class) or self.same_namespace?(node_1,node_2) == false
    false
  else
    case node_1.node_type
    when DOCUMENT_NODE
      self.compare_documents(node_1,node_2,opts)
    when ELEMENT_NODE
      self.compare_elements(node_1,node_2,opts)
    when ATTRIBUTE_NODE
      self.compare_attributes(node_1,node_2,opts)
    when CDATA_SECTION_NODE
      self.compare_cdata(node_1,node_2,opts)
    when TEXT_NODE
      self.compare_text(node_1,node_2,opts)
    else
      self.compare_children(node_1,node_2,opts)
    end
  end
end

.compare_nodesets(nodeset_1, nodeset_2, opts) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/equivalent-xml.rb', line 89

def compare_nodesets(nodeset_1, nodeset_2, opts)
  local_set_1 = nodeset_1.dup
  local_set_2 = nodeset_2.dup
  
  if local_set_1.length != local_set_2.length
    return false
  end

  local_set_1.each do |search_node|
    found_node = local_set_2.find { |test_node| self.equivalent?(search_node,test_node,opts) }
    if found_node.nil?
      return false
    else
      if search_node.is_a?(Nokogiri::XML::Element) and opts[:element_order]
        if search_node.parent.elements.index(search_node) != found_node.parent.elements.index(found_node)
          return false
        end
      end
      local_set_2.delete(found_node)
    end
  end
  return local_set_2.length == 0
end

.compare_text(node_1, node_2, opts) ⇒ Object



58
59
60
61
62
63
64
# File 'lib/equivalent-xml.rb', line 58

def compare_text(node_1, node_2, opts)
  if opts[:normalize_whitespace]
    node_1.text.strip.gsub(/\s+/,' ') == node_2.text.strip.gsub(/\s+/,' ')
  else
    node_1.text == node_2.text
  end
end

.equivalent?(node_1, node_2, opts = {}) ⇒ Boolean

Returns:

  • (Boolean)


20
21
22
23
# File 'lib/equivalent-xml.rb', line 20

def equivalent?(node_1, node_2, opts = {})
  opts = DEFAULT_OPTS.merge(opts)
  self.compare_nodes(node_1, node_2, opts)
end

.same_namespace?(node_1, node_2) ⇒ Boolean

Returns:

  • (Boolean)


113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/equivalent-xml.rb', line 113

def same_namespace?(node_1, node_2)
  unless node_1.respond_to?(:namespace) and node_2.respond_to?(:namespace)
    return true
  end
  
  if node_1.namespace.nil? and node_2.namespace.nil?
    return true
  end

  href1 = node_1.namespace.nil? ? '' : node_1.namespace.href
  href2 = node_2.namespace.nil? ? '' : node_2.namespace.href
  return href1 == href2
end