diff --git a/lib/oga.rb b/lib/oga.rb index 7b6b11e..b5f1592 100644 --- a/lib/oga.rb +++ b/lib/oga.rb @@ -1,5 +1,6 @@ require 'set' +require_relative 'oga/xml/child_mixin' require_relative 'oga/xml/lexer' require_relative 'oga/xml/parser' require_relative 'oga/xml/node' diff --git a/lib/oga/xml/child_mixin.rb b/lib/oga/xml/child_mixin.rb new file mode 100644 index 0000000..152f612 --- /dev/null +++ b/lib/oga/xml/child_mixin.rb @@ -0,0 +1,32 @@ +module Oga + module XML + ## + # Mixin that can be used to link child nodes together with their parent, + # previous and next following. + # + module ChildMixin + ## + # Links child nodes together with each other and sets the parent node of + # each child. + # + def link_child_nodes + amount = children.length + + children.each_with_index do |child, index| + prev_index = index - 1 + next_index = index + 1 + + if index > 0 + child.previous = children[prev_index] + end + + if next_index <= amount + child.next = children[next_index] + end + + child.parent = self + end + end + end # NodeHierarchy + end # XML +end # Oga diff --git a/lib/oga/xml/document.rb b/lib/oga/xml/document.rb index ca2e2ba..5dad83a 100644 --- a/lib/oga/xml/document.rb +++ b/lib/oga/xml/document.rb @@ -17,6 +17,8 @@ module Oga # @return [Oga::XML::XmlDeclaration] # class Document + include ChildMixin + attr_accessor :children, :doctype, :xml_declaration ## @@ -34,6 +36,15 @@ module Oga @children ||= [] end + ## + # @param [Array] nodes + # + def children=(nodes) + @children = nodes + + link_child_nodes + end + ## # Converts the document and its child nodes to XML. # diff --git a/lib/oga/xml/node.rb b/lib/oga/xml/node.rb index 0f2cea3..5e1c956 100644 --- a/lib/oga/xml/node.rb +++ b/lib/oga/xml/node.rb @@ -17,6 +17,8 @@ module Oga # @return [Oga::XML::Node] # class Node + include ChildMixin + attr_accessor :parent, :children, :next, :previous ## @@ -39,6 +41,15 @@ module Oga after_initialize if respond_to?(:after_initialize) end + ## + # @param [Array] nodes + # + def children=(nodes) + @children = nodes + + link_child_nodes + end + ## # Generates the inspect value for the current node. Sub classes can # overwrite the {#extra_inspect_data} method to customize the output diff --git a/lib/oga/xml/parser.y b/lib/oga/xml/parser.y index 4f132ca..e007edd 100644 --- a/lib/oga/xml/parser.y +++ b/lib/oga/xml/parser.y @@ -120,8 +120,6 @@ rule element.children = val[1].flatten - link_children(element) - element } ; @@ -287,7 +285,8 @@ Unexpected #{name} with value #{value.inspect} on line #{@line}: children = [children] end - document = Document.new + document = Document.new + child_nodes = [] children.each do |child| if child.is_a?(Doctype) @@ -297,38 +296,13 @@ Unexpected #{name} with value #{value.inspect} on line #{@line}: document.xml_declaration = child else - document.children << child + child_nodes << child end end - link_children(document) + document.children = child_nodes return document end - ## - # Links the child nodes together by setting attributes such as the - # previous, next and parent node. - # - # @param [Oga::XML::Node] node - # - def link_children(node) - amount = node.children.length - - node.children.each_with_index do |child, index| - prev_index = index - 1 - next_index = index + 1 - - if index > 0 - child.previous = node.children[prev_index] - end - - if next_index <= amount - child.next = node.children[next_index] - end - - child.parent = node - end - end - # vim: set ft=racc: