Moved Document#each_node into a separate module.
This allows it to be re-used by XML::Node.
This commit is contained in:
parent
8f562c24dd
commit
98984de540
|
@ -20,6 +20,7 @@ end
|
||||||
#:nocov:
|
#:nocov:
|
||||||
|
|
||||||
require_relative 'oga/xml/querying'
|
require_relative 'oga/xml/querying'
|
||||||
|
require_relative 'oga/xml/traversal'
|
||||||
require_relative 'oga/xml/node'
|
require_relative 'oga/xml/node'
|
||||||
require_relative 'oga/xml/document'
|
require_relative 'oga/xml/document'
|
||||||
require_relative 'oga/xml/character_node'
|
require_relative 'oga/xml/character_node'
|
||||||
|
|
|
@ -14,6 +14,7 @@ module Oga
|
||||||
#
|
#
|
||||||
class Document
|
class Document
|
||||||
include Querying
|
include Querying
|
||||||
|
include Traversal
|
||||||
|
|
||||||
attr_accessor :doctype, :xml_declaration
|
attr_accessor :doctype, :xml_declaration
|
||||||
|
|
||||||
|
@ -51,46 +52,6 @@ module Oga
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
|
||||||
# Traverses through the document and yields every node to the supplied
|
|
||||||
# block.
|
|
||||||
#
|
|
||||||
# The block's body can also determine whether or not to traverse child
|
|
||||||
# nodes. Preventing a node's children from being traversed can be done by
|
|
||||||
# using `throw :skip_children`
|
|
||||||
#
|
|
||||||
# This method uses a combination of breadth-first and depth-first
|
|
||||||
# traversal to traverse the entire XML tree in document order. See
|
|
||||||
# http://en.wikipedia.org/wiki/Breadth-first_search for more information.
|
|
||||||
#
|
|
||||||
# @example
|
|
||||||
# document.each_node do |node|
|
|
||||||
# p node.class
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# @example Skipping the children of a certain node
|
|
||||||
# document.each_node do |node|
|
|
||||||
# if node.is_a?(Oga::XML::Element) and node.name == 'book'
|
|
||||||
# throw :skip_children
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# @yieldparam [Oga::XML::Node] The current node.
|
|
||||||
#
|
|
||||||
def each_node
|
|
||||||
visit = children.to_a.dup # copy it since we're modifying the array
|
|
||||||
|
|
||||||
until visit.empty?
|
|
||||||
current = visit.shift
|
|
||||||
|
|
||||||
catch :skip_children do
|
|
||||||
yield current
|
|
||||||
|
|
||||||
visit = current.children.to_a + visit
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Converts the document and its child nodes to XML.
|
# Converts the document and its child nodes to XML.
|
||||||
#
|
#
|
||||||
|
|
|
@ -9,6 +9,8 @@ module Oga
|
||||||
# @return [Oga::XML::NodeSet]
|
# @return [Oga::XML::NodeSet]
|
||||||
#
|
#
|
||||||
class Node
|
class Node
|
||||||
|
include Traversal
|
||||||
|
|
||||||
attr_accessor :node_set
|
attr_accessor :node_set
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
module Oga
|
||||||
|
module XML
|
||||||
|
##
|
||||||
|
# Module that provides methods to traverse DOM trees.
|
||||||
|
#
|
||||||
|
module Traversal
|
||||||
|
##
|
||||||
|
# Traverses through the node and yields every child node to the supplied
|
||||||
|
# block.
|
||||||
|
#
|
||||||
|
# The block's body can also determine whether or not to traverse child
|
||||||
|
# nodes. Preventing a node's children from being traversed can be done by
|
||||||
|
# using `throw :skip_children`
|
||||||
|
#
|
||||||
|
# This method uses a combination of breadth-first and depth-first
|
||||||
|
# traversal to traverse the entire XML tree in document order. See
|
||||||
|
# http://en.wikipedia.org/wiki/Breadth-first_search for more information.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# document.each_node do |node|
|
||||||
|
# p node.class
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# @example Skipping the children of a certain node
|
||||||
|
# document.each_node do |node|
|
||||||
|
# if node.is_a?(Oga::XML::Element) and node.name == 'book'
|
||||||
|
# throw :skip_children
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# @yieldparam [Oga::XML::Node] The current node.
|
||||||
|
#
|
||||||
|
def each_node
|
||||||
|
visit = children.to_a.dup # copy it since we're modifying the array
|
||||||
|
|
||||||
|
until visit.empty?
|
||||||
|
current = visit.shift
|
||||||
|
|
||||||
|
catch :skip_children do
|
||||||
|
yield current
|
||||||
|
|
||||||
|
visit = current.children.to_a + visit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end # Traversal
|
||||||
|
end # XML
|
||||||
|
end # Oga
|
|
@ -30,47 +30,6 @@ describe Oga::XML::Document do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context '#each_node' do
|
|
||||||
before do
|
|
||||||
@document = parse(<<-EOF.strip.gsub(/\s+/m, ''))
|
|
||||||
<books>
|
|
||||||
<book1>
|
|
||||||
<title1>Foo</title1>
|
|
||||||
</book1>
|
|
||||||
<book2>
|
|
||||||
<title2>Bar</title2>
|
|
||||||
</book2>
|
|
||||||
</books>
|
|
||||||
EOF
|
|
||||||
end
|
|
||||||
|
|
||||||
example 'yield the nodes in document order' do
|
|
||||||
names = []
|
|
||||||
|
|
||||||
@document.each_node do |node|
|
|
||||||
names << (node.is_a?(Oga::XML::Element) ? node.name : node.text)
|
|
||||||
end
|
|
||||||
|
|
||||||
names.should == %w{books book1 title1 Foo book2 title2 Bar}
|
|
||||||
end
|
|
||||||
|
|
||||||
example 'skip child nodes when skip_children is thrown' do
|
|
||||||
names = []
|
|
||||||
|
|
||||||
@document.each_node do |node|
|
|
||||||
if node.is_a?(Oga::XML::Element)
|
|
||||||
if node.name == 'book1'
|
|
||||||
throw :skip_children
|
|
||||||
else
|
|
||||||
names << node.name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
names.should == %w{books book2 title2}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context '#to_xml' do
|
context '#to_xml' do
|
||||||
before do
|
before do
|
||||||
child = Oga::XML::Comment.new(:text => 'foo')
|
child = Oga::XML::Comment.new(:text => 'foo')
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Oga::XML::Traversal do
|
||||||
|
context '#each_node' do
|
||||||
|
before do
|
||||||
|
@document = parse(<<-EOF.strip.gsub(/\s+/m, ''))
|
||||||
|
<books>
|
||||||
|
<book1>
|
||||||
|
<title1>Foo</title1>
|
||||||
|
</book1>
|
||||||
|
<book2>
|
||||||
|
<title2>Bar</title2>
|
||||||
|
</book2>
|
||||||
|
</books>
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'yield the nodes in document order' do
|
||||||
|
names = []
|
||||||
|
|
||||||
|
@document.each_node do |node|
|
||||||
|
names << (node.is_a?(Oga::XML::Element) ? node.name : node.text)
|
||||||
|
end
|
||||||
|
|
||||||
|
names.should == %w{books book1 title1 Foo book2 title2 Bar}
|
||||||
|
end
|
||||||
|
|
||||||
|
example 'skip child nodes when skip_children is thrown' do
|
||||||
|
names = []
|
||||||
|
|
||||||
|
@document.each_node do |node|
|
||||||
|
if node.is_a?(Oga::XML::Element)
|
||||||
|
if node.name == 'book1'
|
||||||
|
throw :skip_children
|
||||||
|
else
|
||||||
|
names << node.name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
names.should == %w{books book2 title2}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue