Cross-browser XForms

Tweet

XForms is a complex but powerful replacement for HTML forms that relies heavily on cutting-edge XML technology. As a result of its complexity, browsers have been typically slow to implement it. But with working plugins for Internet Explorer and a pre-release extension now available for Firefox, the time is right to give this technology another look.

The last time I mentioned XForms, it seemed like the technology — at least in mainstream Web browsers — would never see the light of day. It required a plugin to work in Internet Explorer, Mozilla couldn’t find people willing to work on it, and Apple and Opera had both labelled it as impractical for various reasons.

Then, in August last year, Novell and IBM announced they would develop XForms support for Mozilla browsers. Now, those efforts are finally starting to pay off. So does that mean we can start writing XForms that work across browsers?

To find out, I installed the latest version of FormsPlayer for Internet Explorer 6 and Mozilla’s XForms extension preview release for Firefox 1.5 Beta 2, then started writing XForms.

XForms can fit right into an XHTML document, but the Firefox extension requires that the document be served with the true XHTML MIME type (application/xhtml+xml). It’s easy enough to use PHP (or another server-side language) to see if the browser supports this and send the appropriate HTTP header:

if (stristr($_SERVER['HTTP_ACCEPT'], "application/xhtml+xml")) {
  header("Content-type: application/xhtml+xml");
}

To identify XForms tags within your XHTML document, you need to declare a namespace prefix for the tags. While we’re at it, we’ll declare a prefix for XML Events as well, as XForms uses that standard to handle user interface events:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xforms="http://www.w3.org/2002/xforms"
    xmlns:ev="http://www.w3.org/2001/xml-events">

Since Internet Explorer doesn’t fully support XHTML, the FormsPlayer plugin needs to be loaded before any XForms tags are used, and told which namespace prefix you’ll use for XForms. For this, you need an <object> tag and an XML processing instruction in the <head> of the document:

<object id="FormsPlayer" width="0" height="0"
    classid="CLSID:4D0ABA11-C5F0-4478-991A-375C4B648F58">
</object>
<?php echo '<?import namespace="xforms" implementation="#FormsPlayer"?>'; ?>

I’ve output the processing instruction with PHP to prevent it from causing a PHP error if PHP’s short tags feature is enabled.

Now we can get down to writing some XForms. The basic premise of the technology is that you define one or more models — XML document skeletons — and then define the form that will be used to fill them in with data using a set of user interface elements.

Here’s an XForms model for a simple login form:

<xforms:model id="login">
  <xforms:instance>
    <login xmlns="">
      <username />
      <password />
    </login>
  </xforms:instance>
  <xforms:bind nodeset="/login/username" required="true()" />
  <xforms:submission action="submit.php" method="post" id="loginsubmit"
      includenamespaceprefixes="#default" />
</xforms:model>

The <xforms:instance> tag contains the XML document skeleton to be filled in. The <xforms:bind> tag indicates that the username tag requires a value before the form can be submitted. The <xforms:submission> tag says where and how the completed document should be submitted (in this case, a POST request to submit.php).

We can also create a second model–the equivalent of a second old-style HTML form–to allow a new visitor to register for an account:

<xforms:model id="newuser" schema="newuser.xsd">
  <xforms:instance>
    <newuser xmlns="">
      <username />
      <email />
    </newuser>
  </xforms:instance>
  <xforms:bind nodeset="/newuser/username" required="true()" />
  <xforms:bind nodeset="/newuser/email" required="true()" />
  <xforms:submission action="submit.php" method="post" id="newusersubmit"
      includenamespaceprefixes="#default" />
</xforms:model>

The main difference here is the schema attribute on the <xforms:model> tag. While we can use <xforms:bind> tags to make particular values required for submission, this attribute lets us control when values are considered valid. The specified file (newuser.xsd in this case) uses the XML Schema standard to describe the data values that must make up the submitted document.

This is where XForms lost a lot of support from browser makers. XML Schema is a complex standard, difficult both to learn and to implement, because it gives you incredible control over the kinds of values that are
acceptable in an XML document. For example, we can use a regular expression to require a valid email address:

<xsd:element name="email" type="emailtype" />
<xsd:simpleType name="emailtype">
  <xsd:restriction base="xsd:string">
    <xsd:pattern value="[-._a-zA-Z0-9]+@([a-zA-Z0-9]+.)+[a-zA-Z]" />
  </xsd:restriction>
</xsd:simpleType>

Unfortunately, because of the amount of work involved in implementing XML Schema, the current Mozilla XForms support does not enforce constraints like these. Just like JavaScript-based form validation logic, however, XForms must be validated server-side after submission anyway, so this is more an inconvenience than a deal-breaker.

Back in our XHTML document, we can now put together some form components to enable users to fill in and submit our two models. First, we want to let visitors choose if they will log in or register for a new account:

<xforms:group>
  <xforms:trigger>
    <xforms:label>Log In</xforms:label>
    <xforms:toggle case="logincase" ev:event="DOMActivate" />
  </xforms:trigger>
  <xforms:trigger>
    <xforms:label>Register</xforms:label>
    <xforms:toggle case="newusercase" ev:event="DOMActivate" />
  </xforms:trigger>
</xforms:group>

Each of the <xforms:trigger> tags here will create (in a desktop Web browser, at least) a button with the specified label (<xforms:label>). When these buttons are clicked (which
generates a DOMActivate event), the <xforms:toggle> tag will display a case — one of a number of available sub-forms. One of these will let the user log in, while the other will allow a new user to register.

<xforms:switch>
  <xforms:case id="logincase">
    ...login form...
  </xforms:case>
  <xforms:case id="newusercase">
    ...registration form...
  </xforms:case>
</xforms:switch>

Here’s the login form:

<xforms:input ref="/login/username" model="login">
  <xforms:label>Username</xforms:label>
  <xforms:hint>6-32 characters (letters, numbers, or underscores)</xforms:hint>
</xforms:input>
<xforms:secret ref="/login/password" model="login">
  <xforms:label>Password</xforms:label>
  <xforms:hint>The password you enter will not be displayed</xforms:hint>
</xforms:secret>            
<xforms:submit submission="loginsubmit">
  <xforms:label>Log In</xforms:label>
</xforms:submit>

It uses an <xforms:input> tag for the username field, an <xforms:secret> tag for the password field, and an <xforms:submit> tag for the submit button. Each of the fields has ref and model attributes that point to the specific element in the model that we want this field to set. The submit button indicates which <xforms:submission> tag to trigger — which model to submit and how.

So, how do our two XForms-enabled browsers cope with all this?

XForms default rendering in both browsers

About what we’d expect from an unstyled HTML form, really. Labels, fields and buttons are laid out inline with default dimensions and appearance. Just like HTML forms, XForms should be styled using CSS. Unfortunately, this is where the cross-browser niceness starts to fall apart.

The whole point of the XForms standard is that the appearance of the form’s user interface is determined by the browser or device displaying the form. The specification makes no comment on how CSS should apply to XForms fields, buttons, and whatnot. As a result, different XForms implementations will require different CSS.

Say you want to make the label of a form field bold and red when it contains an invalid value. Here’s how to do it for FormsPlayer:

xforms:input.invalid xforms:label,
xforms:secret.invalid xforms:label {
    color: red;
    font-weight: bold;
}

Easy enough, although it doesn’t conform to the standard for representing XML namespaces in CSS selectors. Firefox, however, does, so it requires this code instead:

@namespace xf url("http://www.w3.org/2002/xforms");
xf|input[invalid] xf|label,
xf|secret[invalid] xf|label {
    color: red;
    font-weight: bold;
}

Also note that the Firefox XForms extension currently uses attributes to identify states like invalid fields. In the final version of the extension, it’ll use pseudo-classes instead:

@namespace xf url("http://www.w3.org/2002/xforms");
xf|input:invalid xf|label,
xf|secret:invalid xf|label {
    color: red;
    font-weight: bold;
}

And that’s just the tip of the iceberg. Until better standards are developed in this area, you’ll basically need a separate style sheet for each of the XForms implementations you wish to support. For this case, we can use Internet Explorer’s conditional comments feature to apply the FormsPlayer style sheet in that browser only:

<link rel="stylesheet" type="text/css" href="xforms-mozilla.css" />
<!--[if IE]>
<link rel="stylesheet" type="text/css" href="xforms-formsplayer.css" />
<![endif]-->

With a bit of experimentation, I was able to set up style sheets that got the form looking pretty good in both implementations.

XForms styled rendering in both browsers

As you can see, when the Mozilla XForms implementation becomes publicly available, developers who have the luxury of asking their Internet Explorer users to install a plugin could find real-world uses for this technology fairly quickly.

Browser support is still something of a sticking point, however, with Apple and Opera working on supporting the less ambitious Web Forms 2.0 in their next major browser releases, and native support in Internet Explorer nowhere in sight. FormsPlayer displays a really ugly ad for itself as a browser toolbar when it starts up unless you manually disable it with Tools > Manage Add-ons…, so I’d hate to ask my users to install it.

Still, XForms is compelling technology — the example we’ve looked at here has only just scratched the surface of what XForms is capable of. If you’ve ever had to code a five-page form in three different languages with full client-side validation and fields that should appear and disappear in response to other selections, XForms is for you. It can knock over tasks like that with incredible ease.

Curious? Grab yourself one of the XForms implementations discussed here and try the example for yourself. Download the code and have a tinker, then head over to the XForms website and read a tutorial or two.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Pingback: Julian On Software » SitePoint Blogs » Cross-browser XForms

  • Jake Archibald

    Great article and a good introduction to xforms. However, I think it’s painfully clear that xforms is not much more powerful than html forms + javascript.

    Also, the differences in implementations are show-stoppers at the moment. For once, it seems down to an ambiguous standard than incorrect implementations.

    Jake.

  • Sojan80

    Good read, Nice job Kevin. It still seems like an awful lot of work for now though.

    I mean between dealing with the the “You have to install this plugin to use all the features of this site” hooha and the virtually non-existent support in Apple / Opera it just seems easier to develop forms the way we ae now.

    The one thing I’m not real clear on is XForms bascially a precursor to web forms 2.0?

    Is there any rumblings about when web forms 2.0 will have as much/more support than XForms already has, and will web forms 2.0 require yet another special plugin to be installed by users?

  • http://www.sitepoint.com/ Kevin Yank

    Sojan80,

    If you mean XHTML 2.0 (which is very different from Web 2.0), then yes — they’re related.

    According to the current XHTML 2.0 draft, XForms 2.0 is to replace the current forms tags in HTML 4 and XHTML 1.x. Some people don’t think that’s such a good idea, because XForms is so complicated. Some people have even gone so far as to develop an alternative successor to the current HTML forms tags: Web Forms 2.0.

    Personally, I believe there’s room for both. And that’s the beauty of XHTML — you can use either one. With browser support slowly emerging for both standards, developers will be able to choose between the simplicity and ease of development of Web Forms 2.0, or the power and flexibility of XForms.

  • Dr Livingston

    As good as it is I don’t think we are ready for it. The technology is too advanced for both us developers and users at the moment.

    In another 18 ~ 24 months then look at it again, certainly but I won’t be developing with it without native browser support. Plugins are never a viable solution, more so when XForms are meant to be a standard set down by the W3C.

    It’s good that the interest is there, and I’m sure that Firefox will support it natively years before IE does, as you would expect but it’s too much too soon in my view.

  • Mark Birbeck

    Nice article Kevin…very nice!

    Just a couple of quick things; first, the “xf:input” syntax is standard CSS, so will work in all browsers. All that is happening is the ‘:’ is being escaped so that it is not interpreted as a pseudo-class.

    Second, even putting that aside, you can have both sets of styles in the same stylesheet–just use the comma to separate selectors.

    Finally, on whether it is little more than HTML forms (Jake’s point). I can assure you it is a lot, lot more. One way to look at it is as a set of ‘patterns’ that have been codified in declarative mark-up. Things like help, hints, labels, validation, submission to servers, and so on, only require simple mark-up, rather than the large amount of scripting that the AJAX solutions use.

    More information is available at the XForms Wiki, and a number of articles and screenshots are available on my blog (where I also look at things like XForms versions of Google Suggest, Google Maps, del.icio.us side-bars, and more).

    Thanks for raising the issues, and once again, a very good article.

    Regards,

    Mark

    Mark Birbeck
    CEO
    x-port.net Ltd.

    e: Mark.Birbeck@x-port.net
    t: +44 (0) 20 7689 9232
    w: http://www.formsPlayer.com/
    b: http://internet-apps.blogspot.com/

    Download our XForms processor from
    http://www.formsPlayer.com/

  • juanchilo

    It is a good example and id like to aprove with this new standar but i dont know if Xform is the better solutions in these days, may be in a next time.
    bye

  • http://www.sitepoint.com/ Kevin Yank

    Thanks for your comments, Mark!

    the “xf:input” syntax is standard CSS, so will work in all browsers. All that is happening is the ‘:’ is being escaped so that it is not interpreted as a pseudo-class.

    It’s standard CSS, yes, but it requires that you use the same namespace prefixes across your entire site. This is not in the spirit of XML Namespaces. That’s why CSS3 has added the @namespace at-rule so that you can define your namespaces in your style sheet (e.g. xf| above). That’s what IE doesn’t support.

    Second, even putting that aside, you can have both sets of styles in the same stylesheet—just use the comma to separate selectors.

    No you can’t. Because IE doesn’t recognize the syntax of namespace selectors like xf|input, IE will ignore any rule that contains such a selector. To have both sets of rules in the same style sheet, you would need to declare the rules separately for each selector type.

    Keeping the style sheet rules separate also enables you to manage the different styles required by the different XForms implementations.

  • Erik Bruchez

    Nice introductory article. Now you should mention that there is more to XForms than FormsPlayer and the upcoming Firefox implementation: there are pure client-side implementations as well as hybrid, Ajax-based client-server implementations, including our own Orbeon PresentationServer (OPS). OPS is open source, and version 3.0, which brings the new Ajax-based XForms engine, is currently in beta. Check out our online examples (try out the ones marked “XForms NG”): they work in Internet Explorer and Firefox, and there is no need for any download.

    I have to react to the comment that says “However, I think it’s painfully clear that xforms is not much more powerful than html forms + javascript.” Yes, you can do what XForms does with Javascript and HTML forms, but it is incredibly painful! XForms provides you with a declarative programming model which is extremely powerful, much less error-prone and much easier to learn than Javascript. In fact, one of the goals of XForms is to reduce the need for scripting. This article doesn’t touch on things like xforms:repeat, xforms:switch, xforms:submission, etc., but I encourage the poster of that comment to take more time to look into XForms. Yes today cross-platform deployment is still problematic, but server-side implementations will alleviate this problem soon.

  • Adrian

    However, I think it’s painfully clear that xforms is not much more powerful than html forms + javascript.

    It’s exactly the opposite: it’s painfully clear that XForms *is* significantly more powerful than resorting to HTML+Javascript. Do some experimentation with some semi-complex examples and you’ll be excited by potential, regardless of some of the current integration issues.

    The use of declarative/non-procedural markup alone is a massive advantage in terms of managing complexity, quality and portability. It also opens the door for a raft of oppurtunities for automated tools to interact with the structured markup (designers, transformations to/from other abstract form definitions etc) in ways that simply aren’t feasible with HTML+Javascript.

  • http://www.deanclatworthy.com Dean C

    It’s as simple as this. I don’t want my IE users to have to install a plugin each time they visit my websites. For some users this is not even possible due to network permissions that reset their settings as soon as they log out. Maybe sometime in the future when it’s more widely supported we can think about adopting it :)

  • Erik Bruchez

    Well again, Dean, the current integration problem is well understood, but keep looking at XForms solution which do not involve upgrading your browser or installing a plugin.

  • http://www.errewf.it RaS!

    Bah, too tricky…

  • Anonymous

    Good introduction to this technology but I cant help but wonder whats wrong with how we code html forms now? Seems to work pretty well to me. When I first saw the article I thought it would allow greater control over the styling of form elements, that would get more interest from me.

    Mark

  • Client-Side

    No Client-Side Support, so why bother. Check out X-FORMS.com XSLT implementation of alot of the XForm Spec. With almost all browsers supporting Client-Side Transformation, it may be interesting to developers.

  • Pingback: SitePoint Blogs » Mozilla XForms Project threatened by cutbacks

  • Pingback: SitePoint Blogs » Mozilla XForms presentation from OSDC

  • Duane Gran

    I concur with Erik Bruchez on his comments. I’ve been developing an XForms application with OPS for the past two months and in my particular case server-side processing was the best solution. I think FormsPlayer and Mozilla XForms are excellent solutions, but I would recommend that anyone interested in this technology also consider OPS (as well as Chiba).

    There is some debate in this thread about the utility of XForms. Naturally for simple cases it is overkill, but if you have ever tried to create an XML document with a web interface (using html forms) you will immediately see the benefits. Throw in a few repeatable elements and the problem becomes nearly intractable — XForms to the rescue!

  • FormFaces

    FormFaces is a pure JavaScript solution that utilizes AJAX techniques and can be seamlessly integrated with AJAX applications. This means that XForms+HTML can be sent directly to the browser where JavaScript transcodes the XForms controls to HTML form controls and processes the binding directly within the browser – requiring ZERO server-side processing and ZERO plug-ins. This is extremely simple to use, just insert the following tag into your XForms+HTML document:

    The FormFacesTM JavaScript is compatible with browsers that implement XHTML 1.0, ECMA-262 3rd Edition, and DOM Level 2 which includes Internet Explorer, Netscape, Mozilla, FireFox, Opera, Konquerer, Safari, and NetFront. To this end, the new FormFacesTM framework enables:

    1. Cross-browser support – existing client-side browser can be used.

    2. Server-side technology agnostic – the same forms can be used across disparate frameworks such as Java and .Net.

    3. Offline mode is possible – user interaction does not require server round-trips.

    FormFaces is available for download, and is licensed under both a GPL and commercial license.

  • claud108

    Hi,
    What if I want to whow a case with more data to select in case when user/password is correct?
    It is needed a choice of the above mentioned case based upon a message of confirmation sent by server.

    Thank you