Module: Canon::Comparison::XmlComparatorHelpers::ChildComparison

Defined in:
lib/canon/comparison/xml_comparator/child_comparison.rb

Overview

Child comparison service for XML nodes

Handles comparison of child nodes using both semantic matching (ElementMatcher) and simple positional comparison. Delegates back to the comparator for individual node comparisons.

This module encapsulates the complex child comparison logic, making the main XmlComparator cleaner and more maintainable.

Class Method Summary collapse

Class Method Details

.compare(node1, node2, comparator, opts, child_opts, diff_children, differences) ⇒ Integer

Compare children of two nodes using semantic matching

Uses ElementMatcher to pair children semantically (by identity attributes or position), then compares matched pairs and detects position changes.

Parameters:

  • node1 (Object)

    First parent node

  • node2 (Object)

    Second parent node

  • comparator (XmlComparator)

    The comparator instance for delegation

  • opts (Hash)

    Comparison options

  • child_opts (Hash)

    Options for child comparison

  • diff_children (Boolean)

    Whether to diff children

  • differences (Array)

    Array to collect differences

Returns:

  • (Integer)

    Comparison result code



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/canon/comparison/xml_comparator/child_comparison.rb', line 29

def compare(node1, node2, comparator, opts, child_opts,
diff_children, differences)
  # Apply side-specific pretty-print heuristic when either flag is set:
  # pretty_printed_expected → drop \n-starting whitespace nodes from node1
  # pretty_printed_received → drop \n-starting whitespace nodes from node2
  # The ephemeral _pretty_print_side_active flag is consumed by node_excluded?
  # and must NOT be forwarded into recursive compare_nodes calls.
  require_relative "../xml_node_comparison"
  opts1 = XmlNodeComparison.opts_for_side(opts, :expected)
  opts2 = XmlNodeComparison.opts_for_side(opts, :received)

  children1 = comparator.send(:filter_children, node1.children, opts1)
  children2 = comparator.send(:filter_children, node2.children, opts2)

  # Quick check: if both have no children, they're equivalent
  return Comparison::EQUIVALENT if children1.empty? && children2.empty?

  # Check if we can use ElementMatcher (requires Canon::Xml::DataModel nodes)
  if can_use_element_matcher?(children1, children2)
    use_element_matcher_comparison(children1, children2, node1, comparator,
                                   opts, child_opts, diff_children, differences)
  else
    use_positional_comparison(children1, children2, node1, comparator,
                              opts, child_opts, diff_children, differences)
  end
end