refactor: simplify indices_sorted_by_descending_values method; add HtmlTree class for parsing and traversing HTML
parent
c9a56f66f4
commit
9032b20783
@ -0,0 +1,95 @@
|
|||||||
|
require 'nokogiri'
|
||||||
|
|
||||||
|
class HtmlTree
|
||||||
|
include Enumerable
|
||||||
|
|
||||||
|
def initialize(html)
|
||||||
|
puts "Input HTML:\n#{html.inspect}" # Проверяем входной HTML
|
||||||
|
@root = parse_html(html)
|
||||||
|
raise "Parsed HTML tree is empty" if @root.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def each(order = :breadth_first, &block)
|
||||||
|
case order
|
||||||
|
when :breadth_first
|
||||||
|
breadth_first_traversal(&block)
|
||||||
|
when :depth_first
|
||||||
|
depth_first_traversal(&block)
|
||||||
|
else
|
||||||
|
raise ArgumentError, "Unknown order: #{order}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def parse_html(html)
|
||||||
|
doc = Nokogiri::HTML::DocumentFragment.parse(html)
|
||||||
|
root_node = doc.at_css('body') || doc.children.find(&:element?) || doc.root
|
||||||
|
return nil if root_node.nil? || root_node.children.empty?
|
||||||
|
|
||||||
|
build_tree(root_node)
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_tree(node)
|
||||||
|
if node.element?
|
||||||
|
children = node.children.map { |child| build_tree(child) }.compact
|
||||||
|
HtmlTag.new(node.name, node.attributes.transform_values(&:value), children)
|
||||||
|
elsif node.text? && !node.content.strip.empty?
|
||||||
|
HtmlTag.new("text", { "content" => node.content.strip }, [])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def breadth_first_traversal
|
||||||
|
queue = [@root].compact
|
||||||
|
until queue.empty?
|
||||||
|
current = queue.shift
|
||||||
|
next if current.nil?
|
||||||
|
|
||||||
|
yield current
|
||||||
|
queue.concat(current.children.compact) if current.has_children?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def depth_first_traversal(node = @root, &block)
|
||||||
|
return if node.nil?
|
||||||
|
|
||||||
|
yield node
|
||||||
|
node.children.compact.each { |child| depth_first_traversal(child, &block) } if node.has_children?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class HtmlTag
|
||||||
|
attr_reader :name, :attributes, :children
|
||||||
|
|
||||||
|
def initialize(name, attributes, children = [])
|
||||||
|
@name = name
|
||||||
|
@attributes = attributes
|
||||||
|
@children = children
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_children?
|
||||||
|
!@children.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"#{@name} #{@attributes}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
html = <<-HTML
|
||||||
|
<div id="root">
|
||||||
|
<p class="text">Hello, world!</p>
|
||||||
|
<ul>
|
||||||
|
<li>Item 1</li>
|
||||||
|
<li>Item 2</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
HTML
|
||||||
|
|
||||||
|
tree = HtmlTree.new(html)
|
||||||
|
|
||||||
|
puts "Traversal in breadth-first order:"
|
||||||
|
tree.each(:breadth_first) { |tag| puts tag }
|
||||||
|
|
||||||
|
puts "\nTraversal in depth-first order:"
|
||||||
|
tree.each(:depth_first) { |tag| puts tag }
|
Loading…
Reference in new issue