Class: Canon::Diff::NodeSerializer
- Inherits:
-
Object
- Object
- Canon::Diff::NodeSerializer
- Defined in:
- lib/canon/diff/node_serializer.rb
Overview
Serializes nodes from different parsing libraries into canonical strings This abstraction allows Canon to work with any parsing library (Nokogiri, Moxml, etc.) without being tied to a specific implementation.
This is library-agnostic because it detects node type and uses the appropriate serialization method.
Class Method Summary collapse
-
.element_name(node) ⇒ String
Get element name from a node Handles both Nokogiri and Canon nodes.
-
.extract_attributes(node) ⇒ Hash
Extract attributes from a node as a normalized hash Handles both Nokogiri and Canon nodes.
-
.serialize(node) ⇒ String
Serialize a node to a string for display Handles both Nokogiri and Canon nodes.
-
.serialize_attributes(attributes) ⇒ String
Serialize attributes to string format Returns attributes in “ name="value"” format.
-
.serialize_element_node(element) ⇒ String
Serialize an ElementNode to HTML/XML string.
-
.text_content(node) ⇒ String
Get text content from a node Handles both Nokogiri and Canon nodes.
Class Method Details
.element_name(node) ⇒ String
Get element name from a node Handles both Nokogiri and Canon nodes
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/canon/diff/node_serializer.rb', line 138 def self.element_name(node) return "" if node.nil? # Handle Canon::Xml::Nodes::ElementNode if node.is_a?(Canon::Xml::Nodes::ElementNode) return node.name end # Handle Nokogiri elements if node.respond_to?(:name) return node.name.to_s end "" end |
.extract_attributes(node) ⇒ Hash
Extract attributes from a node as a normalized hash Handles both Nokogiri and Canon nodes
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/canon/diff/node_serializer.rb', line 96 def self.extract_attributes(node) return {} if node.nil? # Handle Canon::Xml::Nodes::ElementNode if node.is_a?(Canon::Xml::Nodes::ElementNode) attrs = {} node.attribute_nodes.each do |attr| attrs[attr.name] = attr.value end return attrs end # Handle Nokogiri elements if node.respond_to?(:attributes) && node.attributes.is_a?(Hash) attrs = {} node.attributes.each do |name, attr| # Nokogiri attributes have different structure value = if attr.respond_to?(:value) attr.value elsif attr.is_a?(String) attr else attr.to_s end attrs[name] = value end return attrs end # Handle TreeNode attributes (already a hash) if node.is_a?(Hash) return node end {} end |
.serialize(node) ⇒ String
Serialize a node to a string for display Handles both Nokogiri and Canon nodes
24 25 26 27 28 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 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/canon/diff/node_serializer.rb', line 24 def self.serialize(node) return "" if node.nil? # Handle Canon::Xml::Nodes::TextNode if node.is_a?(Canon::Xml::Nodes::TextNode) # Use original text (with entity references) if available, # otherwise fall back to value (decoded text) return node.original || node.value end # Handle Canon::Xml::Nodes::CommentNode if node.is_a?(Canon::Xml::Nodes::CommentNode) return "<!--#{node.value}-->" end # Handle Canon::Xml::Nodes::ElementNode if node.is_a?(Canon::Xml::Nodes::ElementNode) return serialize_element_node(node) end # Handle Canon::Xml::Nodes::ProcessingInstructionNode if node.is_a?(Canon::Xml::Nodes::ProcessingInstructionNode) return "<?#{node.target} #{node.data}?>" end # Handle Canon::Xml::Nodes::RootNode - serialize children if node.is_a?(Canon::Xml::Nodes::RootNode) return node.children.map { |child| serialize(child) }.join end # Handle Nokogiri nodes if node.respond_to?(:to_html) return node.to_html end if node.respond_to?(:to_xml) return node.to_xml end # Fallback to string node.to_s end |
.serialize_attributes(attributes) ⇒ String
Serialize attributes to string format Returns attributes in “ name="value"” format
184 185 186 187 188 189 190 |
# File 'lib/canon/diff/node_serializer.rb', line 184 def self.serialize_attributes(attributes) return "" if attributes.nil? || attributes.empty? attributes.sort.map do |name, value| " #{name}=\"#{value}\"" end.join end |
.serialize_element_node(element) ⇒ String
Serialize an ElementNode to HTML/XML string
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/canon/diff/node_serializer.rb', line 71 def self.serialize_element_node(element) # Build opening tag with attributes tag = "<#{element.name}" # Add attributes element.sorted_attribute_nodes.each do |attr| tag += " #{attr.name}=\"#{attr.value}\"" end # Check if element has children if element.children.empty? # Self-closing tag for empty elements "#{tag}/>" else # Full element with children content = element.children.map { |child| serialize(child) }.join "#{tag}>#{content}</#{element.name}>" end end |
.text_content(node) ⇒ String
Get text content from a node Handles both Nokogiri and Canon nodes
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/canon/diff/node_serializer.rb', line 159 def self.text_content(node) return "" if node.nil? # Handle Canon::Xml::Nodes::TextNode if node.is_a?(Canon::Xml::Nodes::TextNode) return node.value.to_s end # Handle Nokogiri text nodes if node.respond_to?(:text) return node.text.to_s end if node.respond_to?(:content) return node.content.to_s end "" end |