Path: README.txt
Last Update: Tue Jun 24 10:21:52 +0200 2008

OSM Library - Base

A library for handling OpenStreetMap data.


This work is released into the public domain. This applies worldwide. In case this is not legally possible, any entity is granted the right to use this work for any purpose, without any conditions, unless such conditions are required by law.


Jochen Topf <>


For more information see the OSM Library home page at or the Rubyforge project page at . The OpenStreetMap project can be found at .


  • georuby
  • libxml-ruby (optional C-based XML parser, needs reasonably new version) (Debian/Ubuntu: libxml-ruby1.8)
  • xmlparser (optional C-based XML parser) (Debian/Ubuntu: libxml-parser-ruby1.8)
  • builder (Debian/Ubuntu: libbuilder-ruby1.8)

Dependencies are not all installed automatically when installing the gem packages because this breaks when the packages are already installed as Debian packages.


Basic OSM Objects

The library provides classes for the three basic building blocks of any OSM database: OSM::Node, OSM::Way, and OSM::Relation. They are all subclasses of OSM::OSMObject.

  # support for basic OSM objects
  require 'OSM/objects'

  # create a node
  node =, 'user', '2007-10-31T23:48:54Z', 7.4, 53.2)

  # create a way and add a node
  way =, 'user', '2007-10-31T23:51:17Z')
  way.nodes << node

  # create a relation
  relation =, 'user', '2007-10-31T23:51:53Z')

There is also an OSM::Member class for members of a relation:

  # create a member and add it to a relation
  member ='way', 1743, 'role')
  relation << [member]

Tags can be added to Nodes, Ways, and Relations:

  way.add_tags('highway' => 'residential', 'name' => 'Main Street')

You can get the hash of tags like this:

  way.tags['name'] = 'Bay Street'

As a convenience tags can also be accessed with their name only:


This is implemented with the method_missing() function. Of course it only works for tag keys which are allowed as ruby method names.

Accessing the OSM API

You can access the OSM RESTful web API through the OSM::API class and through some methods in the OSM::Node, OSM::Way, and OSM::Relation classes.

There are methods for getting Nodes, Ways, and Relations by ID, getting the history of an object etc.

Currently only read access is implemented, write access will follow in a later version.

See the OSM::API class for details.

The Stream Parser

To parse an OSM XML file create a subclass of OSM::Callbacks and define the methods node(), way(), and relation() in it:

  class MyCallbacks < OSM::Callbacks

    def node(node)

    def way(way)

    def relation(relation)


Instantiate an object of this class and give it to a OSM::StreamParser:

  require 'OSM/StreamParser'

  cb =
  parser = => 'filename.osm', :callbacks => cb)

The methods node(), way(), or relation() will be called whenever the parser has parsed a complete node, way, or relation (i.e. after all tags, nodes in a way, or members of a relation are available).

There are several parser options available:

  • REXML (Default, slow, works on all machines, because it is part of the Ruby standard distribution)
  • Libxml (Based on the C libxml2 library, faster than REXML, new version needed, sometimes hard to install)
  • Expat (Based on C Expat library, faster than REXML)

Since version 0.1.3 REXML is the default parser because many people had problems with the C-based parser. Change the parser by setting the environment variable OSMLIB_XML_PARSER to the parser you want to use (before you require ‘OSM/StreamParser’):

From the shell:

    export OSMLIBX_XML_PARSER=Libxml

From ruby:

    require 'OSM/StreamParser'

Using a Database

If you want the parser to keep track of all the objects it finds in the XML file you can create a OSM::Database for it:

  require 'OSM/Database'

  db =

The database lives in memory so this works only if the XML file is not too big.

When creating the parser you can give it the database object:

  parser = => 'filename.osm', :db => db)

In your node(), way(), and relation() methods you now have to return true if you want this object to be stored in the database and false otherwise. This gives you a very simple filtering mechanism. If you are only interested in pharmacies, you can use this code:

  def node(node)
    return true if node.amenity == 'pharmacy'

After the whole file has been parsed, all nodes with amenity=pharmacy will be available through the database. All other objects have been thrown away. You can get a hash of all nodes (key is id, value is a Node object) with:


Or single nodes with the ID:


Ways and relations are accessed the same way.

When deleting a database call


first. This will break the internal loop references and makes sure that the garbage collector can free the memory.

More examples

For more examples see the examples directory.


Call ‘rake test’ to run tests. You can change the XML parser the tests should use by setting the OSMLIB_XML_PARSER environment variable:

  OSMLIB_XML_PARSER=REXML rake test  # (default)
  OSMLIB_XML_PARSER=Libxml rake test
  OSMLIB_XML_PARSER=Expat rake test