module MultiXml::Parsers::Oga

def each_attr(node, &)

def each_attr(node, &)
  node.attributes.each(&)
end

def each_child(node, &)

def each_child(node, &)
  node.children.each(&)
end

def node_name(node)

def node_name(node)
  node.name
end

def node_to_hash(node, hash = {}) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength

rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
def node_to_hash(node, hash = {}) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
  node_hash = {MultiXml::CONTENT_ROOT => ""}
  name = node_name(node)
  # Insert node hash into parent hash correctly.
  case hash[name]
  when Array
    hash[name] << node_hash
  when Hash
    hash[name] = [hash[name], node_hash]
  when NilClass
    hash[name] = node_hash
  end
  # Handle child elements
  each_child(node) do |c|
    if c.is_a?(::Oga::XML::Element)
      node_to_hash(c, node_hash)
    elsif c.is_a?(::Oga::XML::Text) || c.is_a?(::Oga::XML::Cdata)
      node_hash[MultiXml::CONTENT_ROOT] += c.text
    end
  end
  # Remove content node if it is empty
  node_hash.delete(MultiXml::CONTENT_ROOT) if node_hash[MultiXml::CONTENT_ROOT].strip.empty?
  # Handle attributes
  each_attr(node) do |a|
    key = node_name(a)
    v = node_hash[key]
    node_hash[key] = ((v) ? [a.value, v] : a.value)
  end
  hash
end

def parse(io)

def parse(io)
  document = ::Oga.parse_xml(io)
  node_to_hash(document.children[0])
end

def parse_error

def parse_error
  LL::ParserError
end