Class: Oga::XML::Generator
- Inherits:
-
Object
- Object
- Oga::XML::Generator
- Defined in:
- lib/oga/xml/generator.rb
Overview
Instance Method Summary collapse
-
#after_element(element, output) ⇒ Object
-
#html_void_element?(element) ⇒ Boolean
-
#initialize(root) ⇒ Generator
constructor
A new instance of Generator.
-
#on_attribute(attr, output) ⇒ Object
-
#on_cdata(node, output) ⇒ Object
-
#on_comment(node, output) ⇒ Object
-
#on_doctype(node, output) ⇒ Object
-
#on_document(doc, output) ⇒ Object
-
#on_element(element, output) ⇒ Object
-
#on_processing_instruction(node, output) ⇒ Object
-
#on_text(node, output) ⇒ Object
-
#on_xml_declaration(node, output) ⇒ Object
-
#self_closing?(element) ⇒ TrueClass|FalseClass
-
#to_xml ⇒ String
Returns the XML for the current root node.
Constructor Details
Instance Method Details
#after_element(element, output) ⇒ Object
149 150 151 |
# File 'lib/oga/xml/generator.rb', line 149 def after_element(element, output) output << "</#{element.}>" unless self_closing?(element) end |
#html_void_element?(element) ⇒ Boolean
220 221 222 |
# File 'lib/oga/xml/generator.rb', line 220 def html_void_element?(element) @html_mode && HTML_VOID_ELEMENTS.allow?(element.name) end |
#on_attribute(attr, output) ⇒ Object
155 156 157 158 159 160 |
# File 'lib/oga/xml/generator.rb', line 155 def on_attribute(attr, output) name = attr. enc_value = attr.value ? Entities.encode_attribute(attr.value) : nil output << %Q(#{name}="#{enc_value}") end |
#on_cdata(node, output) ⇒ Object
111 112 113 |
# File 'lib/oga/xml/generator.rb', line 111 def on_cdata(node, output) output << "<![CDATA[#{node.text}]]>" end |
#on_comment(node, output) ⇒ Object
117 118 119 |
# File 'lib/oga/xml/generator.rb', line 117 def on_comment(node, output) output << "<!--#{node.text}-->" end |
#on_doctype(node, output) ⇒ Object
164 165 166 167 168 169 170 171 172 |
# File 'lib/oga/xml/generator.rb', line 164 def on_doctype(node, output) output << "<!DOCTYPE #{node.name}" output << " #{node.type}" if node.type output << %Q{ "#{node.public_id}"} if node.public_id output << %Q{ "#{node.system_id}"} if node.system_id output << " [#{node.inline_rules}]" if node.inline_rules output << '>' end |
#on_document(doc, output) ⇒ Object
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/oga/xml/generator.rb', line 176 def on_document(doc, output) if doc.xml_declaration on_xml_declaration(doc.xml_declaration, output) output << "\n" end if doc.doctype on_doctype(doc.doctype, output) output << "\n" end first_child = doc.children[0] # Prevent excessive newlines in case the next node is a newline text # node. if first_child.is_a?(Text) && first_child.text.start_with?("\r\n", "\n") output.chomp! end end |
#on_element(element, output) ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/oga/xml/generator.rb', line 129 def on_element(element, output) name = element. attrs = '' element.attributes.each do |attr| attrs << ' ' on_attribute(attr, attrs) end if self_closing?(element) closing_tag = html_void_element?(element) ? '>' : ' />' output << "<#{name}#{attrs}#{closing_tag}" else output << "<#{name}#{attrs}>" end end |
#on_processing_instruction(node, output) ⇒ Object
123 124 125 |
# File 'lib/oga/xml/generator.rb', line 123 def on_processing_instruction(node, output) output << "<?#{node.name}#{node.text}?>" end |
#on_text(node, output) ⇒ Object
101 102 103 104 105 106 107 |
# File 'lib/oga/xml/generator.rb', line 101 def on_text(node, output) if @html_mode && (parent = node.parent) && parent.literal_html_name? output << node.text else output << Entities.encode(node.text) end end |
#on_xml_declaration(node, output) ⇒ Object
198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/oga/xml/generator.rb', line 198 def on_xml_declaration(node, output) output << '<?xml' [:version, :encoding, :standalone].each do |getter| value = node.send(getter) output << %Q{ #{getter}="#{value}"} if value end output << ' ?>' end |
#self_closing?(element) ⇒ TrueClass|FalseClass
212 213 214 215 216 217 218 |
# File 'lib/oga/xml/generator.rb', line 212 def self_closing?(element) if @html_mode && !HTML_VOID_ELEMENTS.allow?(element.name) false else element.children.empty? end end |
#to_xml ⇒ String
Returns the XML for the current root node.
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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/oga/xml/generator.rb', line 30 def to_xml current = @start output = '' while current children = false # Determine what callback to use for the current node. The order of # this statement is based on how likely it is for an arm to match. case current when Oga::XML::Element callback = :on_element children = true when Oga::XML::Text callback = :on_text when Oga::XML::Cdata callback = :on_cdata when Oga::XML::Comment callback = :on_comment when Oga::XML::Attribute callback = :on_attribute when Oga::XML::XmlDeclaration # This must come before ProcessingInstruction since XmlDeclaration # extends ProcessingInstruction. callback = :on_xml_declaration when Oga::XML::ProcessingInstruction callback = :on_processing_instruction when Oga::XML::Doctype callback = :on_doctype when Oga::XML::Document callback = :on_document children = true else raise TypeError, "Can't serialize #{current.class} to XML" end send(callback, current, output) if child_node = children && current.children[0] current = child_node elsif current == @start # When we have reached the root node we should not process # any of its siblings. If we did we'd include XML in the # output from elements no part of the root node. after_element(current, output) if current.is_a?(Element) break else # Make sure to always close the current element before # moving to any siblings. after_element(current, output) if current.is_a?(Element) until next_node = current.is_a?(Node) && current.next if current.is_a?(Node) && current != @start current = current.parent end after_element(current, output) if current.is_a?(Element) break if current == @start end current = next_node end end output end |