DevX HomePage

The Secret Life of XForms

XForms recently reached the W3C's Candidate Recommendation status—and you need to know about it—because XForms isn't a form description language, it's a language for describing applications in a platform-independent way. Best of all, it integrates easily with technologies you already know, such as XHTML, XPath, SVG, and CSS.
ake a look at the applications you deal with on a regular basis. Regardless of the platform or GUI that you use, or the programming language used to create them, there's a certain innate commonality to applications: areas where you enter text, buttons (always buttons), menus, scroll bars, sliders, grids, trees, panes (or pages), and so forth. Certainly there are exceptions; graphics programs such as Photoshop or 3D Studio have much more sophisticated interfaces, and games are fundamentally all about interface. But for most business programs, such as accounting packages, word processors, statistical analysis applications, or a wide range of other programs, you'll find a common set of abstract "components" that provide the bulk of interface functionality. In many cases these components also perform a significant amount of the intermediate processing—communicating directly with databases, setting internal variables to the application, persisting content, and so on.

If you think a bit more about such applications you also begin to see other pieces of commonality. Starting roughly fifty years ago, programmers realized that by creating an application that looped continuously, the application could retain its own internal state, working in "user" time to accept input interactively and generate output without terminating. This idea caused the shift from batch mode to interactive mode programming that underlies every windowed operating system today. Admittedly, most modern applications subscribe to a thread manager rather than creating a (system-locking) infinite loop; however, if you delve deeply enough into that thread manager, the loop is there, figuring out which thread to run at each successive pass.

The modern version of this application loop is called an event loop, named for its role in managing not just threads, but also the events that are passed from the system to various objects within the interface. Events that are not intercepted by some object within the event loop are recycled back to the system, which can discard them or handle them generically.

Event loops make it possible to load and maintain an internal state within the application. That state may be simply the contents of the visible form elements in the application, but more typically, the state is a separate model of which the visible interface is simply a reflection. When you load a file into the application, you are generally loading the model. Similarly, saving the file persists the model in a format understandable to the application.

HTML, as it exists right now, is at its core a batch document—the HTML content that describes a form is read by a browser and rendered as a Web page. In the absence of a scripting language, the form elements themselves are almost completely static—they cannot validate content, they do not interact, and most importantly, changing their states only sets the values of each control—there's no underlying background model. You can add interactivity via scripting and working with the HTML DOM, but that's not always portable between browser implementations, and still involves sending the interface representation to an external client, losing state the moment the client replaces the page with a new one.

If you take a look at a typical XForms viewer, you'll find that it gives you much the same kind of structure as any other application framework does: moving from a batch to an interactive programming mode. Implementations differ, but all XForms viewers preserve and update internal state for the application.

The idea here is pretty simple—the View, or user interface, provides a set of controls that give the "public" face of the application. The only way you can interact with that XForm is through its public face. Every time you load the form, enter a word into a text box, move a slider's thumb, or select an item from a drop down list, you change the state of a control, which in turn launches an event notifying the system that a change has taken place. You can then define actions (akin to event handlers) that occur whenever the event is fired for that particular component to update the internal model. You can also bind events to the model so that when a given value in the model changes, it forces an event to be launched that can be caught elsewhere.

If this sounds a lot like traditional event-based programming, that's because it is. The only difference is that the event handlers, the event notifiers, and everything else are built with XML; you handle processing with XPath expressions, describe the model using XML schema, and fire events using the XML Events architecture.




XForms Is About Applications, Not Just Forms
It's worth emphasizing the idea that XForms technology is about applications, not just about forms. One of the most common misconceptions that people have about the W3C XForms recommendation is that its primary purpose is to generate forms, such as job applications, building permits, and so forth, with the tight layout ability implicit in such forms. That's an admirable goal, and it's one that XForms could potentially fulfill, but this focus on "forms" also causes people to miss the real point of the language (and illustrates the danger of choosing names poorly).

XForms is not necessarily a Web language, though there are a number of Web based XForms engines. Instead, it's a way to create an application that, with no scripting, can do such things as automatically reject invalid data, automatically update the contents of one control based upon changes in another, load content from external resources and send content to external URLs without leaving the application, retain state from one "page" to another, pass information into secondary dialogs, and so forth.

Envision XForms as an XML based language for the description of an application.
In other words, an XForms form is (superficially at least) similar to a Visual Basic Windows application or a Swing Java client program. However, because XForms is in essence an abstract representation of the application, it's not language-specific. It's entirely possible that you could use the same XForms document as the basis for a windowed application in either VB or Java, though doing that is beyond the scope of this article.

XForms provides an abstract conceptual model of the form, rather than describing a specific layout.
This abstract XForms representation takes place at a number of levels. The first, and most obvious, is the use of abstract controls to describe interface elements. Listing 1 contains a simple stock calculator. When you select a specific stock and enter a number of shares, the calculator determines the total stock price.

When rendered in a browser, the results look like Figure 1. I used the x-port formsPlayer plugin for Internet Explorer, so your application may look somewhat different.

 
Figure 1: The Stock Calculator. The figure shows the Stock Calculator running in the X-Port FormsPlayer plugin for Windows.
I'm going to jump over the namespaces and the model for a moment to concentrate on the user interface components. The first thing you may have noticed in Listing 1 is that the XForms content, like a Java applet or ActiveX control, is embedded within the HTML (more properly, within the XHTML) that makes up the page. The creators of XForms wanted to replace the older browser-based, platform-specific form elements with something that could provide basic client-side validation and interaction, but that could still be incorporated into the XHTML model.

The example shows how you can place XForms content into a standard XHTML-formatted table. Once again, the point to remember is that XForms provides an abstract conceptual model of the form, rather than describing a specific layout.

Author's Note: One implication of XForms' abstract conceptual model is that you can theoretically incorporate XForms within SVG, XSL-FO, or any other XML dialect, rather than just using it within XHTML.

The example XForms code shown in Listing 1 contains five distinct components:

  1. <label> - The label element provides a general caption for a control. Labels are generally static—they don't generally change in response to changes in content.
  2. <select1> - This component provides a list of items from which the user is supposed to choose one. It is generally rendered much like an HTML <select> tag, though it could also be rendered as a set of radio buttons. In this particular case, the select statement reads from the model data (specifically the stocks portion) to populate both the name and value of each item in the selector.
  3. <input> - The input element will almost invariably be a text entry box of some sort, though the box can be set up to accept only certain types of input.
  4. <trigger> - The trigger element can be very confusing at first glance. In general, the best way to think of a trigger is to imagine that it is a button that, when pressed, initiates an action.
  5. <output> - The output element provides content that can't be modified. For instance, here the output is the price of each stock and the total value of the stocks purchased, both formatted in dollar units, complete with dollar sign and thousands separation.
Until you get into extremely customized graphical interfaces, most typical GUI components that people use to make Windows or Java applications are composed of simpler components.
While the most immediate interpretation of these tags is fairly obvious, it's less obvious that user agents can interpret the elements in any way that best fits the UI metaphor in use. For instance, a <select1> element in a 3D application might consist of items spaced evenly in a circle, as viewed along the plane of the circle, so that the selected item is always the nearest one. In contrast, a <select1> element in a virtual jukebox might present pages of song choices arranged by artist. This has some important implications, especially for SVG, because that language affords a much better vehicle for creating "rich" interfaces than almost any other.

The XForms library contains only a dozen or so components; however, because these components are abstract they can be combined to create more sophisticated interfaces. For example, a <range> element can represent sliders, spinners, or other similar operators. Moreover, you can combine the base components with repeaters, switches, groups, toggles, and other aggregating and control elements. This is an important point—until you get into extremely customized graphical interfaces, most typical GUI components that people use to make Windows or Java applications are composed of simpler components.




Building a Model
The second level of abstraction tied into XForms is the creation of models. A model represents an internal entity into which the interface (through the components) provides a window. Programming languages such as C# or Java usually reflect the model using classes and the relationships between classes.

However, one of the benefits of working with XML is that it is generally much easier to create an internal model as an XML document than as a set of related classes. The user interface may not necessarily duplicate the model exactly. For example, in the stock example shown earlier, while the internal model represented the price of each stock and the final price as an integer, the interface showed the price as a dollar amount—45225.253 became $45,225.25. The user interface may hide some items or display computed quantities based upon the contents the internal model.

The <xforms:model> element contains the model. At the topmost levels this looks like:

 <xforms:model id="userAccounts">
<xforms:instance>
<stockData>
<stocks>
<!-- a listing of stock data -->
</stocks>
<account>
<!-- account information
</account>
</stockData>
</xforms:instance>
</xforms:model>
The model's id identifies the model in subsequent expressions (invoked via the model attribute). The XForms engine automatically assumes that the first model in the document is the reference document unless explicitly overridden by a model attribute. Each model in turn contains instance data.

Everything within the instance should be valid XML. This document is the state repository for the XForm. That differs from other XML applications because it's dynamic—values within the instance can change in response to events that occur in the XForms application.

 <stocks>
<stock>
<name>Allied Data Systems</name>
<symbol>ADS</symbol>
<value>25.00</value>
</stock>
<stock>
<name>Beta System Components</name>
<symbol>BSC</symbol>
<value>17.37</value>
</stock>
<!-- additional stock data (
</stocks>
The example gives two distinct pieces of information, combined for convenience. The first part contains the relevant stock data for five stocks—the stock name, symbol, and price per share of the stock. In this example, the information is static. In a working application you could load the information dynamically from an external resource.

The second part of the model, however, provides the working core.

 <account>
<stock>
<name/>
<symbol/>
<value>0.00</value>
</stock>
<shares>0</shares>
<totalCost>0.00</totalCost>
</account>
The elements <name>, <symbol>, <value>, <shares>, and <totalCost> act as temporary variables that will be assigned values based upon the information from the components. This information is dynamic—choosing a new stock sets a new symbol and value, which then interact with the shares value to determine total costs. In essence, these become the equivalent of private variables, accessible only through the interface.

If you run the example XForm, set the drop-down box (Available Stocks) to Allied Data Systems and the number of shares to 12, then the internal model changes to:

 <account>
<stock>
<name>Allied Data Systems</name>
<symbol>ADS</symbol>
<value>25.00</value>
</stock>
<shares>12</shares>
<totalCost>300.00</totalCost>
</account>
Note that this latter version doesn't contain any of the formatting information shown in the display. The forms engine handles the appearance of content while the internal model contains the base data used to generate the content. In that respect, XForms is much like XSLT, except that where XSLT creates an entirely new output based upon the XML input, XForms simply modifies the XML input directly.




Binding it Together
Some of you may have begun to visualize the letters MVC floating in the background—not as some 1940s Roman epic movie (or 1990s remake) but as the initials for Model/View/Controller. In the early 1970s, the language Smalltalk introduced this particular design architecture. Simply put, the MVC architecture supposes you have a discrete model containing, some kind of output view, and then code of some sort to bind the view to the model—a controller that handled event input and the mappings between the two.

XForms is very nearly a pure embodiment of MVC. The distinction between model and view (or user interface) is fairly clean. The binding mechanism, though, can seem a little confusing at first, because XForms actually relies on a few different effects to handle the binding.

At the very lowest level, you have the ref attribute, which tells the XForm engine to associate a particular element or attribute value in the model with the control. For instance, in the Cost Per Share section of the example form, you have the output tag:

 <xforms:output ref="format-number(
/stockData/account/stock/value,
'$#,##0.00')">
The ref attribute contains an XPath expression, usually pointing to one or more elements within the model. In the above case, the XPath expression uses the stock value as retrieved from the XPath expression /stockData/account/stock/value. XForms passes the retrieved value to the XPath function format-number, which converts the price into a string of the form '$#,##0.00', a number mask indicating that the string should include the US dollar symbol, with a separator at the thousands point (Continental readers would of course use a different mask).

In this particular case the reference in the ref attribute is read only. However, references can go both ways. For instance, the sample XForm also inserts the initial value of the /stockData/account/shares element into the Number of Shares input box item.

 <xforms:input ref="/stockData/account/shares"/>
When users change this field, nothing happens until they press the button (trigger) marked "Calculate".

 <xforms:trigger>
<xforms:label>Calculate</xforms:label>
<xforms:action ev:event="DOMActivate">
<xforms:setvalue ref=
"/stockData/account/totalCost"
value="format-number(
number(/stockData/account/shares) *
number(/stockData/account/stock/value),
'##0.00')"/>
</xforms:action>
</xforms:trigger>
The <action> element is XForms' closest approximation to a subroutine. Actions take their context based upon the elements that called them (or the elements that they are in), and the specific event. For instance, a trigger invokes a "DOMActivate" event when pressed (activated), causing any and all internal DOMActivate actions contained within to run. It is possible, though not recommended, to have multiple event handlers with the same event key.

The <setvalue> command uses the ref attribute to retrieve an element or attribute from the model, then replaces the current value of the reference with the evaluated XPath expression in the value attribute. In this particular instance, the form takes the number of shares entered by the user, and multiplies that by the currently selected stock's value. Finally, it formats and displays the result as a floating point number with two significant displayed digits.

The selection box is more complex:

 <xforms:select1 ref=
"/stockData/account/stock/symbol">
<xforms:action ev:event="xforms-value-changed">
<xforms:setvalue ref=
"/stockData/account/stock/name"
value="/stockData/stocks/stock[symbol =
/stockData/account/stock/symbol]/name"/>
<xforms:setvalue ref=
"/stockData/account/stock/value"
value="/stockData/stocks/stock[symbol =
/stockData/account/stock/symbol]/value"/>
<xforms:setvalue ref=
"/stockData/account/totalCost"
value="format-number(
(/stockData/account/shares) *
(/stockData/account/stock/value),
'##0.00')"/>
</xforms:action>
<xforms:itemset nodeset=
"/stockData/stocks/stock">
<xforms:label ref="name"/>
<xforms:value ref="symbol"/>
</xforms:itemset>
</xforms:select1>
When the user makes a selection, XForms invokes the event xforms-value-changed on the selection box, which then invokes the three <setvalue> statements, changing the symbol, the stock value, and the total cost based upon this price and the number of outstanding shares. Changing the values automatically notifies all interface elements bound to them so they can update their own content, thus the <output> elements change their displayed values automatically.

This may seem like a lot of work for what should be a fairly simple application, but there are some real advantages. Handling cascading values, where changing one control causes other controls to change their internal contents—their models—as well, is notoriously difficult. But in this case, the XForms engine acts as the notifier, handling all the uglier notification processes, and leaving developers free to concentrate on establishing the data paths and other resources. This has the advantage of making the code easier to maintain as well.




The State of the Art
XForms can seem inordinately large and complicated at first blush, but much of the complexity can be attributed to integrating the model into the equation. Unlike scripted XHTML forms, once you've done the initial work to build an XForms document, adding new controls is surprisingly easy. Therefore, most working XForms (with many controls and components) will be easier to maintain than the equivalent scripted code applications.

What's more, because XForms is 100% XML based, you can use XSLT to generate an XForms document from one or more source XML files, perhaps with some schema filtering thrown in to determine which components best match the elements described by the schema.

The XForms specification itself is in Candidate Recommendation status. It may hold there until the XPath 2.0 specification is completed, because there are some compelling reasons to bind these two standards together, including external function definitions and inline regular expression support in XPath.

Implementation-wise, XForms support is perhaps not yet where it needs to be, though that's changing. IBM has begun work on the specification with its XForms Processing Center. In addition to supporting the XForms 1.0 standard, IBM's XPC also incorporates a ListView type control extension and a way to invoke Web services to send and retrieve content. This latter point is especially important because it makes it possible to build very robust client/server applications solely through an XForms interface.

The Novell XForms Technology Preview provides a stand-alone XForms viewer, designed to work with "pure" XForms (i.e., those that aren't embedded within HTML) though support for the latter is coming. The Novell implementation does include extensive CSS support, however, so the lack of an HTML substrate is not necessarily a major limitation.

Perhaps the most full-featured XForms viewer to date is the x-port XForms viewer. It provides both pure XML and embedded HTML support (with associated CSS in both cases), and runs as a plug-in within IE6. One drawback is that you must include both the <object> reference for the player and a processing instruction in the body of the XForm to use X-Port, though that may change after the specification becomes more mature.

As XForms evolves, it will likely move into two different realms. The Scalable Vector Graphics working group of the W3C is exploring ways to incorporate XForms into SVG 1.2, providing at least basic support for several critical components, which you can then override with custom graphics.

The next likely venue for XForms is in the wireless/mobile phone market. It's much easier to build XForms interpreters than to support a full-bore scripting language. XForms could quickly replace the cumbersome and awkward WAP/WML standard. Given the obvious synergy between XForms and VoiceXML, it is also likely that the next version of VoiceXML will be rebuilt along XForms lines, though maintaining a modicum of backwards compatibility.

XCiting XForms
XForms represents both a very old and very new way of programming, a model that can be crafted by hand or generated through transformations with equal ease. As computer architectures tend to move toward dynamic user interfaces, XForms provides a powerful vehicle to create increasingly robust "applications" without huge amounts of fragile scripted code. As a W3C standard, such applications have the implicit advantage of being platform and software language independent.

If your company deals with complex form information, wants to keep costs down, and needs a solution that can be easily maintained and updated, you could do a lot worse than explore XForms.

Kurt Cagle is a software developer and author specializing in XML technologies. He is the editor of the Metaphorical Web newsletter, an e-zine focusing on XML, Web technologies, and the state of the industry. You can reach him .


DevX is a division of Internet.com.
© Copyright 2010 Internet.com. All Rights Reserved. Legal Notices