Before you study the details of specific APIs, you should understand the formats used to get data in and out of maps. Sometimes you can make a map by formatting what you want to place on a map in the right format. You already saw this approach in the previous section where I showed you how to transform the Yahoo! Local collection XML into CSV to feed to Mapbuilder.net. In the following sections, I’ll examine some common data formats for online maps:
CSV
Microformats and other metatags
GeoRSS
KML
CSV stands for comma-separated values. It is a simple and widely supported format across many operating systems and applications. For tabular data, it is conceptually simpler and more compact than XML. In the case of Mapbuilder.net, you can upload the data for a set of markers using CSV format. For each marker, you can specify the caption, street address, city, state, and ZIP code. Mapbuilder.net can then geocode the addresses (that is, calculate the latitude and longitude of the address) to place them on a map. The built-in geocoding functionality of Mapbuilder.net is a major convenience for users.
For example, you can use a simple use of CSV by Geocoder.us (a service to convert U.S. addresses to latitude and longitude). The following:
http://rpc.geocoder.us/service/csv?address=2855+Telegraph+Ave.,+Berkeley,+CA
returns this:
37.858276,-122.260070,2855 Telegraph Ave,Berkeley,CA,94705
Some web sites have taken to embedding geographic information in HTML. As I will
discuss in Chapter 18, microformats are little parcels of structured data that are
seamlessly embedded in web pages—making them easily parsed by computer programs so
that the data can be reused in other contexts. There are two relevant microformats in
this context: geo
and adr
.
Consider the case of geotagged photos in Flickr, specifically the example I have already used in this book:
http://www.flickr.com/photos/raymondyee/18389540/
in which you will see the use of both the geo
and adr
microformats as instantiated in the following pieces of HTML, respectively:
<span class='geo' style='display:none'><span class='latitude'>37.8721</span> <span class='longitude'>-122.257704</span></span> <li id="li_location" class="Stats adr"> [....] <span class='locality'>Oakland</span>, <span class='region'>California</span> [....] </li>
![]() | Caution |
---|---|
Although the latitude and longitude are correct, the placement of the address in
Oakland, California, is inaccurate unless Berkeley is being subsumed as part of
Oakland. This inaccuracy doesn’t take away from the syntactic correctness of
the |
You might notice also the use of two metatags that embed the latitude and longitude
corresponding to the photo. The ICBM
<meta>
tag, which in this case is as follows, is documented at
http://geourl.org/add.html
:
<meta name="ICBM" content="37.8721, -122.257704">
You can learn more about the geo.position
metatag, such as the
following:
<meta name="geo.position" content="37.8721; -122.257704">
at http://geotags.com/geo/
. Both the <meta>
tags
(located in the <head>
section) are used to associate a latitude and
longitude with a web page as a whole.
GeoRSS (http://georss.org/
) is a way of embedding location information
within RSS 2.0, RSS 1.0, Atom 1.0, and potentially other XML formats. GeoRSS seems to be
a standard—or at least an emerging one. In GeoRSS, you can represent points,
lines, boxes, and polygons. Let’s look in more detail at how to work with points.
GeoRSS is conceptually simple, but you might get confused by the fact that there are at least four ways to encode GeoRSS points in XML. The first two are the recommended encodings going forward, while the second set of two are considered legacy formats that are nonetheless widely used and therefore recommended for support. I list them here with examples:
The GeoRSS GML encoding (http://georss.org/gml
)
wraps the gml:pos
element in a gml:Point
element within
georss:where
—where the gml
prefix corresponds
to http://www.opengis.net/gml
and the georss
prefix
corresponds to http://www.georss.org/georss
:
<georss:where> <gml:Point> <gml:pos>37.8721 -122.257704</gml:pos> </gml:Point> </georss:where>
The GeoRSS Simple encoding (http://georss.org/simple
) uses a single georss:point
element to contain the latitude and longitude, where georss
corresponds to the same namespace as for the GeoRSS GML encoding (that is,
http://www.georss.org/georss
):
<georss:point>37.8721 -122.257704</georss:point>
The W3C Basic Geo encoding
(http://georss.org/w3c
) uses
geo:Point
to wrap the geo:lat
and
geo:long
elements—where the geo
namespace
prefix refers to http://www.w3.org/2003/01/geo/wgs84_pos#._gml
:
<geo:Point> <geo:lat>37.8721 </geo:lat> <geo:long>-122.257704</geo:long> </geo:Point>
A common variant of the previous, which I call here the Compact W3C
Basic Geo encoding, drops the enclosing
geo:Point
:
<geo:lat>37.8721</geo:lat> <geo:long>-122.257704</geo:long>
If you refer to Listing 13-3, you will note that the Live Search Maps collection uses the GeoRSS Simple ? encoding. Let’s also look at Flickr GeoFeed, which you can currently get for a given user here:
http://api.flickr.com/services/feeds/geo/?id={user-nsid}&lang=en-us&format=rss_200
For example, the GeoFeed for Rev. Dan Catt (the driving force behind Flickr geotagging) is as follows:
http://api.flickr.com/services/feeds/geo/?id=35468159852@N01&lang=en-us&format=rss_200
You can also get a GeoFeed for a given Flickr group here:
http://api.flickr.com/services/feeds/geo/?g={group-nsid}&lang=en-us&format=rss_200
For example, the GeoFeed for the FlickrCentral group is as follows:
http://api.flickr.com/services/feeds/geo/?g=34427469792@N01&lang=en-us&format=rss_200
Studying the GeoFeeds, you’ll notice the use of two GeoRSS encodings, the GeoRSS Simple and W3C Basic Geo encodings, within the GeoFeeds:
<?xml version="1.0" encoding="utf-8"?> <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:georss="http://www.georss.org/georss"> <channel> [....] <item> <title>maybe not</title> <link>http://www.flickr.com/photos/solidether/1270523097/</link> [....] <georss:point>51.269057 12.345714</georss:point> <geo:Point> <geo:lat>51.269057</geo:lat> <geo:long>12.345714</geo:long> </geo:Point> [....] </item> [....] </channel> </rss>
When you read Yahoo!’s documentation at the following locations about its
support for GeoRSS, you might get confused by the conflation of its own set of
extensions to RSS 2.0 that use YMaps (corresponding to http://api.maps.yahoo.com/Maps/V1/AnnotatedMaps.xsd
or http://api.maps.yahoo.com/Maps/V2/AnnotatedMaps.xsd
—depending
on which API you are using):
http://developer.yahoo.com/maps/simple/V1/reference.html
(for
the Yahoo! Maps Simple API)
http://developer.yahoo.com/maps/georss/index.html
(for its
Ajax API)
There are a whole bunch of tags, but I’ll focus here on the ones for marking up
addresses: <ymaps:Address>
, <ymaps:CityState>
,
<ymaps:Zip>
, and <ymaps:Country>
to denote an
address associated with an <item>
.
The Yahoo! Simple API[170]
This ability to use a mix of Geo and YMaps extensions reflects the ability of Yahoo!
Maps to do the geocoding for you: you can still place a point on a map without knowing
the latitude and longitude as long as you have an address that you can mark up with the
appropriate ymaps
tag. (We will look later at how to call on services to do
explicit geocoding.) However, you must not conflate the YMaps extension with
GeoRSS—they are not the same. For instance, I don’t know of any applications
outside of Yahoo! Maps that supports the YMaps extensions.
Let’s look at a working example of how to use the YMaps extension. Recall that you can use the Yahoo! Local API to get the XML for a collection here:
http://collections.local.yahooapis.com/LocalSearchService/V1/getCollection?appid={app-id}&collection_id={collection-id}
For example, the following is the URL for the collection of bookstores that I have assembled:
http://collections.local.yahooapis.com/LocalSearchService/V1/getCollection?appid={appp-id}&collection_id=1000014156
I have cached the results of the API call here:
http://examples.mashupguide.net/ch13/bookstores.yahoo.local.xml
You can convert this XML to RSS 2.0 with the YMaps extension either by hand or by using some XSLT code that I wrote for that purpose. What you get, which is cached here:
http://examples.mashupguide.net/ch13/yahoo.local.to.georss.xsl
is the following:
<?xml version="1.0" encoding="UTF-8"?> <rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:yahoo="urn:yahoo:travel" xmlns:ymaps="http://api.maps.yahoo.com/Maps/V1/AnnotatedMaps.xsd" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" version="2.0"> <channel> <title>bookstores around Berkeley</title> <link>http://local.yahoo.com/collections?cid=1000014156</link> <description>some of my favorite bookstores around Berkeley.</description> <item> <title>Moe's Books</title> <link>http://local.yahoo.com/details?id=21518795&stx=&csz=Berkeley+CA&ed=xoDOxa160SyYoswS6OvDhQk64pj4Q8RHG5PQhcSqprzxVT6mDHMezwfQ2U244pugG4LDSdibA78iSw--</link> <description> * The Bay Area's Largest Selection of Used Scholarly Books </description> <ymaps:Address>2476 Telegraph Ave</ymaps:Address> <ymaps:CityState>Berkeley, CA</ymaps:CityState> <ymaps:Zip>94704</ymaps:Zip> <ymaps:Country>US</ymaps:Country> </item> <item> <title>Cody's Books</title> <link>http://local.yahoo.com/details?id=21512172&stx=&csz=Berkeley+CA&ed=3uqWba160SzFEqntYzu46yunejqBEmJnCBEi_I7QbD68sZTEVRYl4WkOGEf6alVIaEB3</link> <description/> <ymaps:Address>1730 4th St</ymaps:Address> <ymaps:CityState>Berkeley, CA</ymaps:CityState> <ymaps:Zip>94710</ymaps:Zip> <ymaps:Country>US</ymaps:Country> </item> <item> <title>Barnes & Noble Booksellers</title> <link>http://local.yahoo.com/details?id=21414999&stx=&csz=El+Cerrito+CA&ed=Fo51gq160Sy24fPx_u7IvyZen3kxQq5wR9ZOi_Aos2J.pPlJ75D_th3K2MHtNCWF_V5k_n0q62ssy3I-</link> <description/> <ymaps:Address>6060 El Cerrito Plz</ymaps:Address> <ymaps:CityState>El Cerrito, CA</ymaps:CityState> <ymaps:Zip>94530</ymaps:Zip> <ymaps:Country>US</ymaps:Country> </item> </channel> </rss>
![]() | Tip |
---|---|
You can use the W3C XSLT services to perform online XSLT transformations at
|
Go to the following URL to see the rendition of the location data in version 1 of Yahoo! Maps:
http://api.maps.yahoo.com/Maps/V1/annotatedMaps?appid={app-id}&xmlsrc=http://examples.mashupguide.net/ch13/bookstores.georsss.xml
You can also pass the geocoded RSS 2.0 to the Ajax Yahoo! Maps.[171]
![]() | Caution |
---|---|
If you plan to feed GeoRSS to the Yahoo! Maps APIs, use the Compact W3C Basic Geo encoding since that’s the encoding implied by the documentation for Yahoo! Maps. Moreover, you may find the error messages from the Yahoo! Maps Simple API to be rather terse. I have found using Feedvalidator.org to be useful in debugging my GeoRSS. |
Virtual Earth also has the capacity to handle GeoRSS files using any of the four encodings, according to this:
http://dev.live.com/virtualearth/sdk/Ref/HTML/WorkingWithLayers.htm
Now we should be able to feed that file to Virtual Earth. Making a slight modification to some sample code[175][176]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title></title> <meta ?http-?equiv="Content-Type" content="text/html; charset=utf-8"> <script src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=5"> </script> <script> var map = null; var layerid=1; function GetMap() { map = new VEMap('myMap'); map.LoadMap(); } function AddMyLayer(type) { var l = new VEShapeLayer(); var txtSource = document.getElementById('txtSource'); var veLayerSpec = new VEShapeSourceSpecification(type, txtSource.value, l); map.ImportShapeLayerData(veLayerSpec, onFeedLoad); } function onFeedLoad(feed) { feed0 = feed; alert('RSS or Collection loaded. There are '+feed.GetShapeCount()+ ' items in this list.'); } </script> </head> <body onload="GetMap();"> <div id='myMap' style="position:relative; width:400px; height:400px;"></div> <input id="txtSource" type="text" value="flickr.geofeed.xml" name="txtSource"> <input id="loadFeed" type="button" value="Load RSS" onclick="AddMyLayer(VEDataType.GeoRSS);"> </body> </html>
This is available here:
http://examples.mashupguide.net/ch13/virtualearth.flickrgeofeed.v5.html
Keyhole Markup Language (KML) “is an XML grammar and file format for modeling and storing geographic features such as points, lines, images, and polygons for display in Google Earth, Google Maps, and Google Maps for mobile.”[177]
KML has moved beyond its use in Google Earth alone. For instance, you can display KML
files and export search results and one of your My Maps from Google Maps in KML. Other
applications are beginning to support KML. For instance, you can get KML coming out of
Yahoo! Pipes;[178][179][180]<attribution>
element. Google apparently will also index
GeoRSS.
I’ll cover the syntax KML in greater detail in the “Google Earth and KML” section. It’s helpful, nonetheless, to see a simple example of a KML document so that you have something concrete to bounce off of:
<?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://earth.google.com/kml/2.1"> <Placemark id="berkeley"> <name>Berkeley</name> <description>Berkeley, CA</description> <Point> <coordinates>-122.257704,37.8721,0</coordinates> </Point> </Placemark> </kml>
In commenting on the Where 2.0 conference, Benjamin Christen wrote this: “There are two important XML schemas covered today at Where 2.0—GeoRSS and KML.[181][182][183]
There are of course other geodata formats in use, which deserve a look as alternatives to GeoRSS. KML is used in Google Earth, and loads of data layers have been published by an active community. However, KML is very tied to its application, with features specifically aimed for 3D spinny globes, and the spec is controlled by a single organization. GPX, for data interchange between GPS units, is again very tied to specifics of GPS units. GML is a feature-rich vocabulary for encoding geographic information, but its complexity has been daunting for unversed developers and its proper use misunderstood. GML is similar to RDF, defining a number of primitive objects that can be assembled into profiles for particular purposes. In fact, a GML profile for GeoRSS is a result of the new standard.
Not surprisingly, Maron was involved in such interoperability efforts as MGeoRSS, an extension that “integrates basic GeoRSS support directly into Google Maps.”[184]
We’re at a point now that since both GeoRSS and KML are getting a good amount of traction, some good interconversion utilities between them would be timely.
[174] http://www.squarefree.com/shell/, a technique introduced in Chapter 8.
[178] http://blog.pipes.yahoo.com/2007/05/02/pipes-adds-interactive-yahoo-maps-kml-support-and-more/
[182] http://www.ogleearth.com/2006/05/georss_is_here.html is a good summary of some of the issues.