REST interfaces to online resources are becoming more and more common. Yet it remains more difficult than it ought to be, at least in my experience, to make our development tools talk to them. Here’s how to make Cocoon GET from and POST to the REST interface of the XML database eXist; the same method would apply to Solr or any other RESTful resource.

GET is easy: the file generator accepts a url, from which it will draw the XML that gets pumped through the pipeline. For other verbs we need another solution. If we were POSTing name-value pairs, the CInclude transformer would do the trick; but when we need the body of the request to be a block of XML, we need the Webdav transformer. For some reason it isn’t included in the Cocoon documentation except in javadoc; but examples of its use are found in the Webdav block samples. It is part of the Webdav block, so you must have enabled this block in your Cocoon build to use it.

First, declare some global variables in the sitemap, for convenience:

<existpath>localhost:8888/exist/webdav/db/test</existpath>
<existuser>root</existuser>
<existpassword>xxxxxxx</existpassword>

A pipeline to post a bunch of documents from documents.xml looks like this:

<map:match pattern="populate">
  <map:generate src="path/to/documents.xml" label="content"/>
  <map:transform src="xsl/documents2webdav.xsl" label="step1">
    <map:parameter name="existpath" value="{global:existpath}"/>
  </map:transform>
  <map:transform type="webdav">
    <map:parameter name="username" value="{global:existuser}"/>
    <map:parameter name="password" value="{global:existpassword}"/>
  </map:transform>
  <map:serialize type="xml"/>
</map:match>

Let’s suppose that each document has an id attribute, which we want to use as the file name in eXist. The documents2webdav.xsl stylesheet should have a template like this:

<xsl:template match="document">
  <request xmlns="http://cocoon.apache.org/webdav/1.0" xmlns:d="DAV:" target="webdav://{$existpath}/documents/{@id}.xml" method="POST">
    <header name="Content-type" value="text/xml; charset=UTF-8"/>
    <body>
      <xsl:copy-of select="."/>
    </body>
  </request>
</xsl:template>

The output contains instructions to the Webdav transformer (which looks for elements in the Cocoon Webdav namespace) to POST each document into a file in the eXist database. The other HTTP and Webdav methods, such as PUT and DELETE, are available. It is easy to build these steps into the success pipeline for a Cocoon Form, for example, so that the edited content of the form can be stored via a REST interface.