OpenLayers Atom

I mentioned a Format/Atom.js file in the previous post. I've overhauled some older code so that it conforms almost completely to RFC 4287 and submitted a patch for OpenLayers: #1366. Download it into a buildout and you can patch it into the latest and greatest OpenLayers like this:

[buildout]
parts = openlayers-format-atom

[openlayers-format-atom]
recipe = zgeo.recipe.openlayers
url = http://openlayers.org/download/OpenLayers-2.8-rc5.tar.gz
patches =
    format-atom.patch
include =
    OpenLayers/Format/Atom.js

The format's tests give a pretty good overview of its capabilities:

// write entry 6: Atom links
function test_Format_Atom_writeentry6(t) {
    t.plan(1);

    // Feature attributes in Atom namespace
    var atomAttrib = {
          title: "Atom test",
          summary: "An Atom testing feature",
          updated: "2009-06-02T10:00:00Z",
          links: [
            { href: "http://example.com/blog/1", rel: "alternate" }
            ]
          };

    var fx = new OpenLayers.Feature.Vector(null, {atom: atomAttrib});
    fx.fid = 'urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed';

    var writer = new OpenLayers.Format.Atom();
    var data = writer.write(fx);

    t.xml_eq(
      data,
      // begin document
      '<entry xmlns="http://www.w3.org/2005/Atom">'               +
      '<id>urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed</id>'    +
      '<link href="http://example.com/blog/1" rel="alternate"/>'  +
      '<summary>An Atom testing feature</summary>'                +
      '<title>Atom test</title>'                                  +
      '<updated>2009-06-02T10:00:00Z</updated>'                   +
      '</entry>',
      // end document
      'Writes an entry doc with Atom constructs and links'
      );
}

// write out point -- just enough to see that we're getting the
// georss:where element with a Point. We'll trust GML.v3 to get the
// details right.
function test_Format_Atom_writepoint(t) {
    t.plan(1);

    var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
    var fx = new OpenLayers.Feature.Vector(point, {});
    fx.fid = 'urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed';

    var writer = new OpenLayers.Format.Atom();
    var data = writer.write(fx);

    t.xml_eq(
      data,
      // begin document
      '<entry xmlns="http://www.w3.org/2005/Atom">'                 +
      '<id>urn:uuid:82ede847-b31a-4e3d-b773-7471bad154ed</id>'      +
      '<title>undefined</title>'                                    +
      '<georss:where xmlns:georss="http://www.georss.org/georss">'  +
      '  <gml:Point xmlns:gml="http://www.opengis.net/gml">'        +
      '    <gml:pos>45.68 -111.04</gml:pos>'                        +
      '  </gml:Point>'                                              +
      '</georss:where>'                                             +
      '</entry>',
      // end document
      'Writes an entry doc with a point location'
      );
}

The patch brings a few new constructs to OpenLayers: Atom categories, persons, and links as javascript objects. The latter have been expressed before in Subbu's blog (http://www.subbu.org/blog/2008/10/generalized-linking), and the former follow. An atom namespace is introduced into a features attributes object to minimize collisions or confusion with other formats (link in GeoRSS.js).

Writing a feature to Atom format is the hard part. Posting to an AtomPub service is easy. With jQuery:

var entry = new OpenLayers.Feature.Vector(geom, data);
var writer = new OpenLayers.Format.Atom();

$.ajax({
    async: false,
    type: "POST",
    url: $("link[rel=service]").attr("href"),
    data: writer.write(entry),
    processData: false,
    success: function(msg) {
        alert( "Data Saved: " + msg );
    },
    beforeSend: function(req) {
        req.setRequestHeader("Slug", slug);
    }
});