xefer

Rebel: A RE(ST API for X)BEL

· Thursday, January 17th, 2003 ·

XBEL Schema

I have been building a REST interface for storing bookmarks marked up using the XBEL schema as a sort of counterpoint to Microsoft's Cold Rooster SOAP example. It quickly became obvious however that XBEL, being such a general hierarchical format of folders and bookmarks, could serve as the basis for organizing many types of data. The most immediate one that comes to mind, is allowing for better weblog categorization and production of RSS 2.0 feeds. See below.

I’m interested in getting feedback on the REST interface that I've outlined here. Any comments would be very welcomed.

Sections

The Rebel Interface

The interface is built around the three major elements of XBEL: <xbel>, <folder> and <bookmark>. Folders are stored under URLs that end in “/”, and bookmarks are stored under URLs that do not end in “/”.

The <folder> Element

URL Format

xbel/.../folder-name/

Interface
HTTP MethodDescription
GET Get the folder and it’s children. See below.
POST If a <folder> is POSTed, create a new folder under the given url.
If a <bookmark>is POSTed, create a new bookmark resource under the given url.
If any other entity type is POSTed, it is accepted and made a part of the resource, but no new resource is created.
Note: For the current implementation, all <folder> and <bookmark> elements must contain an id attribute; this is used to produce the url of the new resource. See below.
PUT Create or update the folder at the given url.
If the folder already exists, it will be replaced by the PUT entity; all children of the resource will be replaced by the children of the entity also.
If the parent folder(s) do not exist, they will be created as necessary.
Note: For the current implementation, the value of the id attribute must match the last element of the hierarchical URL name. See below.
DELETEDelete the folder and all it’s children.
OPTIONS Returns an Allow header, as well as metadata specifiying the schema of entities that can be PUT or POSTed.

The <bookmark> Element

URL Format

xbel/.../folder-name/bookmark-name

Interface
HTTP MethodDescription
GET Get the bookmark.
POST Accepts the entity and includes it under the bookmark, but no resource is ever created.
PUT Create or update a bookmark at the given url. If the parent folders do not exist, they will be created also, as necessary.
Note: For the current implementation, the value of the id attribute must match the last element of the hierarchical URL name. See below.
DELETEDelete the bookmark and all it’s children.
OPTIONS Returns an Allow header, as well as metadata specifiying the schema of entities that can be PUT or POSTed.

The <xbel> Element

URL Format

xbel or xbel/

Interface

The <xbel> element is handled exactly the same way as the <folder> element, except that the <xbel> element can be referenced with or without the trailing “/”, other than that its behavior is the same.


The <title>, <desc>, <info> and <metadata> Elements

Interface

All these elements are common to the folder, bookmark and XBEL document elements. They are semantically rich but they are not themselves addressable resources. Any of these elements can be POSTed to the XBEL element that they are describing, but they do not return a resource location.


The <alias> and <separator> Elements

Interface

These elements are common to the folder and XBEL document elements. They are semantically rich but they are not themselves addressable resources. Any of these elements can be POSTed to the XBEL element that they will be included with, but they do not return a resource location.

It really doesn't make much sense to POST a <separator> element to it’s parent as it will simply be appended to the list of children. If seperators are need, the parent should be edited by the client and then PUT.

Open Issues

A note on ids

As discussed in the interface section above, this implementation currently requires the use of the “id” attribute which is defined as optional in the XBEL schema. While it would have been possible to use the title element to construct a URL, the results would often times would have been a grim looking URL, e.g., /The%20New%20York%20Times, as opposed to /nytimes.

I would be grateful for any ideas on how to deal with this situation. One idea that I had was to allow for both, but have a URL based on the title issue a 301 redirect to the id if one exists.

A note on hierarchy

Currently the API is defined as such that performing a GET on a folder returns the full tree that it parents. When I was thinking about this application strictly in terms of bookmarks that hardly seemed to be a terrible concern as the file wouldn’t as a general rule be particularly huge. If however the file began to contain verbose description contents as it could if it were supporting, say, the content of a weblog, this could quickly become unwieldy. While it wouldn't necessarily happen that often, having to GET then PUT a large block of bytes just to manipulate the content on a resource high up the hierarchy could be an issue.

I've decided the way to handle this is to expose a different resource-space for dealing with the XBEL information as a collection of “flat” resources. The url structure and API will be the same except for the /xbel “root” element. Instead the top level will be:

xbel-flat or xbel-flat/

And format will contain xlink references to it’s children, e.g.:


  <folder id="standards" xmlns:xlink="http://www.w3.org/1999/xlink">
    <title>Standards Documents</title>
    <info>
      <metadata owner="Jeffrey Winter">
    </info>
    <description>A collection of information about standards</description>
    <bookmark xlink:href="servlet"/>
    <folder xlink:href="rfcs"/>
    <folder xlink:href="w3c"/>
    <bookmark xlink:href="xbel"/>
    <separator/>
    <bookmark xlink:href="rss"/>
  </xbel>
        
A note on exports

Currently this API deals with fragments of XBEL documents; when an entity is requested via GET it returns just the element requested, which except for the case of the root <xbel> element is not strictly a conformant XBEL document, i.e., it would not validate against the XBEL DTD.

To deal with this issue, there will be another resource-space that returns strictly XBEL conformant XML documents. This will be a read-only (i.e., GET-only) interface for possibly sharing folders. The url structure will be the same except for the /xbel “root” element. Instead the top level will be:

xbel-export or xbel-export/

Implementation

This current implementation is written for a Servlet 2.3 servlet engine (such as Tomcat 4.x.) It uses Xerces and Xalan for XML manipulation. For client-side testing, I use cURL.

This implementation is also written such that it manipulates and stores the document as a single XML document. This is clearly less than optimal but it works well as a simple way to work with the REST interface to help clarify it from a design perspective. I’ve isolated most of the XML machinery so that a version that works with a directory structure or a database should be a relatively straight-forward implementation of a base interface. My plan is to work on that refactoring after hearing any feedback, etc.

XBEL vs. RSS?

It struct me after looking at the RSS 2.0 format, that XBEL could easily be used for managing weblog content—with the <bookmark> element corresponding to the RSS <item> element. The XBEL could easily be transformed into RSS, and might offer a better way of storing, organizing and categorized a weblog and its feeds because of its hierarchical schema.

The basic idea is that you POST directly to a specific category, or PUT to an item in a specific category for the content. It makes more sense to POST an entry to:

http://www.xefer.com/xbel/code/java/

or PUT an entry to:

http://www.xefer.com/xbel/code/java/javastory

With the <alias> element, these items can be referenced in numerous ways; for example, there could be a daily feed at the folder

http://www.xefer.com/xbel/current

POST an <alias> element that references a new item that had been stored under a specific category in context. The daily RSS feed would be a <folder> with just a list of <alias> s.

When it’s time to archieve a month’s worth of items, obtain the current folder, PUT it to a folder /xbel/2003/01, remove the contents of the current folder and PUT it back to /xbel/current.

To actually support the RSS feed itself, a different root folder (handled by a different servlet for example) would be employeed that dereferenced the XBEL feed and performed a transformation on the response. So there would be two corresponding URL bases:

http://www.xefer.com/xbel/
http://www.xefer.com/rss/

Of course, the same idea could be used to produce other types of content, HTML or whatever.

This seems a better way to organize data than having an entry with, say, a <category>code/java<category> element imbedded somewhere within it and POSTing it to:

http://www.xefer.com/xbel

RSS 2.0 does have a <category> element, but it is tucked into the <item> element in a way that models a URL’s hierarchical format but without actually exposing it.

RSS 2.0 does of course allow multiple <category> elements, and this is perhaps one issue with the XBEL approach: With XBEL, the categories themselves would have to reference the elements they don't directly own with <alias> elements. Essentially, both RSS 2.0 and XFML provide a child→parent relationship from the item to the category; XBEL being purely hierarchical has only a parent→child relationship expressed explicitly through containment. Any other relationships require the an <alias> element.

archive

topics

projects

feed