XForms Guide
A guide to XForms processing on NetKernel
Index > Books > Declarative Development Guide > Reference Library > Developer Guides > XForms Guide

Rate this page:
Really useful
Satisfactory
Not helpful
Confusing
Incorrect
Unsure
Extra comments:


Introduction

XForms are a recently ratified W3C recommendation for next generation HTML Forms. XForms provide an abstracted Model-View-Controller pattern for presenting and interacting with the instance data of a form.

XForms were conceived as a predominantly client-side technology. However very few browsers support XForms directly. The NetKernel XForms accessor allows XForms to be deployed as a server-side technology. XForms used on the server-side today will be deployable on the client-side in the future.

The NetKernel XForm module is derived from the Chiba XForms project - thanks to the Chiba team for providing a great XForms model engine.

Model-View-Controller Pattern

The MVC pattern is well known in software development. A model holds instance data which is visialized by a viewer, a controller co-ordinates the interaction between the view and the model.

XForms uses a MVC pattern. The model is an XML document containing instance data, the visualization is provided by a standard HTML form. The controller coordinates the submission of the HTML form data to the model which performs event-based updates to the instance data it holds based upon the submitted form data.

Unlike the traditional HTML form which when submitted is completed, XForms may have mutiple states of completion, checks on the state of the instance data may lead to changes in the view of the form enabling rich interactions between visual form and data to be developed.

Prepare-Execute-Process Pattern

We are not going to cover the details of the XForms syntax or model here. We recommend reading the W3C's XForms for HTML developers guide and refering to a copy of the XForms specification will be useful too. Here we will discuss a simple pattern for using and processing XForms on NetKernel.

The Prepare-Execute-Process pattern was developed in creating the Blogxter XML service blogging application. This is a full-scale application which uses XForms extensively. We recommend examining the source-XML of the mod_blogxter_web module for many examples of XForms used in this pattern.

Like the name suggest the PEP pattern is a three stage process. Preparation involves creating an XForm populating it's initial instance data and storing the stateful XForm in a session. Execution involves posting newly entered form data from the HTML view of the form to the XForm model, the model is updated with the submitted data based upon the XForms rules. If the model has not satisified a completed state a new rendering of the HTML form is returned to the user. If the submitted form data satisfies a completed state of the model the current instance data is submitted to a process for processing.

The NetKernel XForms module provides the XForm accessor which is a Controller of a Chiba XForm model and XSLT form renderer (for the view). Below we show how the XForm accessor can be used to implement a PEP server-side XForm pattern.

Prepare

Below is a simple example XForm. It consists of model with some instance data, in this case a Name-Value-Pair document containing a single element data. The model also contains an xform binding which says that the data element in the instance must start with a capital X (just for example).

<html xmlns:chiba="http://chiba.sourceforge.net/2003/08/xforms" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xml:base="http://localhost:8080/chiba-0.9.2/">
  <head>
    <xforms:model>
      <xforms:submission id="submit" xforms:replace="all" xforms:action="active:dpml+operand@ffcpl:/application/path/form_process_data.idoc" xforms:method="post" />
      <xforms:instance>
        <nvp>
          <data />
        </nvp>
      </xforms:instance>
      <xforms:bind id="data" xforms:nodeset="/nvp/data" xforms:type="string" xforms:required="true()" xforms:constraint="substring( /nvp/data, 1, 1) = 'X'" />
    </xforms:model>
  </head>  <form>    <xforms:group>
      <xforms:input xforms:bind="data">
        <xforms:label>data</xforms:label>
        <xforms:alert>You must enter a value</xforms:alert>
        <xforms:hint>Provide some data here</xforms:hint>
      </xforms:input>
      <xforms:trigger id="submit">
        <xforms:label>Test</xforms:label>
        <xforms:hint>Submit this data</xforms:hint>
        <xforms:action id="login">
          <xforms:send xforms:submission="submit" />
        </xforms:action>
      </xforms:trigger>
    </xforms:group>
  </form>
</html>

Suppose that we initially want the form data value to contain "Xenon". We could prepare the XForm as follows...

<instr>
  <type>stm</type>
  <operand>myXForm.xml</operand>
  <operator>
    <stm:group xmlns:stm="http://1060.org/stm">
      <stm:set xpath="//xforms:instance/nvp/data">Xenon</stm:set>
    </stm:group>
  </operator>
  <target>var:myPreparedXForm</target>
</instr>

Note the XForm standard allows instance data to be included by reference - our current implementation does not yet support this.

We must now create an XForm model in our current session by invoking the XForm accessor. The XForm accessor stores the XForm instance in the session URI passed as the session argument. Since XForms are stateful and HTML is stateless the XForm is persisted in a session resource. See the Session Guide for information on how to create and manage sessions on NetKernel.

<instr>
  <type>XForm</type>
  <xform>var:myPreparedXForm</xform>
  <xslt>/my/application/path/style_myXForm.xsl</xslt>
  <param>
    <null />
  </param>
  <session>this:param:session</session>
</instr>

The XForm is now prepared and ready to be executed. In general the preparation stage is performed as a hidden layer - ie it is a process that is invoked from the browser but which issues a redirect to the execution interface as it's result. The execution interface is the primary public interface for the PEP pattern.

Execution

Execution is the stage were the form is rendered, new data is input, the data is submitted back to the public execution interface and then internally to the XForm model. This stage is repeated until the submitted data conforms with the XForm model.

This whole cycle is achieved with one instruction...

<instr>
  <type>XForm</type>
  <xform>var:myPreparedXForm</xform>
  <xslt>/my/application/path/style_myXForm.xsl</xslt>
  <param>this:param</param>
  <session>this:param:session</session>
  <target>this:response</target>
</instr>

The only difference between the preparation stage and the execution stage is that the externally submitted form data is passed to the XForm accessor in the <param> argument. The XForm accessor updates the XForm model with the param data, finally it styles (view) the XForm with the stylesheet specified by the <xslt> argument. Generally the result of the XForm accessor is returned as the response of the execution process.

Styling

XSLT is used to render the XForm into traditional HTML form elements. Fortunately the Chiba team created an XSLT library for generating the standard form components from an XForm document. We've slightly adapted it so that instead of producing a complete HTML page it generates just an XHTML form. Here's a stylesheet that will render our example XForm...

<xsl:stylesheet xmlns:chiba="http://chiba.sourceforge.net/2003/08/xforms" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xrl="http://1060.org/xrl" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="chiba xforms xlink xsl" version="1.0">
  <xsl:include href="/org/chiba/xslt/form-standard.xsl" />
  <xsl:output encoding="UTF-8" method="xml" />
  <xsl:template match="/">
    <div>
      <xsl:apply-templates />
    </div>
  </xsl:template>  <xsl:template match="form">    <style type="text/css"> input[title="Provide some data here"] {font-weight: bold;} </style>
    <xsl:call-template name="build-form">
      <xsl:with-param name="action-uri" select="'/blogxter/myblog/edit'" />
    </xsl:call-template>
  </xsl:template>
</xsl:stylesheet>

The XSLT must xsl:include the /org/chiba/xslt/form-standard.xsl which is our modified wrapper around the chiba xslt library. We have added a single parameter named action-uri to the call to the build-form template. action-uri specifies the URI to which the form will POST it's data when submitted. This URI should always be the URI of the XForm Execution. An XForm on NetKernel never posts directly to another public URI for processing, all processing is mediated by the Execution controller - this makes Form processing very secure since no public interface is exposed only a completed XForm model can access the internal process (For an example of why this is very valuable examine the AntiSpam Comment XForm in the Blogxter Application).

Processing

As discussed in the Styling section the instance data of a completed XForm is not submitted to a publicly exposed interface. Instead the XForm controller calls the internal processing URI interface with the instance data as parameter. The processing URI is specified in the XForm model in an xform:action attribute of an xform:submission. In the example above it is an active: URI request to execute another idoc. The idoc will be invoked with the completed XForm instance data as it's parameter. The result of the processing stage will be returned as the result of the XForm accessor. Generally the processor's result is a redirect to another HTTP address.

Debugging and Logging

A good way to identify and solve problems with running an XForm under Chiba or indeed a problem with Chiba itself, is to view the generated log files. By default the logging output generated by the Chiba library (with Log4j) is written to the NetKernel log directory in a file named XFormsURAlog4j.log. As shipped, the XForms URA has the logging level set to INFO which produces a moderate amount of detail in the output. To debug problems with your XForms running with Chiba or to reduce the level of detail output to the log file you will need to change Chiba's Log4j logging level. To do this, firstly you will need to unpack the XForms module to a directory, modules/ext_xforms-1.2.0 for example and edit the log4j.xml file, making the required changes, such as setting the priority value to DEBUG or SEVERE. Secondly, you will need to edit NetKernel's etc/deployedModules.xml file and change the reference to /modules/ext_xforms-1.2.0.jar to the directory where ext_xforms-1.2.0.jar was unzipped, i.e. in this case /modules/ext_xforms-1.2.0/. Cold restarting NetKernel will complete the required changes and the appropriate logging levels will be set.

Conclusion

The PEP pattern is a general server-side pattern for XForm processing. It provides an encapsulated processing interface with a public interface provided by the Execution engine. Very rich form handling processes can be developed with the XForm module.

© 2003-2005, 1060 Research Limited. 1060 registered trademark, NetKernel trademark of 1060 Research Limited.