SimpleXist III

Last time, we finished with a working example on a small XQuery engine based on a simplified eXist install called, unimaginatively, SimpleXist. Now we could leave it there as it’s true that you can write a whole application with just the database and XQuery. However, once forms are involved, it’s so much easier to use XForms rather than native HTML which is of course also the front bit of the XRX architecture. In our case we use XSLTForms to do our XForms on the client side, although there are also good ways to do it server-side with something like BetterForms.

Note: I’m not getting into a XForms / XRX how-to just now. There are numerous resources such as Dan McCreary’s XRX Beginners Guide and there is an excellent WikiBooks XForms section to name but two you can read if unfamiliar with the topic.

Now with our initial project, we used a transform to render the output page at the end of each XQuery. This is a pretty useful idiom and we’d want to keep it going with our XForms. This means that our XSL style sheet needs modifying so that it can cope with two sorts of input, straight xml and xforms.

Simple XForm

Before we can do anything we need the XSLTForms software from the agenceXML site. Download it and put it in /ROOT/resources folder as this probably isn’t the only project that’s going to use it! They also have a simple HelloWord XForm on their site we’ll use as a template. Have a look at the source; what we’re going to do is make that work in SimpleXist. So, first off, create a hello.xql in /project1 and copy in the following:

xquery version "1.0";
declare namespace transform=""; 
declare option exist:serialize "method=xhtml media-type=text/xml indent=yes"; 
let $input := 
<document xmlns:xf="">

  <title>Hello World in XForms</title>
        <PersonGivenName />

<p>Type your first name in the input box.<br />
If you are running XForms, the output should be displayed in the output area.

<xf:input ref="PersonGivenName" incremental="true">
  <xf:label>Please enter your first name: </xf:label>

<xf:output value="concat('Hello ', PersonGivenName, '. We hope you like XForms!')">
<xf:label>Output: </xf:label>

transform:transform($input, "styles/style.xsl", ())

There are a couple of things to note here. First, we’re returning text/xml as the mime-type rather than text/xhtml as that’s what triggers the XForms XSL transform on the client. Next, we’ve got a namespace in our document section, and lastly, we’ve now got a separate <header> element in our XML as the <xf:model> parts of the form need to go in the HTML <head> element in the output.

Now if you try to run it at localhost:8080/project1/hello.xql , nothing interesting happens as we don’t have the XSLT to support it: that’s next.


First off, copy this style.xsl over the one in /project1/styles. It’s a small addition to find out if we’re in an XForm or not and send the right processing-instructions back. This is done by testing for xf:model in the header. Note that we’ve used /resources/xsltforms.xsl as we’re using the /ROOT/resources folder.

<xsl:if test="document/header/xf:model">
<xsl:processing-instruction name="xml-stylesheet">
<xsl:processing-instruction name="css-conversion">
<xsl:processing-instruction name="xsltforms-options">

We can also set other specific XSLTForms directives in here, such as setting support for ordinary css files and turning off debug. Using this code, the standard XQuery will be returned as before and the XForms version with appropriate processing instructions.

Now if you run the hello.xql file again you should get a working XForm!

Next steps: HerdBook

Now we’ve a set-up that’s simple, works with XQueries on the file system and supports XForms. Next stop a personal project to exercise the setup a bit more fully. I’ve been looking to scratch this itch for a while – I need a Herd Book. This is a database of all the llamas and alpacas we have, matings, medicines we’ve given them, shows they’ve been to and results. In short everything we have currently written in various calendars, notebooks and a set of index cards. It’s way overdue!