2014-03-26 17:12:00 +00:00
|
|
|
module Oga
|
|
|
|
module XML
|
|
|
|
##
|
2014-03-28 16:11:54 +00:00
|
|
|
# The TreeBuilder class turns an AST into a DOM tree. This DOM tree can be
|
|
|
|
# traversed by requesting child elements, parent elements, etc.
|
2014-03-26 17:12:00 +00:00
|
|
|
#
|
2014-03-28 16:11:54 +00:00
|
|
|
# Basic usage:
|
|
|
|
#
|
|
|
|
# builder = Oga::XML::TreeBuilder.new
|
|
|
|
# ast = s(:element, ...)
|
|
|
|
#
|
|
|
|
# builder.process(ast) # => #<Oga::XML::Document ...>
|
2014-03-26 17:12:00 +00:00
|
|
|
#
|
2014-03-28 15:37:37 +00:00
|
|
|
class TreeBuilder < ::AST::Processor
|
2014-03-28 16:11:54 +00:00
|
|
|
##
|
|
|
|
# @param [Oga::AST::Node] node
|
|
|
|
# @return [Oga::XML::Document]
|
|
|
|
#
|
2014-03-28 07:59:48 +00:00
|
|
|
def on_document(node)
|
|
|
|
document = Document.new
|
|
|
|
document.children = process_all(node)
|
|
|
|
|
|
|
|
document.children.each do |child|
|
|
|
|
child.parent = document
|
|
|
|
end
|
|
|
|
|
|
|
|
return document
|
|
|
|
end
|
|
|
|
|
2014-03-28 16:11:54 +00:00
|
|
|
##
|
|
|
|
# @param [Oga::AST::Node] node
|
|
|
|
# @return [Oga::XML::Comment]
|
|
|
|
#
|
2014-03-28 07:59:48 +00:00
|
|
|
def on_comment(node)
|
|
|
|
return Comment.new(:text => node.children[0])
|
2014-03-26 17:12:00 +00:00
|
|
|
end
|
|
|
|
|
2014-03-28 16:11:54 +00:00
|
|
|
##
|
|
|
|
# Processes an `(element)` node and its child elements.
|
|
|
|
#
|
|
|
|
# An element can have a parent, previous and next element as well as a
|
|
|
|
# number of child elements.
|
|
|
|
#
|
|
|
|
# @param [Oga::AST::Node] node
|
|
|
|
# @return [Oga::XML::Element]
|
|
|
|
#
|
2014-03-26 17:12:00 +00:00
|
|
|
def on_element(node)
|
2014-03-28 07:59:48 +00:00
|
|
|
ns, name, attr, *children = *node
|
|
|
|
|
|
|
|
if attr
|
|
|
|
attr = process(attr)
|
|
|
|
end
|
|
|
|
|
|
|
|
if children
|
2014-03-28 16:11:54 +00:00
|
|
|
children = process_all(children.compact)
|
2014-03-28 07:59:48 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
element = Element.new(
|
|
|
|
:name => name,
|
|
|
|
:namespace => ns,
|
|
|
|
:attributes => attr,
|
|
|
|
:children => children
|
|
|
|
)
|
|
|
|
|
2014-03-28 16:11:54 +00:00
|
|
|
process_children(element)
|
2014-03-28 07:59:48 +00:00
|
|
|
|
|
|
|
return element
|
2014-03-26 17:12:00 +00:00
|
|
|
end
|
|
|
|
|
2014-03-28 16:11:54 +00:00
|
|
|
##
|
|
|
|
# @param [Oga::AST::Node] node
|
|
|
|
# @return [Oga::XML::Text]
|
|
|
|
#
|
2014-03-26 17:12:00 +00:00
|
|
|
def on_text(node)
|
2014-03-28 07:59:48 +00:00
|
|
|
return Text.new(:text => node.children[0])
|
|
|
|
end
|
|
|
|
|
2014-03-28 16:11:54 +00:00
|
|
|
##
|
|
|
|
# @param [Oga::AST::Node] node
|
|
|
|
# @return [Oga::XML::Cdata]
|
|
|
|
#
|
2014-03-28 08:27:53 +00:00
|
|
|
def on_cdata(node)
|
|
|
|
return Cdata.new(:text => node.children[0])
|
|
|
|
end
|
2014-03-28 07:59:48 +00:00
|
|
|
|
2014-03-28 16:11:54 +00:00
|
|
|
##
|
|
|
|
# Converts a `(attributes)` node into a Hash.
|
|
|
|
#
|
|
|
|
# @param [Oga::AST::Node] node
|
|
|
|
# @return [Hash]
|
|
|
|
#
|
2014-03-28 07:59:48 +00:00
|
|
|
def on_attributes(node)
|
|
|
|
pairs = process_all(node)
|
|
|
|
|
|
|
|
return Hash[pairs]
|
|
|
|
end
|
2014-03-26 17:12:00 +00:00
|
|
|
|
2014-03-28 16:11:54 +00:00
|
|
|
##
|
|
|
|
# @param [Oga::AST::Node] node
|
|
|
|
# @return [Array]
|
|
|
|
#
|
2014-03-28 07:59:48 +00:00
|
|
|
def on_attribute(node)
|
|
|
|
return *node
|
2014-03-26 17:12:00 +00:00
|
|
|
end
|
2014-03-28 16:11:54 +00:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
##
|
|
|
|
# Iterates over the child elements of an element and assigns the parent,
|
|
|
|
# previous and next elements. The supplied object is modified in place.
|
|
|
|
#
|
|
|
|
# @param [Oga::XML::Element] element
|
|
|
|
#
|
|
|
|
def process_children(element)
|
|
|
|
amount = element.children.length
|
|
|
|
|
|
|
|
element.children.each_with_index do |child, index|
|
|
|
|
prev_index = index - 1
|
|
|
|
next_index = index + 1
|
|
|
|
|
|
|
|
if index > 0
|
|
|
|
child.previous = element.children[prev_index]
|
|
|
|
end
|
|
|
|
|
|
|
|
if next_index <= amount
|
|
|
|
child.next = element.children[next_index]
|
|
|
|
end
|
|
|
|
|
|
|
|
child.parent = element
|
|
|
|
end
|
|
|
|
end
|
2014-03-28 15:37:37 +00:00
|
|
|
end # TreeBuilder
|
2014-03-26 17:12:00 +00:00
|
|
|
end # XML
|
|
|
|
end # Oga
|