HTML5 notation for XForms elements and CSS styling

XSLTForms is now using an HTML5 notation for XForms elements replacing numerous DIV and SPAN embedded elements with only CSS classes to differentiate them. This is still performed with XSLT 1.0 but it can also be done with vanilla Javascript and Node.js.

HTML5 is allowing custom elements and CSS classes can be defined for them. To avoid name conflicts, XForms elements are transformed into xforms-* elements (xforms-input, for example) and XForms attributes into xf-* attributes (xf-selected, for example). Shadow DOM is not currently used in XSLTForms but it cannot be used for grouping controls anyway.

Each HTML attribute with AVT is renamed with the prefix xf-template- and the xf-avt attribute is added to the corresponding HTML element.

XForms repeat elements are automatically converted into XForms repeat attributes when in HTML tables.

For example,

<xf:input ref="PersonGivenName" incremental="true">
 <xf:label>Please enter your first name: </xf:label>
</xf:input>

Becomes

<xforms-input xf-ref="PersonGivenName" xf-incremental="true">
 <xforms-label>Please enter your first name: </xforms-label>
</xforms-input>

There is no Javascript instructions generation in the new XSLT stylesheet.

HTML5 is not allowing custom elements within HEAD element so xforms-model elements have to go within BODY element.

Inline XML instances and XML schemas have to be protected within SCRIPT elements with a not-supported type (application/xml, for example) to preserve letter cases. Because of a design error in Mozilla Firefox XSLT engine, instances are also to be serialized with entities.

For example,

<xf:instance>
 <data xmlns="">
  <PersonGivenName/>
 </data>
</xf:instance>

Becomes

<xforms-instance>
 <script type="application/xml">&lt;data xmlns=""&gt;&lt;PersonGivenName/&gt;&lt;/data&gt;</script>
</xforms-instance>

As a consequence, for XSLTForms, the XSLT 1.0 stylesheet is lighter and the transformation is more than 3 times faster which is nicer for users, reducing the blank page wait.

The XSLT stylesheet is much simpler and it becomes easy to rewrite it in a procedural programming language. It could also be done with XQuery [XQuery] [XPF], of course. It has, actually, already been done in Javascript for Node.js because browser debuggers didn’t allow anymore breakpoints in Javascript when resulting from an XSLT transformation (it has been fixed in browsers since, but a few months later).

It is also possible to directly write forms in HTML5 as the XSLT stylesheet would generate them. When generating XForms pages with XQuery at server side, it might be more convenient than finding some trick to add the XSLT processing instruction to be applied at client side not at server-side. It is, of course, also good for performance and there is no blank page effect at all.

Yet, XSLTForms requires more custom sub elements, such as xforms-body, xforms-help, … to render XForms controls with HTML and CSS. This is now performed with Javascript when building the form.

For example,

<xforms-input xf-ref="PersonGivenName" xf-incremental="true">
  <xforms-label>Please enter your first name: </xforms-label>
  </xforms-input>

Becomes

<xforms-input xf-ref="PersonGivenName" xf-incremental="true">
  <xforms-label>Please enter your first name: </xforms-label>
  <xforms-body>
    <input>
  </xforms-body>
  <xforms-required></xforms-required>
  <xforms-alert-mark></xforms-alert-mark>
  <xforms-alert></xforms-alert>
</xforms-input>

Because of CSS attribute selectors, CSS rules are powerful enough to manage custom elements visibility. XSLTForms is not anymore adding its own CSS classes: it is adding run-time attributes instead. For example, an XForms group without a binding will always be visible but, with a binding, an extra attribute (xf-bound) will be programmatically added when effectively bound to enable visibility. Models and actions are always hidden.

Default CSS rules have been aligned to CSS rendering of XForms tutorial written by Steven Pemberton [XFTUT].

The xsltforms.css file has, effectively, been fully rewritten.

For example,

xforms-input:not([xf-required])[xf-invalid] > xforms-label::after {
  content: "\2716";
  color: red;
}