diff --git a/lib/oga.rb b/lib/oga.rb index 657670f..b9eb488 100644 --- a/lib/oga.rb +++ b/lib/oga.rb @@ -6,6 +6,9 @@ require_relative 'oga/xml/lexer' require_relative 'oga/xml/parser' require_relative 'oga/xml/node' require_relative 'oga/xml/element' +require_relative 'oga/xml/comment' +require_relative 'oga/xml/text' +require_relative 'oga/xml/document' require_relative 'oga/xml/builder' require_relative 'oga/html/parser' diff --git a/lib/oga/xml/builder.rb b/lib/oga/xml/builder.rb index f497196..45a024f 100644 --- a/lib/oga/xml/builder.rb +++ b/lib/oga/xml/builder.rb @@ -9,19 +9,68 @@ module Oga class Builder < ::AST::Processor attr_reader :ast - ## - # @param [Oga::AST::Node] ast - # - def initialize(ast) - @ast = ast + def on_document(node) + document = Document.new + document.children = process_all(node) + + document.children.each do |child| + child.parent = document + end + + return document + end + + def on_comment(node) + return Comment.new(:text => node.children[0]) end def on_element(node) + ns, name, attr, *children = *node + if attr + attr = process(attr) + end + + if children + children = process_all(children) + end + + element = Element.new( + :name => name, + :namespace => ns, + :attributes => attr, + :children => children + ) + + element.children.each_with_index do |child, index| + if index > 0 + child.previous = element.children[index - 1] + end + + if index + 1 <= element.children.length + child.next = element.children[index + 1] + end + + child.parent = element + end + + return element end def on_text(node) + return Text.new(:text => node.children[0]) + end + alias_method :on_cdata, :on_text + + def on_attributes(node) + pairs = process_all(node) + + return Hash[pairs] + end + + def on_attribute(node) + return *node end end # Builder end # XML diff --git a/lib/oga/xml/comment.rb b/lib/oga/xml/comment.rb new file mode 100644 index 0000000..eeb0eae --- /dev/null +++ b/lib/oga/xml/comment.rb @@ -0,0 +1,13 @@ +module Oga + module XML + ## + # + class Comment < Node + attr_accessor :text + + def to_xml + return "" + end + end # Comment + end # XML +end # Oga diff --git a/lib/oga/xml/document.rb b/lib/oga/xml/document.rb new file mode 100644 index 0000000..e587831 --- /dev/null +++ b/lib/oga/xml/document.rb @@ -0,0 +1,14 @@ +module Oga + module XML + ## + # Class description + # + class Document < Node + attr_accessor :dtd, :xml_version, :encoding + + def to_xml + return children.map(&:to_xml).join('') + end + end # Document + end # XML +end # Oga diff --git a/lib/oga/xml/element.rb b/lib/oga/xml/element.rb index bb55eb5..4e057b8 100644 --- a/lib/oga/xml/element.rb +++ b/lib/oga/xml/element.rb @@ -5,14 +5,30 @@ module Oga # attributes and child nodes. # class Element < Node - ## - # @param [String] name The name of the element - # @see Oga::XML::Node#initialize - # - def initialize(name, options = {}) - super(options) + attr_accessor :name, :namespace, :attributes - @name = name + def after_initialize + @attributes ||= {} + end + + def attribute(name) + return attributes[name] + end + + alias_method :attr, :attribute + + def to_xml + ns = namespace ? "#{namespace}:" : '' + body = children.map(&:to_xml).join('') + attrs = '' + + attributes.each do |key, value| + attrs << "#{key}=#{value.inspect}" + end + + attrs = " #{attrs}" unless attrs.empty? + + return "<#{ns}#{name}#{attrs}>#{body}" end end # Element end # XML diff --git a/lib/oga/xml/node.rb b/lib/oga/xml/node.rb index 8c087cf..3eca9ef 100644 --- a/lib/oga/xml/node.rb +++ b/lib/oga/xml/node.rb @@ -1,20 +1,20 @@ module Oga module XML ## - # @!attribute [r] parent + # @!attribute [rw] parent # @return [Oga::XML::Node] # - # @!attribute [r] children + # @!attribute [rw] children # @return [Array] # - # @!attribute [r] next + # @!attribute [rw] next # @return [Oga::XML::NOde] # - # @!attribute [r] previous + # @!attribute [rw] previous # @return [Oga::XML::Node] # class Node - attr_reader :parent, :children, :next, :previous + attr_accessor :parent, :children, :next, :previous ## # @param [Hash] options @@ -30,6 +30,10 @@ module Oga options.each do |key, value| instance_variable_set("@#{key}", value) if respond_to?(key) end + + @children ||= [] + + after_initialize if respond_to?(:after_initialize) end end # Element end # XML diff --git a/lib/oga/xml/text.rb b/lib/oga/xml/text.rb new file mode 100644 index 0000000..dc0d211 --- /dev/null +++ b/lib/oga/xml/text.rb @@ -0,0 +1,13 @@ +module Oga + module XML + ## + # + class Text < Node + attr_accessor :text + + def to_xml + return text.to_s + end + end # Text + end # XML +end # Oga