How to Parse XML with Ruby

With one of my side projects, I’ve been investigating how to integrate maps with a Rails application. One of the tasks for a proof of concept was to mock up some reviews for restaurants, and I came across the Overpass API, which exposes a nice interface for getting lists of map items.

To get an XML document with the list of restaurants in your area, you simply submit a http get request to the properly formed URL… like so:

http://www.overpass-api.de/api/xapi?node[bbox=7.1,51.2,7.2,51.3][amenity=restaurant]

The bbox attribute specifies the “bounding box” of the area you want to search as latitude and longitude coordinates.
The output from the query will give you xml that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="Overpass API">
<meta osm_base="2012-03-11T22:12:02Z"/>
  <node id="266302295" lat="36.0164193" lon="-78.9189592">
    <tag k="amenity" v="restaurant"/>
    <tag k="created_by" v="Potlatch 0.9a"/>
    <tag k="name" v="Watts Grocery"/>
  </node>
  <node id="266814066" lat="36.0139023" lon="-78.9215805">
    <tag k="amenity" v="restaurant"/>
    <tag k="created_by" v="Potlatch 0.9a"/>
    <tag k="name" v="Magnolia Grill"/>
  </node>
  <node id="266814217" lat="36.0106114" lon="-78.9222843">
    <tag k="amenity" v="restaurant"/>
    <tag k="created_by" v="Potlatch 0.9a"/>
    <tag k="name" v="Vin Rouge"/>
  </node>
...
</osm>

I took this XML and saved it to a file named restaurants.xml

After you have the XML, you sill need to parse it. To do that, I used REXML which is built into the ruby library. For this example, I create a “Restaurant” object for each of the XML nodes, and parsed it using XPath expressions to get the values I cared about. Then I saved off the values and made sure each object was saved to my DB.

xml = File.read('./lib/restaurants.xml')

require 'rexml/document'
doc = REXML::Document.new(xml)

doc.elements.each('osm/node') {|x|
   r = Restaurant.new
   r.name = x.elements["tag[@k='name']"].attributes["v"]
   r.openmap_id = x.attributes["id"].to_i
   r.latitude = x.attributes["lat"]
   r.longitude = x.attributes["lon"]
   r.save
}

Tagged , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *