class GeoRuby::GeorssParser

Parses GeoRSS strings You can also use directly the static method Geometry.from_georss

Constants

GEORSS_REGEX

Attributes

geometry[R]
georss_tags[R]

Public Instance Methods

parse(georss, with_tags = false) click to toggle source

Parses the georss geometry passed as argument and notifies the factory of events the parser assumes

# File lib/geo_ruby/georss.rb, line 21
def parse(georss, with_tags = false)
  @geometry = nil
  @georss_tags = GeorssTags.new
  parse_geometry(georss, with_tags)
end

Private Instance Methods

parse_geometry(georss, with_tags) click to toggle source
# File lib/geo_ruby/georss.rb, line 29
def parse_geometry(georss, with_tags)
  georss.strip!
  # check for W3CGeo first
  if georss =~ /<[^:>]*:lat\s*>([^<]*)</
    # if valid, it is W3CGeo
    lat = Regexp.last_match[1].to_f
    if georss =~ /<[^:>]*:long\s*>([^<]*)</
      lon = Regexp.last_match[1].to_f
      @geometry = Point.from_x_y(lon, lat)
    else
      fail GeorssFormatError, 'Bad W3CGeo GeoRSS format'
    end
  elsif georss =~ /^<\s*[^:>]*:where\s*>/
    # GML format found
    gml = $'.strip
    if gml =~ /^<\s*[^:>]*:Point\s*>/
      # gml point
      if gml =~ /<\s*[^:>]*:pos\s*>([^<]*)/
        point = Regexp.last_match[1].split(' ')
        # lat comes first
        @geometry = Point.from_x_y(point[1].to_f, point[0].to_f)
      else
        fail GeorssFormatError, 'Bad GML GeoRSS: Malformed Point'
      end
    elsif gml =~ /^<\s*[^:>]*:LineString\s*>/
      if gml =~ /<\s*[^:>]*:posList\s*>([^<]*)/
        xy = Regexp.last_match[1].split(' ')
        @geometry = LineString.new
        0.upto(xy.size / 2 - 1) do |index|
          @geometry << Point.from_x_y(xy[index * 2 + 1].to_f,
                                      xy[index * 2].to_f)
        end
      else
        fail GeorssFormatError, 'Bad GML GeoRSS: Malformed LineString'
      end
    elsif gml =~ /^<\s*[^:>]*:Polygon\s*>/
      if gml =~ /<\s*[^:>]*:posList\s*>([^<]*)/
        xy = Regexp.last_match[1].split(' ')
        @geometry = Polygon.new
        linear_ring = LinearRing.new
        @geometry << linear_ring
        xy = Regexp.last_match[1].split(' ')
        0.upto(xy.size / 2 - 1) do |index|
          linear_ring << Point.from_x_y(xy[index * 2 + 1].to_f,
                                        xy[index * 2].to_f)
        end
      else
        fail GeorssFormatError, 'Bad GML GeoRSS: Malformed Polygon'
      end
    elsif gml =~ /^<\s*[^:>]*:Envelope\s*>/
      if gml =~ /<\s*[^:>]*:lowerCorner\s*>([^<]*)</
        lc = Regexp.last_match[1].split(' ').collect(&:to_f).reverse
        if gml =~ /<\s*[^:>]*:upperCorner\s*>([^<]*)</
          uc = Regexp.last_match[1].split(' ').collect(&:to_f).reverse
          @geometry = Envelope.from_coordinates([lc, uc])
        else
          fail GeorssFormatError, 'Bad GML GeoRSS: Malformed Envelope'
        end
      else
        fail GeorssFormatError, 'Bad GML GeoRSS: Malformed Envelope'
      end
    else
      fail GeorssFormatError, 'Bad GML GeoRSS: Unknown geometry type'
    end
  else
    # must be simple format
    if georss =~ /^<\s*[^>:]*:point([^>]*)>(.*)</m
      tags = Regexp.last_match[1]
      point = Regexp.last_match[2].gsub(',', ' ').split(' ')
      @geometry = Point.from_x_y(point[1].to_f, point[0].to_f)
    elsif georss =~ /^<\s*[^>:]*:line([^>]*)>(.*)</m
      tags = Regexp.last_match[1]
      @geometry = LineString.new
      xy = Regexp.last_match[2].gsub(',', ' ').split(' ')
      0.upto(xy.size / 2 - 1) do |index|
        @geometry << Point.from_x_y(xy[index * 2 + 1].to_f,
                                    xy[index * 2].to_f)
      end
    elsif georss =~ /^<\s*[^>:]*:polygon([^>]*)>(.*)</m
      tags = Regexp.last_match[1]
      @geometry = Polygon.new
      linear_ring = LinearRing.new
      @geometry << linear_ring
      xy = Regexp.last_match[2].gsub(',', ' ').split(' ')
      0.upto(xy.size / 2 - 1) do |index|
        linear_ring << Point.from_x_y(xy[index * 2 + 1].to_f,
                                      xy[index * 2].to_f)
      end
    elsif georss =~ /^<\s*[^>:]*:box([^>]*)>(.*)</m
      tags = Regexp.last_match[1]
      corners = []
      xy = Regexp.last_match[2].gsub(',', ' ').split(' ')
      0.upto(xy.size / 2 - 1) do |index|
        corners << Point.from_x_y(xy[index * 2 + 1].to_f,
                                  xy[index * 2].to_f)
      end
      @geometry = Envelope.from_points(corners)
    else
      fail GeorssFormatError, 'Bad Simple GeoRSS format: ' \
                              'Unknown geometry type'
    end

    # geometry found: parse tags
    return unless with_tags
    if tags =~ /featuretypetag#{GEORSS_REGEX}/
      @georss_tags.featuretypetag = Regexp.last_match[1]
    end

    if tags =~ /relationshiptag#{GEORSS_REGEX}/
      @georss_tags.relationshiptag = Regexp.last_match[1]
    end

    if tags =~ /elev#{GEORSS_REGEX}/
      @georss_tags.elev = Regexp.last_match[1].to_f
    end

    if tags =~ /floor#{GEORSS_REGEX}/
      @georss_tags.floor = Regexp.last_match[1].to_i
    end

    if tags =~ /radius#{GEORSS_REGEX}/
      @georss_tags.radius = Regexp.last_match[1].to_f
    end

  end
end