class GeoRuby::KmlParser

Constants

ELEMENT_MAP

Public Class Methods

new(factory) click to toggle source
# File lib/geo_ruby/kml.rb, line 12
def initialize(factory)
  @factory = factory
  @buffer = ''
  @with_z = false
end

Public Instance Methods

parse(kml) click to toggle source

argument should be a valid kml geometry fragment ie. <Point> .… </Point> returns the GeoRuby geometry object back

# File lib/geo_ruby/kml.rb, line 20
def parse(kml)
  @factory.reset
  @with_z = false
  @parser = REXML::Parsers::PullParser.new(kml)
  while @parser.has_next?
    e = @parser.pull
    if e.start_element?
      if (type = ELEMENT_MAP[e[0]])
        @factory.begin_geometry(type)
      else
        @buffer = '' if (e[0] == 'coordinates') # clear the buffer
        accumulate_start(e)
      end
    elsif e.end_element?
      if ELEMENT_MAP[e[0]]
        @factory.end_geometry(@with_z)
        @buffer = '' # clear the buffer
      else
        accumulate_end(e)
        if (e[0] == 'coordinates')
          parse_coordinates(@buffer)
          @buffer = '' # clear the buffer
        end
      end
    elsif e.text?
      accumulate_text(e)
    elsif e.cdata?
      accumulate_cdata(e)
    end
  end
  @factory.geometry.dup
end

Private Instance Methods

accumulate_cdata(e) click to toggle source
# File lib/geo_ruby/kml.rb, line 59
def accumulate_cdata(e)
  @buffer << "<![CDATA[#{e[0]}]]>"
end
accumulate_end(e) click to toggle source
# File lib/geo_ruby/kml.rb, line 71
def accumulate_end(e)
  @buffer << "</#{e[0]}>"
end
accumulate_start(e) click to toggle source
# File lib/geo_ruby/kml.rb, line 63
def accumulate_start(e)
  @buffer << "<#{e[0]}"
  if (e[1].class == Hash)
    e[1].each_pair { |k, v| @buffer << " #{k}='#{v}'" }
  end
  @buffer << '>'
end
accumulate_text(e) click to toggle source
# File lib/geo_ruby/kml.rb, line 55
def accumulate_text(e)
  @buffer << e[0]
end
parse_coordinates(buffer) click to toggle source
# File lib/geo_ruby/kml.rb, line 75
def parse_coordinates(buffer)
  if buffer =~ /<coordinates>(.+)<\/coordinates>/m
    Regexp.last_match[1].gsub(/\n/, ' ').strip.split(/\s+/).each do |coord|
      x, y, z = coord.split(',')
      if x.nil? || y.nil?
        fail StandardError, 'coordinates must have at least x and y elements'
      end
      @factory.begin_geometry(SimpleFeatures::Point)
      if z.nil?
        @factory.add_point_x_y(x, y)
      else
        @factory.add_point_x_y_z(x, y, z)
        @with_z = true unless @with_z # is the conditional even necessary
      end
      @factory.end_geometry(@with_z)
    end
  end
rescue
  raise StandardError, 'error parsing coordinates: check your kml for errors'
end