X Hits The Spot
A year or two ago, XML was heard about more often than it was seen, a technology that was sufficiently arcane enough to keep all but the most hardened geeks at bay. No more is this the case; today, XML is most definitely in the mainstream, and proving its mettle by making all kinds of new and unique applications possible (witness the success of Amazon.com’s AWS service, or the Google APIs, both based on XML technology).
XML isn’t resting on its laurels, though. As the technology is becoming more and more popular, XML development groups operating under the aegis of the World Wide Web Consortium are rapidly inventing new and interesting ways to use it. One of the more interesting ideas is XForms, which uses XML to manage the display, input and processing of user-inputted data on the Web.
If you’re at all serious about using XML, you’re going to need to understand XForms. And over the course of this tutorial, I’m going to assist you in this endeavour by explaining the fundamentals of the XForms data model, together with some examples of how it can be used.
Before we get going, though, a few disclaimers:
First, I don’t claim to be an expert on XForms. Much of the material in this tutorial is based on my own research with the XForms specifications and varied XForms implementations, or gleaned from late-night email conversations over beer and stale pizza. In other words - caveat emptor!
Second, as new XML standards are proposed and disposed, the material here may become invalid; you should always refer to the most current standard or recommendation for up-to-date information. This tutorial is based on the W3C’s XForms 1.0 recommendation dated 14 October 2003, at http://www.w3.org/TR/2003/REC-xforms-20031014/
Now that I have that off my chest - let’s get started!
Out With The Old…
Before getting into the details of how XForms works, it’s important to understand the context in which it was developed, and the need and rationale behind it.
You know that HTML already allows user interaction with a Web application, through the use of forms and associated form controls like text entry fields, checkboxes and radio buttons. However, although HTML forms are simple to understand and easy to use, they do have a couple of drawbacks:
-
HTML forms can usually be viewed (and used) only in a Web browser - they don’t render too well on handhelds, cellphones or other devices.
-
Processing form input in the Web world usually requires the services of a programmer, who must code the business logic need for form data validation, input parsing and further data manipulation and processing.
-
Unless you put in a great deal of thought at the design stage (and sometimes not even then), HTML forms cannot be easily reused across different applications, or even within an application.
These drawbacks might seem trivial in the context of today’s Internet - it ain’t broke, you’re probably thinking, so why fix it? - but they assume serious proportions in the context of an XML world, which is built around data and the relationships inherent in it.
…In With The New
XForms was designed to address these drawbacks, and also breathe fresh life into traditional approaches to handling user input in a client-server paradigm.
If you take a look at the requirements document for XForms - it’s available online at http://www.w3.org/TR/xhtml-forms-req - you’ll see that XForms was designed to enable the “separation of the data being collected from the markup of the controls collecting the individual values”. Right at the outset, then, the XForms specification makes a clear distinction between the form model (what the form does) and its controls (what it looks like).
A simple example of this might be a form which asks for your gender - in a Web browser, you’d be presented with radio buttons or a drop-down list, while on a cellphone, you’d be asked to enter a particular number corresponding to the choices. This distinction between form (no pun intended) and function makes it possible to use a single form model on multiple platforms and devices, by defining what the form is supposed to do once, and then further defining the user interface for each device or platform to be supported separately.
XForms also come with built-in data typing capabilities and event handlers, making it possible to validate user input without having to resort to complex scripting or server-side business logic. XForms can even be integrated with the validation rules laid down in XML Schemas, to further centralize application logic and reduce the impact of changes in business rules.
Another good thing about XForms, especially as we move to a more XML-centric world, is its native support for the XML standard. Data entered into an XForm is usually submitted to the receiving application in XML format. This simplifies integration with third-party tools (which are gradually becoming XML-aware) and also reduces the need for complex data processing and manipulation routines, as the submitted data can easily be parsed using standard SAX or DOM interfaces.
There’s only one problem - while the theory is certainly exciting, practical implementation still leaves a lot to be desired. The W3C’s XForms site at http://www.w3.org/MarkUp/Forms/ lists a number of different XForms implementations, but the technology has yet to make an appearance in any popular browser; this makes it harder to test and research.
Of the different implementations available, the examples in this tutorial were tested with FormsPlayer (http://www.formsplayer.com/), though you will also get good results with X-Smiles, a Java browser (http://www.x-smiles.org/) and Novell’s XForms (http://www.novell.com/xforms). Expect to spend some time with the documentation for each of these implementations to get your XForms development environment up and running (tip: I found FormsPlayer to be the simplest to install, as it integrates directly with Internet Explorer 6.0)
What’s In A Name?
Let’s start with a simple example that demonstrates the functionality of XForms.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xforms="http://www.w3.org/2002/xforms/cr">
<head>
<!-- define the form model -->
<xforms:model id="enter">
<xforms:instance>
<user>
<name />
</user>
</xforms:instance>
</xforms:model>
<basefont face="Arial">
</head>
<body>
<font size="+1">What's In A Name?</font><br /><br />
<!-- define the form interface -->
<xforms:input id="txtname" model="enter" ref="/user/name">
<xforms:label>Name</xforms:label>
<xforms:hint>Enter your name, then press TAB</xforms:hint>
</xforms:input>
<br />
<!-- do something with the input -->
Welcome to XForms, <xforms:output model="enter" ref="/user/name" />
</body>
</html>
Let’s look at this line by line.
The first basic rule when dealing with XForms is that they cannot exist as independent entities; instead, they’re designed to be integrated with XHTML (or other markup) documents. That’s why the XForm above is enclosed within a regular XHTML document, and why the XHTML namespace has been referenced at the top.
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xforms="http://www.w3.org/2002/xforms/cr">
...
</html>
Note that in addition to the XHTML namespace, when dealing with XForms, you’ll also need to specify the XForms namespace, which is currently “http://www.w3.org/2002/xforms/cr”.
<!-- define the form model -->
<xforms:model id="enter">
...
</xforms:model>
The second basic rule when working with XForms is this: every XForm consists of two primary components, a form model (which specifies functionality) and one or more form controls (which handles presentation).
The form model, indicated by the <xforms:model>
element, defines what the form does. This model defines the data to be captured/modified by the form as well as the logical components that govern how the form behaves on user interaction (including where the form should be submitted and how to handle the various form events). The model also includes information on the bindings between the form controls and the instance data, and can optionally link to external XML Schemas for validation purposes.
The <xforms:model>
element is usually accompanied with an “id” attribute, which contains a name for the model; this name is used by the form controls in order to link the interface section of the form to the correct form model. Obviously, this also means that you can have multiple models with a single XHTML file, and link to each one by its name. Additionally, since the form model only defines how the form works and has nothing to do with its presentation, it can easily be reused, either within the same application or in other applications or platforms.
Typically, the <xforms:model>
element appears within the <head>
of the document, and encloses an <xforms:instance>
element.
<!-- define the form model -->
<xforms:model id="enter">
<xforms:instance>
<user>
<name />
</user>
</xforms:instance>
</xforms:model>
The <xforms:instance>
element defines the “instance data” for the form. This instance data is an XML tree representation of the values associated with the form, and it can be defined inline (as above) or imported from an external XML file. In this case, the XML structure is pretty simple - a single root element called <user>
encompassing one child element called <name>
.
Normally, the <xforms:model>
element would also contain information on where the form is to be submitted via the <xforms:submission>
element, data bindings via the <xforms:bind>
element and event handlers via the <xforms:action>
element - I’ll be discussing those shortly, so don’t worry too much about them for the moment.
Once the form model has been defined, it’s time to define the other half of the puzzle - the form controls, or how the form looks. XForms provides a bunch of elements to accomplish this - by and large, they map neatly into the HTML form controls you’re already familiar with, and appear within the <body>
of the document.
<!-- define the form interface -->
<xforms:input id="txtname" model="enter" ref="/user/name">
<xforms:label>Name</xforms:label>
<xforms:hint>Enter your name, then press TAB</xforms:hint>
</xforms:input>
The first (and simplest) of these controls is the <xforms:input>
element, which represents a text entry field. Note my use of the “model” attribute to tell the XForms processor which form model this control belongs to, and the “ref” attribute to tell it which node in the instance data tree this particular value maps to. XPath expressions are used in the latter - in case you don’t know what those are, take a look at https://www.melonfire.com/archives/trog/article/xpath-basics and they should make a little more sense to you.
<!-- do something with the input -->
Welcome to XForms, <xforms:output model="enter" ref="/user/name" />
Another useful (though not often used) form control is the <xforms:output>
element, which is used to display the value of a particular node from the XML instance data tree. Note again my usage of the “model” and “ref” attributes to link the control to the model and instance data tree defined in the <head>
of the document.
If you were to try viewing the XForm above in an XForms-capable browser, you’d see something like this:
Pretty cool, huh?
Welcome To Nowhere
The previous example demonstrated two of the form controls available in XForms. However, there are lots more - here’s a brief list:
<xforms:input> a single-line text entry field
<xforms:secret> a single-line text entry field which masks user input, good for passwords
<xforms:select> a list field allowing multiple selection
<xforms:select1> a list field allowing selection of only a single item from the list
<xforms:textarea> a multi-line text entry field
<xforms:upload> a file upload field
<xforms:range> a field which restricts entry to a range of values
<xforms:submit> a form submission field
<xforms:output> a field for displaying values from the instance data
In addition, the XForms specification also defines the following elements, which may be attached to the controls above:
<xforms:label> descriptive information for the corresponding control
<xforms:help> help information for the corresponding control
<xforms:hint> brief usage information for the corresponding control
Here’s an example demonstrating some of them in action:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xforms="http://www.w3.org/2002/xforms/cr">
<head>
<!-- form model -->
<xforms:model id="immigration">
<xforms:instance src="immigration.xml" />
</xforms:model>
<basefont face="Arial">
</head>
<body>
<!-- define interface controls -->
<table cellspacing="5" cellpadding="5" border="0">
<tr>
<td colspan="2" align="center"><font color="red" size="4">Welcome to Immigration</font></td>
</tr>
<tr>
<td>
<xforms:input id="txtname" model="immigration" ref="/immigrant/name">
<xforms:label>Name</xforms:label>
<xforms:hint>Enter your name here</xforms:hint>
</xforms:input>
</td>
</tr>
<tr>
<td>
<xforms:input id="txtcitizenship" model="immigration" ref="/immigrant/citizenship">
<xforms:label>Citizenship</xforms:label>
<xforms:hint>Enter your country of origin here</xforms:hint>
</xforms:input>
</td>
</tr>
<tr>
<td align="left">
<xforms:select1 model="immigration" ref="/immigrant/purpose" appearance="full">
<xforms:label>Purpose of visit</xforms:label>
<xforms:hint>Please state the purpose of your visit</xforms:hint>
<xforms:item>
<xforms:label>Business</xforms:label>
<xforms:value>B</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Pleasure</xforms:label>
<xforms:value>P</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Other</xforms:label>
<xforms:value>O</xforms:value>
</xforms:item>
</xforms:select1>
</td>
</tr>
<tr>
<td align="left">
<xforms:select model="immigration" ref="/immigrant/immunization" appearance="full">
<xforms:label>Immunization</xforms:label>
<xforms:hint>Please select the diseases that you have been immunized against</xforms:hint>
<xforms:item>
<xforms:label>Smallpox</xforms:label>
<xforms:value>100</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Malaria</xforms:label>
<xforms:value>113</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Yellow fever</xforms:label>
<xforms:value>56</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Typhoid</xforms:label>
<xforms:value>174</xforms:value>
</xforms:item>
</xforms:select>
</tr>
<tr>
<td align="left">
<xforms:textarea model="immigration" ref="/immigrant/address">
<xforms:label>Address in home country</xforms:label>
</xforms:textarea>
</td>
</tr>
</table>
</body>
</html>
First up, the definition of the XForms model. Unlike the previous example, I’ve defined the instance data tree in a separate file and imported it via the “src” attribute.
<!-- form model -->
<xforms:model id="immigration">
<xforms:instance src="immigration.xml" />
</xforms:model>
<basefont face="Arial">
Here’s what “immigration.xml” looks like:
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- immigration.xml -->
<immigrant>
<name />
<citizenship />
<purpose />
<immunization />
<address />
</immigrant>
You’ve already seen how to use an <xforms:input>
element in previous examples, so I won’t go into the details again. Do note, however, my usage of the <xforms:label>
and <xforms:hint>
elements within it - these come in handy to provide descriptive human-readable information about the control.
<xforms:input id="txtname" model="immigration" ref="/immigrant/name">
<xforms:label>Name</xforms:label>
<xforms:hint>Enter your name here</xforms:hint>
</xforms:input>
The <xforms:select1>
element allows the user to select one item from a series of options:
<xforms:select1 model="immigration" ref="/immigrant/purpose" appearance="full">
<xforms:label>Purpose of visit</xforms:label>
<xforms:hint>Please state the purpose of your visit</xforms:hint>
<xforms:item>
<xforms:label>Business</xforms:label>
<xforms:value>B</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Pleasure</xforms:label>
<xforms:value>P</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Other</xforms:label>
<xforms:value>O</xforms:value>
</xforms:item>
</xforms:select1>
Within the <xforms:select1>
element, the list of available choices are defined via one or more <xforms:item>
elements, each of which must have a label and value; the former is displayed to the user and the latter is passed to the server on submission.
A special “appearance” attribute in the <xforms:select1>
element can be used to control the display of the element in the browser (“full” for a list of all values, “minimal” for a minimum number of values, and “compact” for a scrollable list).
Similar, though not identical to the above, is the <xforms:select>
element, which allows the user to select more than one value from the options available.
<xforms:select model="immigration" ref="/immigrant/immunization" appearance="full">
<xforms:label>Immunization</xforms:label>
<xforms:hint>Please select the diseases that you have been immunized against</xforms:hint>
<xforms:item>
<xforms:label>Smallpox</xforms:label>
<xforms:value>100</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Malaria</xforms:label>
<xforms:value>113</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Yellow fever</xforms:label>
<xforms:value>56</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>Typhoid</xforms:label>
<xforms:value>174</xforms:value>
</xforms:item>
</xforms:select>
As before, the choices are defined via a series of <xforms:label>
and <xforms:value>
elements, while the “appearance” attribute can be used to control the appearance of the control (“full” for a list of all values, “minimal” for a minimum number of values, and “compact” for a scrollable list).
Finally, the <xforms:textarea>
element is used to display a multi-line text entry box, suitable for use with large blocks of text.
<xforms:textarea model="immigration" ref="/immigrant/address">
<xforms:label>Address in home country</xforms:label>
</xforms:textarea>
And here’s what it all looks like:
Now, all this is fine and dandy - but how about submitting the form and actually doing something with the user’s data?
Well, that’s a whole new kettle of fish, one which involves jumping through a complicated series of hoops involving the <xsd:submission>
element. I don’t plan to discuss it now - instead, I’m going to defer it to the second segment of this tutorial and instead encourage you to spend the interim playing with the various form controls to understand how they work. Each control comes with specific properties that can be used to customize its behaviour - so take a look at the specification, get comfortable with them, try out a couple of implemetations, and come back next week to take the next step in our XForms journey!
Note: Examples are illustrative only, and are not meant for a production environment. Melonfire provides no warranties or support for the source code described in this article. YMMV!
This article was first published on 28 Oct 2003.