class Eatr::Xml::Document

Attributes

schema[R]

Public Class Methods

new(schema_path) click to toggle source
# File lib/eatr/xml/document.rb, line 17
def initialize(schema_path)
  @schema = Schema.new(YAML.load(File.read(schema_path)))
end

Public Instance Methods

parse(xml_document_path) click to toggle source
# File lib/eatr/xml/document.rb, line 21
def parse(xml_document_path)
  @namespaces = {}

  parse_document = ->(f) do
    Nokogiri::XML(f) { |config| config.strict.nonet }
  end

  if File.exists?(xml_document_path)
    doc = File.open(xml_document_path, &parse_document)
  else
    doc = StringIO.open(xml_document_path, &parse_document)
  end


  if @schema.remove_namespaces?
    doc.remove_namespaces!
    @namespaces = {}
  else
    @namespaces = doc.collect_namespaces
  end

  cardinality = @schema.fields.inject(1) do |memo, field|
    if field.node?
      memo * [doc.xpath(field.xpath, @namespaces).count, 1].max
    else
      memo
    end
  end

  objects = []

  cardinality.times do |n|
    objects << @schema.to_struct.new
  end

  @schema.fields.each do |field|
    objects = set_field(objects, doc, field)
  end

  objects
end

Private Instance Methods

set_field(objects, doc, field) click to toggle source
# File lib/eatr/xml/document.rb, line 65
def set_field(objects, doc, field)
  if field.node?
    doc.xpath(field.xpath, @namespaces).each_with_index do |child_xml, idx|
      field.children.flat_map do |child|
        set_field([objects[idx]], child_xml, child)
      end
    end
  elsif field.name
    objects.each do |o|
      o.public_send("#{field.name}=", value_at(doc, field))
    end
  end

  objects
end
value_at(doc, field) click to toggle source
# File lib/eatr/xml/document.rb, line 81
def value_at(doc, field)
  if field.xpath
    if node = doc.at_xpath(field.xpath, @namespaces)
      parse_value(field, node.content)
    elsif field.value
      parse_value(field, field.value)
    elsif field.required?
      raise NodeNotFound, "Unable to find '#{field.name}' using xpath '#{field.xpath}'"
    end
  elsif field.value
    field.value
  end
end