getting started with eXist

If you haven't had the opportunity to do so yet, pop on over to the eXist website and check out their wares.

eXist is an open-source native XML database. Aside from being free, eXist offers a great little playground for developing XML-based applications. It supports XQuery, XPath, XSLT and SOAP just to name a few.

The main benefit to using eXist is the powerful support for XQuery. Entire applications can be developed just using XQuery Language on the back end. These can then be surfaced using your front-end development environment of choice.

To demonstrate just how easy it is, we'll run through a little app I knocked up in a few minutes to manage a list of albums.

Starting with a sample XML file that looks something like:

albums.xml

  <albums>
    <album>
      <id>000001</id>
      <title>The Essential Hank Williams Collection: Turn Back the Years</title>
      <artist>Hank Williams</artist>
      <label>Mercury</label>
      <year>2005</year>
    </album>
    <album>
      <id>000002</id>
      <title>The College Dropout</title>
      <artist>Kanye West</artist>
      <label>Roc-a-Fella</label>
      <year>2004</year>
    </album>
    ...
    ...
  </albums>
      
We can start writing some code to perform specific functions. The functions we will need are:
  • Getting a list of albums,
  • Adding a new album,
  • Deleting an album, and,
  • Updating an album's data

Starting with the easy stuff, let's look at returning a list of albums:

getAlbumList.xql

        declare namespace xdb="http://exist-db.org/xquery/xmldb";
        let $AlbumList := doc("xmldb:exist:///db/interviewtest/albums.xml")
        return $AlbumList
      
Yep, that's it. Three lines, one of which is just a namespace declaration. Get the XML document we're after, return it to the client. How many times have you spent ages stepping through each record in a dataset, carefully wrapping tags around each field?

Ramping it up a little, let's have a look at the insertion code:

addAlbum.xql

  declare namespace request="http://exist-db.org/xquery/request";
  declare namespace xdb="http://exist-db.org/xquery/xmldb";

  let $title	:= request:get-parameter("title","Unknown Title")
  let $artist	:= request:get-parameter("artist","Unknown Artist")
  let $label	:= request:get-parameter("label","Unknown Label")
  let $year	:= request:get-parameter("year","0000")


  let $AlbumList  := doc("xmldb:exist:///db/interviewtest/albums.xml")

  let $lastID := xs:integer($AlbumList//album[last()]/id)
  let $newID  := concat(string-pad("0",6 -string-length(xs:string($lastID + 1)))
                                      ,xs:string($lastID + 1))

  let $NewAlbum	:=  <album>
                      <id>{$newID}</id>
                      <title>{$title}</title>
                      <artist>{$artist}</artist>
                      <label>{$label}</label>
                      <year>{$year}</year>
                    </album>

  let $insert := update insert $NewAlbum into $AlbumList/albums

  return  <result>
            <status>1</status>
            <message>Record added successfully</message>
          </result>
        
Again, not a great deal to it. Declare the neccessary namespaces, read in the parameters from the request - giving them some default values if they don't exist, generate a new ID for the record, wrap it all up in an XML node, insert it into the document and return a status message to the client.

The rest of it doesn't get a great deal more complex. The deletion code:

deleteAlbum.xql

          declare namespace request="http://exist-db.org/xquery/request";
          declare namespace xdb="http://exist-db.org/xquery/xmldb";

          let $id 	:= request:get-parameter("id","")

          let $AlbumList := doc("xmldb:exist:///db/interviewtest/albums.xml")

          return
            if ($id != "") then (
              let $Album := $AlbumList//album[id = $id]
              let $result := if ($Album) then (
                  let $update := update delete $Album
                  return  <result>
                            <status>1</status>
                            <message>Record deleted successfully</message>
                          </result>
                ) else (
                  <result>
                    <status>-1</status>
                    <message>invalid id specified or no album retrieved</message>
                  </result>
                )
              return $result

            ) else (
                <result>
                  <status>-1</status>
                  <message>No id specified</message>
                </result>
            )
        
Simply reads in the supplied album id and, if found in the collection, deletes it, otherwise it returns one of two error messages. Likewise the update code:

updateAlbumData.xql

  declare namespace request="http://exist-db.org/xquery/request";
  declare namespace xdb="http://exist-db.org/xquery/xmldb";

  let $id 	:= request:get-parameter("id","")
  let $title	:= request:get-parameter("title","")
  let $artist	:= request:get-parameter("artist","")
  let $label	:= request:get-parameter("label","")
  let $year	:= request:get-parameter("year","")

  let $AlbumList := doc("xmldb:exist:///db/interviewtest/albums.xml")

  return if ($id != "") then (
    let $Album := $AlbumList//album[id = $id]
    let $result := if ($Album) then (
      let $update := if ($title != "") then (
        update value $Album/title with $title
      ) else ( )
      let $update := if ($artist != "") then (
        update value $Album/artist with $artist
      ) else ( )
      let $update := if ($label != "") then (
        update value $Album/label with $label
      ) else ( )
      let $update := if ($year != "") then (
        update value $Album/year with $year
      ) else ( )

      return <result>
        <status>1</status>
        <message>Record updated successfully</message>
      </result>
    ) else (
      <result>
        <status>-1</status>
        <message>invalid id specified or no album retrieved</message>
      </result>
    )
    return $result
    
  ) else (
    <result>
      <status>-1</status>
      <message>No id specified</message>
    </result>
  )
        
Just walks through the supplied paramaters and inserts their value into the requested album.

OK, so there's the framework. Obviously you'd want to put some validation and security around it before selling to a customer (you would put validation and security on an application before selling it to a customer wouldn't you?) but it's pretty much done. If only everything were that easy.

Gabriel J. Buckley's Facebook profile
My status