class Eatr::Xml::SchemaGenerator

Public Class Methods

new(xml_path) click to toggle source
# File lib/eatr/xml/schema_generator.rb, line 4
def initialize(xml_path)
  @xml_path = xml_path
end

Public Instance Methods

schema(starting_point) click to toggle source
# File lib/eatr/xml/schema_generator.rb, line 8
def schema(starting_point)
  doc = File.open(@xml_path) do |f|
    Nokogiri::XML(f) do |config|
      config.strict.nonet
    end
  end

  doc.remove_namespaces!

  fields = doc.at_xpath(starting_point).element_children.flat_map do |child|
    field_def(child)
  end

  schema = {
    'name' => '',
    'remove_namespaces' => true,
    'fields' => fields
  }

  YAML.dump(schema)
end

Private Instance Methods

field_def(child, name_prefix: '', xpath_relative_to: nil) click to toggle source
# File lib/eatr/xml/schema_generator.rb, line 32
def field_def(child, name_prefix: '', xpath_relative_to: nil)
  if unique_children_count(child) == 1 && child.element_children.map(&:name).count > 1
    relative_path = Regexp.new(child.element_children.first.path.gsub(/\[\d+\]/, "\\[\\d+\\]"))
    node_path = child.element_children.first.path.gsub(/\[\d+\]/, "")

    {
      'node' => name_prefix + underscore(child.name),
      'xpath' => xpath_relative_to ? child.path.gsub(xpath_relative_to, ".") : node_path,
      'children' => child.element_children.first.element_children.flat_map do |c|
        field_def(c, name_prefix: "#{underscore(child.name)}_", xpath_relative_to: relative_path)
      end
    }
  elsif unique_children_count(child) >= 1
    child.element_children.flat_map do |c|
      field_def(c, name_prefix: "#{underscore(child.name)}_", xpath_relative_to: xpath_relative_to)
    end
  else
    {
      'name' => name_prefix + underscore(child.name),
      'xpath' => xpath_relative_to ? child.path.gsub(xpath_relative_to, ".") : child.path,
      'type' => 'string',
      'required' => false
    }
  end
end
underscore(str) click to toggle source
# File lib/eatr/xml/schema_generator.rb, line 62
def underscore(str)
  str.gsub(/::/, '/').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr("-", "_").
    downcase
end
unique_children_count(element) click to toggle source
# File lib/eatr/xml/schema_generator.rb, line 58
def unique_children_count(element)
  element.element_children.map(&:name).uniq.count
end