Skip to content

Do you need to convert third party data into OpenStreetMap tags, but your object oriented language is clunky? This tool lets you express OSM tag transformations as SQLite queries.

License

blackboxlogic/OsmTagsTranslator

Repository files navigation

OsmTagsTranslator

Do you need to convert third party data into OpenStreetMap tags, but your object oriented language is clunky? This tool lets you express OSM tag transformations as SQLite queries.

This file has the address fields from Maine's department of transportation. These tags are not suitable for OSM 😒

<?xml version='1.0' encoding='UTF-8'?>
<osm version='0.6'>
  <node id='-101753' lat='43.73086183589' lon='-70.33776262438'>
    <tag k='ADDRESS_NUMBER' v='18' />
    <tag k='UNIT' v='' />
    <tag k='PREDIR' v='E' />
    <tag k='STREETNAME' v='Lillian' />
    <tag k='SUFFIX' v='Pl' />
    <tag k='POSTDIR' v='' />
    <tag k='POSTAL_COMMUNITY' v='Westbrook' />
    <tag k='STATE' v='ME' />
    <tag k='ZIPCODE' v='04092' />
    <tag k='PLACE_TYPE' v='fire station' />
	...
  </node>
	...
</osm>

Each tag needs some work. For example, addr:street=East Lillian Place must be composed from { PREDIR=E, STREETNAME=Lillian, SUFFIX=Pl}. We can express these transformations using a SQLite query 😮

SELECT
		-- These first two columns are required to identify elements
		xid,
		xtype,
		-- Every other column becomes a tag
		ADDRESS_NUMBER as [addr:housenumber],
		-- Some tags just need their key changed
		UNIT as [addr:unit],
		-- Other tags need lookups and string manipulation
		COALESCE(pre.Value || ' ', '')
			|| COALESCE(STREETNAME, '')
			|| COALESCE(' ' || suf.Value, '')
			|| COALESCE(' ' || post.Value, '') as [addr:street],
		POSTAL_COMMUNITY as [addr:city],
		STATE as [addr:state],
		ZIPCODE as [addr:postcode],
		-- Null or empty fields don't become tags
		LANDMARK as [name],
		-- Arbitrary tags can be added from more complicated lookup tables
		moreDetails.*
	FROM Elements
	-- Lookup are case-insensitive
	LEFT JOIN Directions as pre
		ON pre.ID = PREDIR
	LEFT JOIN Directions as post
		ON post.ID = POSTDIR
	LEFT JOIN StreetSuffixes as suf
		ON suf.ID = SUFFIX
	LEFT JOIN PlaceTypes as moreDetails
		ON moreDetails.ID = PLACE_TYPE
	-- Filter too, if you'd like. Those elements won't be in the result
	WHERE ADDRESS_NUMBER != '0'

JSON files can be loaded as tables with columns "ID" and "Value", like this one, which expands SUFFIX=Pl into Place 😌

{
	...
    "PIKES": "Pike",
    "PINE": "Pine",
    "PINES": "Pines",
    "PNES": "Pines",
    "PL": "Place",
    "PLAIN": "Plain",
    "PLN": "Plain",
    "PLAINS": "Plains",
	...
}

Provide as many lookup files as needed, like one to convert "E" to "East" or add arbitrary other tags.

Run > OsmTagsTranslatorConsole.exe SampleE911Addresses.osm Lookups\Directions.json Lookups\StreetSuffixes.json Lookups\PlaceTypes.json Quieries\E911AddressesToOsmSchema.sql

The resulting file is transformed into OSM conformant tags! 🧙🎩🐇

<?xml version='1.0' encoding='UTF-8'?>
<osm version='0.6'>
  <node id='-101753' lat='43.73086183589' lon='-70.33776262438'>
    <tag k='addr:housenumber' v='18' />
    <tag k='addr:city' v='Westbrook' />
    <tag k='addr:state' v='ME' />
    <tag k='addr:street' v='East Lillian Place' />
    <tag k='addr:postcode' v='04092' />
    <tag k="amenity" v="fire_station" />
  <node>
  ...
</osm>

This project is an executable, interactive command line tool, and a nuget package. Running in a command prompt without a sql script like > OsmTagsTranslatorConsole.exe SampleE911Addresses.osm lets you do data analysis, for example:

SELECT POSTAL_COMMUNITY, count(1) FROM Elements GROUP BY POSTAL_COMMUNITY ORDER BY 2 DESC

About

Do you need to convert third party data into OpenStreetMap tags, but your object oriented language is clunky? This tool lets you express OSM tag transformations as SQLite queries.

Topics

Resources

License

Stars

Watchers

Forks

Languages