even seems to be the magic number for the W3C. Seven years after releasing XSLT 1.0 (which also debuted XPath), they followed up with XPath 2.0, XSLT 2.0, and XQuery 1.0, all unarguably better and more powerful than their predecessors. In a similar vein, XForms 1.0 debuted in 2002 to remarkably little fanfare. After seven years of testing, probing, real-world case studies, and rethinking about the underlying assumptions on which it was based, the W3C recently released XForms 1.1, at a time when people are beginning to seriously examine the potential for the technology.
XForms 1.1 has not changed its (apparently unique) underlying structure: an XForms document consists of a model made up of one or more XML instances, along with controls that are bound via XPath to the model. This approach ensures that you can work with the whole model directly in the client, maintain its own internal cohesiveness and validity, and send parts or the entire model to the server as desired.
Indeed, at first blush, the differences between this version and XForms 1.0 are difficult to see. The enhancements do exist, though, and are actually quite significant. For the most part, they are areas where the initial specification was either ambiguous or was becoming outdated in the face of evolving web technologies.
This article highlights some of the notable new features of XForms 1.1 and introduces some of the early implementations of this latest version.
Templates are easily one of the most requested XForms capabilities. In XForms 1.0, when you insert a new XML construct into the model, it has to come from an existing structure in the instance. This unfortunately means that should you want to start with an empty node and then add more content to it, you have to create a temporary template and then play games with hiding it. In XForms 1.1, you can specify a template resource?a node and its descendants in a separate instance of the model?to incorporate as a child of another element. The origin attribute on the
Beyond making it easier to add new content generically, templates also make it easier to add node content of different kinds simply by changing the XPath of the origin. You can use this to create “preset” templates that contain appropriate starter information (custom user templates), and can also pull in templates that have different underlying data structures (such as different form elements for U.S., Canadian, or European addresses). When a node and descendants from a template are cloned into the model, you can release the template in favor of other templates (which are also now easier to download), keeping client-side memory footprints low.
One of the most significant effects of templates is that they effectively enable you to construct whole XML structures dynamically, doing more than simple duplication of existing nodes. While you are still dependent upon the templates in question for construction (unlike with XQuery or XSLT, where you could construct such nodes dynamically), this feature makes it much easier to build fairly rich structures (especially compartmentalized ones) from component parts.
Submission has been dramatically beefed up to make XForms content submission much more robust, effectively turning it into a first class client. XForms is now capable of supporting a number of new functions:
- You can now design submissions to work with SOAP, RESTful services, Atom-based services, and even non-XML output, based upon the serialization attribute. This enables tasks such as uploading just the text contents of a given node (useful, perhaps, for sending JSON messages) or using XForms as a blogging platform.
- The method attribute on submissions now allows you to pass any QName to the server, rather than only HTTP methods such as GET, POST, and PUT (this includes DELETE, one of the more problematic HTTP methods in XForms 1.0).
- The action attribute has been replaced with a resource attribute (which is used a great deal in XForms 1.1 for a number of elements, not just
) and a element (which can take a value attribute that can then contain an XPath evaluation expression). This makes it much easier to dynamically change the target of a submission.
- Submissions can disable (and re-enable) both validation and relevance. This solves one of the more vexing XForms problems: storing a temporarily invalid block of XML content that was used for draft content editing.
- The targetref attribute is used in conjunction with the replace="instance" flag, making it possible for the results of a submission to replace only a specific node in a document instance, rather than the whole document. Again, you can use this to build the contents of a given data instance dynamically.
- Submission events are now much more informative, able to pass such information as whether a given submission was successful (200 or 300) or not (400 or 500).
- The new
element, part of the submission block, makes it possible to send additional header content, such as authentication information, along with the message.
The control is perhaps one of the more welcome innovations in XForms, and was in fact back-ported to HTML 5. In XForms 1.0, was typically determined by the incoming data type, in conjunction with the appearance attribute. However, it was usually given as a text value with no overt decoration. In XForms 1.1, now also supports the mediatype attribute, which in turn takes a mime-type value as an expression.
For instance, if the mediatype is set to image/* and the type of the node given in the ref or bind attribute is xs:anyURI, then this will render the URL (if it points to an appropriate image type) as an image of the width and height specified in the original image. This makes it possible to create interface elements such as lists that include avatar pictures, or icons that are themed based upon some property of the given element or attribute value in the instance.
Additionally, when you set the mediatype for output to “text/html,” whenever a CDATA section in a given element contains any HTML markup, then it will be rendered as HTML content (i.e., This is a test will be rendered as “This is a test“). The key to this feature is understanding that such CDATA content is not itself rendered as child nodes, but it rather is only text. Like any other form of output, it’s not possible to bind an output element directly to a node that has children (although you can create output using the value attribute).
In those versions of XForms that enable user-defined functions, this capability actually makes it possible to both create live “editors” of markup content on the fly and to generate output via templated functions. This allows you to convert multiple inputs into a report or an SVG graphic, if the browser supports it.
Enhanced Function Set
The core XForms function set was also expanded, solving a few of the thornier issues that XForms 1.0 developers have faced. For instance, XForms 1.1 now natively supports a random() function that will return an xs:double value between 0 and 1. This has long been on my personal wish list, as it enables building applications such as quizzes where item and question order are randomized. In general, it makes it easier to create “simulator” type apps and games.
The power() function also extends the math set, in this case by giving you the capability of evaluating power relationships (i.e., ab). Thus, you could build a simple Pythagoras machine that would generate hypotenuses. If you have three siblings (a, b, and c) that represent the three sides of a right triangle, then you can determine the c side from a and b as follows: , which calculates the expression (a² + b²)½.
The compare() function is used to compare two strings and determine from them in what order they would appear, using Unicode code-point collations (sorting by language). This is used primarily to create sorting algorithms.
The digest() and hmac() functions are used to create hashes from strings. Such hashes are used primarily in cryptographic routines, including the creation of authentication keys for posting web content via SSL forms in a secure manner.
A welcome addition is the introduction of a number of new date math functions:
- local-date() and local-dateTime(): The local:date() and local-dateTime() functions retrieve the date and extended datetime values for the current moment, reading the now() function and adjusting for timezone.
- seconds-to-dateTime() and days-to-date(): The seconds-to-dateTime() and days-to-date() functions take a delta value (the number of seconds or days, as appropriate) from the current date to determine the new date. Thus, if you wanted to know the date 30 days from the current day, you’d use days-to-date(30).
- adjust-dateTime-to-timezone(): The adjust-dateTime-to-timezone() function takes a date with a given timezone (or Greenwich Mean Time if no timezone is given) and converts it into the local data and time.
The choose() function makes it possible to perform a Boolean comparison and return an object (whether nodes or atomic types) based upon the results of that. For instance, suppose that you set up a binding in which the address structure given is different based upon whether the address is U.S. or Canadian. The binding would be expressed as
Two functions that can be a little confusing to differentiate are current() and context(). Current is primarily used in
Consider this snippet:
100 jpy ... 0.59376 8.37597 80.23451 0.76138
In this example, current()will take each of the
The context() function is a little more complex, and it refers primarily to elements such as
For instance, suppose that you had the following instance:
10 5 0
Then context() would be used as follows:
In this case, the default context from the ref that the value would end up using (instance('i2')/result/c) would prove useless in getting the a and b values (ordinarily, you would end up having to re-reference things back from the root, and a repeat element could prove to be unworkable). With context(), on the other hand, the context node for the expressions is the
As a general rule, you would use current() in those situations where you’re working with nodeset bindings, and context() when dealing with a ref statement that changes the immediate context (mainly
Finally, the id() function is useful for retrieving content that has clearly defined IDs (i.e., any element that has a type of “xs:id”). The first argument is a space-separated list of IDs, and the second is a nodeset that describes the root directory from which to look for these resources (typically an instance() node). While it is typically used with a schema, it’s also possible to bind elements directly:
10 25 This is a block of content. ..
Another function that introduces some very useful capabilities to XForms is the event() function. Whenever an event is launched, the user can catch and process that event with a
A submission error () occurred.
Each event has its own set of message properties, and as such, you should consult the XForms 1.1 W3C Recommendation for full details.
These functions should simplify the process of binding and processing XForms content fairly dramatically. None of them is a radical departure from the existing model, but they do fill holes that were proving show-stoppers for most XForms implementations.
XForms 1.1 Implementations
On the implementation front, the news is mixed. XForms has a higher profile than it did a few years ago, and a number of XForms projects are now showing up in everything from government-based sites to commercial applications. However, to date, the only major vendor to produce a commercial XForms 1.1 solution is EMC/Documentum, which developed the Formula XForms Engine for use in their XML tools. Formula is based on the Google Web Toolkit, and has both fast and robust support for 1.1, though it does require that XForms documents be recompiled between changes (typically as part of a pipeline path).
On the other hand, an increasing number of open source projects are producing XForms 1.1 implementations, many of which are proving to be surprisingly effective in their space after a couple of years of foundering.
Orbeon undeniably has the closest thing to a lock on the XForms server market: solutions for scenarios where the XForms implementation is effectively hosted on the server with enough hooks on the client to implement event handling. Because of its Java-based environment, it works well with Java-based XML databases, including those from Oracle and the eXist-db database.
It is very likely that once Ubiquity reaches a 1.0 version, it will also become the defacto XForms implementation used in conjunction with the IBM db2 PureXML database server. IBM also has Lotus Forms, which incorporates an XForms layer within a broader markup package for forms, though I’m not sure whether it supports the XForms 1.1 functionality yet.
Something of a stealth player in the effort to create an effective XForms 1.1 implementation is XSLTForms by
Chiba Web, another open source project, similarly has made the shift to a pure AJAX background, in this case Dojo (Ubiquity is YUI based, while XSLTForms is largely self-rolled). Chiba has recently released their 3.0 version, including support for XForms 1.1 (with a claim of 86% compliance). Like Orbeon (and to a certain extent XSLTForms), this latest version includes both a client and a server component (in this case, built around Saxon 9 as the underlying engine in order to get the XPath 2.0 functionality). It also works with eXist and is Java-based on the back end.
Picoforms, which targeted mobile devices rather than desktop web browsers, made an initial splash before fading. They recently posted a new splash web page promoting PicoWidgets, though it’s an obvious placeholder. There may be something there (XForms in mobile makes a lot of sense), but at this point it could just be a case of a company trying to hold on by their fingernails.
A Solution at the Right Time
XForms 1.0 failed to catch on for a number of reasons: a lack of viable commercial, or even decent open source projects, a rapidly shifting browser landscape, the nadir period of XML in general, and a standard that wasn’t quite viable enough to support the concepts involved. XForms 1.1, on the other hand, is debuting at a time when interest in XML technologies for handling larger-scale projects is rising dramatically. People are beginning to realize that the AJAX revolution by itself is not sufficient to support larger-scale enterprise data-entry solutions, and XForms has been improved considerably in key areas: from more solid support for varying mime-types, to extensibility, to the ability to work with templates and non-XML data. It’s the foundation of the new XRX architecture. The combination of XForms on the front end, XQuery on the back end, and REST in the middle makes for a remarkably compelling story that solves many of the issues associated with complex web application design.
While it may be too early to declare XForms 1.1 a success, it may very well manage to carve a major niche for itself in the next few years, especially as the wide variety of solutions all reach a stage of maturity.