class X12::XMLDefinitions

A class for parsing X12 message definition expressed in XML format.

Public Class Methods

new(str) click to toggle source

Parse definitions out of XML file. @param str [String]

# File lib/x12/xmldefinitions.rb, line 7
def initialize(str)
  doc = LibXML::XML::Document.string(str)
  definitions = doc.root.name =~ /^Definition$/i ? doc.root.find('*').to_a : [doc.root]

  definitions.each do |element|
    # puts element.name
    syntax_element = case element.name
                     when /table/i
                       parse_table(element)
                     when /segment/i
                       parse_segment(element)
                     when /composite/i
                       parse_composite(element)
                     when /loop/i
                       parse_loop(element)
                     end
    self[syntax_element.class] ||= {}
    self[syntax_element.class][syntax_element.name] = syntax_element
  end
end

Private Instance Methods

parse_attributes(e) click to toggle source
# File lib/x12/xmldefinitions.rb, line 74
def parse_attributes(e)
  throw Exception.new("No name attribute found for : #{e.inspect}")          unless name = e.attributes['name']
  throw Exception.new("Cannot parse attribute 'min' for: #{e.inspect}")      unless min = parse_int(e.attributes['min'])
  throw Exception.new("Cannot parse attribute 'max' for: #{e.inspect}")      unless max = parse_int(e.attributes['max'])
  throw Exception.new("Cannot parse attribute 'type' for: #{e.inspect}")     unless type = parse_type(e.attributes['type'])
  throw Exception.new("Cannot parse attribute 'required' for: #{e.inspect}") if (required = parse_boolean(e.attributes['required'])).nil?

  validation = e.attributes['validation']
  min = 1 if required and min < 1
  max = 999_999 if max.zero?

  return name, min, max, type, required, validation
end
parse_boolean(s) click to toggle source
# File lib/x12/xmldefinitions.rb, line 30
def parse_boolean(s)
  return case s
         when nil
           false
         when ''
           false
         when /(^y(es)?$)|(^t(rue)?$)|(^1$)/i
           true
         when /(^no?$)|(^f(alse)?$)|(^0$)/i
           false
         else
           nil
         end
end
parse_composite(e) click to toggle source
# File lib/x12/xmldefinitions.rb, line 120
def parse_composite(e)
  name, _min, _max, _type, _required, _validation = parse_attributes(e)

  fields = e.find('Field').inject([]) { |f, field|
    f << parse_field(field)
  }
  Composite.new(name, fields)
end
parse_field(e) click to toggle source
# File lib/x12/xmldefinitions.rb, line 88
def parse_field(e)
  name, min, max, type, required, validation = parse_attributes(e)

  # FIXME: for compatibility with d12 - constants are stored in attribute 'type' and are enclosed in
  # double quotes
  const_field = e.attributes['const']
  if const_field
    type = "\"#{const_field}\""
  end

  Field.new(name, type, required, min, max, validation)
end
parse_int(s) click to toggle source
# File lib/x12/xmldefinitions.rb, line 64
def parse_int(s)
  return case s
         when nil then 0
         when /^\d+$/ then s.to_i
         when /^inf(inite)?$/ then 999_999
         else
           nil
         end
end
parse_loop(e) click to toggle source
# File lib/x12/xmldefinitions.rb, line 129
def parse_loop(e)
  name, min, max, _type, _required, _validation = parse_attributes(e)

  components = e.find('*').to_a.inject([]) { |r, element|
    r << case element.name
         when /loop/i
           parse_loop(element)
         when /segment/i
           parse_segment(element)
         else
           throw Exception.new("Cannot recognize syntax for: #{element.inspect} in loop #{e.inspect}")
         end
  }
  Loop.new(name, components, Range.new(min, max))
end
parse_segment(e) click to toggle source
# File lib/x12/xmldefinitions.rb, line 111
def parse_segment(e)
  name, min, max, _type, _required, _validation = parse_attributes(e)

  fields = e.find('Field').inject([]) { |f, field|
    f << parse_field(field)
  }
  Segment.new(name, fields, Range.new(min, max))
end
parse_table(e) click to toggle source
# File lib/x12/xmldefinitions.rb, line 101
def parse_table(e)
  name, _min, _max, _type, _required, _validation = parse_attributes(e)

  content = e.find('Entry').inject({}) { |t, entry|
    t[entry.attributes['name']] = entry.attributes['value']
    t
  }
  Table.new(name, content)
end
parse_type(s) click to toggle source
# File lib/x12/xmldefinitions.rb, line 45
def parse_type(s)
  return case s
         when nil
           'string'
         when /^C.+$/
           s
         when /^i(nt(eger)?)?$/i
           'int'
         when /^l(ong)?$/i
           'long'
         when /^d(ouble)?$/i
           'double'
         when /^s(tr(ing)?)?$/i
           'string'
         else
           nil
         end
end