Data Exchange Formats

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

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

Microformats and Metatags for HTML

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]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 adr example.

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

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>
         

Yahoo!’s Use of GeoRSS and Yahoo! YMaps Extensions

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):

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]

http://api.maps.yahoo.com/Maps/V1/annotatedMaps?appid=YahooDemo&xmlsrc=http://developer.yahoo.com/maps/sample.xml

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&amp;stx=&amp;csz=Berkeley+CA&amp;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&amp;stx=&amp;csz=Berkeley+CA&amp;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 &amp; Noble Booksellers</title>
         <link>http://local.yahoo.com/details?id=21414999&amp;stx=&amp;csz=El+Cerrito+CA&amp;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]Tip

You can use the W3C XSLT services to perform online XSLT transformations at http://www.w3.org/?2001/05/xslt and http://www.w3.org/2005/08/online_xslt/ (for XSLT 2.0).

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]

  1. Adapt code from one of the Yahoo! examples[172][173]

  2. Bring up that example. Invoke the JavaScript Shell on it,[174]

    map.addOverlay(new YGeoRSS('http://examples.mashupguide.net/ch13/bookstores.georsss.xml'));
                    
[Caution]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.

GeoRSS in Virtual Earth

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

KML

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>
         

Interoperability Among Formats: GeoRSS vs. 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.

[182] http://www.ogleearth.com/2006/05/georss_is_here.html is a good summary of some of the issues.