class Athena::Formats::XML

Constants

ELEMENT_START_RE

<www.w3.org/TR/2006/REC-xml-20060816/#NT-Name>

NON_ELEMENT_CHAR_RE
VALUE_SEPARATOR

Attributes

specs[R]

Public Instance Methods

convert(record) { |field, struct| ... } click to toggle source
# File lib/athena/formats/xml.rb, line 54
def convert(record)
  builder.row {
    builder.id record.id

    record.struct.each { |field, struct|
      if block_given?
        yield field, struct
      else
        builder.tag!(field) {
          struct[:elements].each { |element|
            (struct[:values][element] || []).each { |value|
              value = (value || '').strip
              builder.tag!(element, value) unless value.empty?
            }
          }
        }
      end
    }
  }
end
parse(input, &block) click to toggle source
# File lib/athena/formats/xml.rb, line 49
def parse(input, &block)
  REXML::Document.parse_stream(input, listener(&block))
  Athena::Record.records.size
end
raw?() click to toggle source
# File lib/athena/formats/xml.rb, line 95
def raw?
  true
end

Private Instance Methods

builder(options = {}) click to toggle source
# File lib/athena/formats/xml.rb, line 132
def builder(options = {})
  @builder ||= begin
    builder = Builder::XmlMarkup.new({ :indent => 2 }.merge(options))
    builder.instruct!

    def builder.method_missing(sym, *args, &block)
      elem = sym.to_s

      elem.insert(0, '_') unless elem =~ ELEMENT_START_RE
      elem.gsub!(NON_ELEMENT_CHAR_RE, '_')

      super(elem, *args, &block)
    end

    builder
  end
end
define_spec(element, field, config, arg) click to toggle source
# File lib/athena/formats/xml.rb, line 168
def define_spec(element, field, config, arg)
  spec = ElementSpec.new(element, field, config)
  arg.is_a?(Hash) ? spec.specs!(arg) : spec.default!(SubElementSpec.new(spec))
  spec
end
init_in(*) click to toggle source
Calls superclass method Athena::Formats::Base#init_in
# File lib/athena/formats/xml.rb, line 101
def init_in(*)
  @__record_element_ok__ = [String, Array]
  super

  case @skip_hierarchy = @config.delete(:__skip_hierarchy)
    when Integer
      # fine!
    when nil
      @skip_hierarchy = 0
    else
      raise ConfigError, "illegal value #{@skip_hierarchy.inspect} for skip hierarchy"
  end

  @specs = {}

  @config.each { |element, element_spec| element_spec.each { |field, c|
    element.split('/').reverse.inject({}) { |hash, part|
      s = define_spec(element, field, c, hash.empty? ? :default : hash)
      merge_specs(hash, part, s)
    }.each { |key, s|
      merge_specs(@specs, key, s)
    }
  } }
end
listener(&block) click to toggle source
# File lib/athena/formats/xml.rb, line 150
def listener(&block)
  record_spec = RecordSpec.new(&block)
  record_spec.specs!(specs)

  root_spec   = BaseSpec.new
  [*record_element].each { |re| root_spec.specs!(re => record_spec) }

  spec        = BaseSpec.new
  spec.default!(root_spec)

  @skip_hierarchy.times {
    prev_spec, spec = spec, BaseSpec.new
    spec.default!(prev_spec)
  }

  XMLStreamin::XMLStreamListener.new(spec)
end
merge_specs(container, key, spec) click to toggle source
# File lib/athena/formats/xml.rb, line 174
def merge_specs(container, key, spec)
  container.insert!(key => spec) { |_, spec1, spec2|
    if spec1.respond_to?(:specs!)
      spec1.specs!(spec2.respond_to?(:specs) ? spec2.specs : spec2)
      spec1
    else
      spec1.merge(spec2)
    end
  }
end
wrap() click to toggle source
Calls superclass method Athena::Formats::Base#wrap
# File lib/athena/formats/xml.rb, line 126
def wrap
  res = nil
  builder(:target => output).database { res = super() }
  res
end