Creating Applications: Recommendations and Advice

To avoid hard-to-explain problems when designing and testing templates, the following advice may be of some use:

Beware of Nesting Elements in Multiple-Choice Elements

It is not necessarily a good idea to nest elements inside multiple-choice elements like this:

<multi>
<multi-enum value="1"/>
<multi-enum value="2"/>
<multi-enum value="3"/>
<nested value="x"/>
</multi>

The reason for this is that the number of multiple-choice values may vary within your application, and the nested elements will appear at a different position depending on how many such values have been inserted. Whilst this might not affect some applications, at least not to begin with, the usage of more advanced features (in-page updates, for example) will probably expose problems due to the way XSLForms reconstructs the XML document data from the input form data.

We can avoid the above mistake by specifying the first parameter in the template:multiple-choice-field and template:multiple-choice-list-field annotations. For example:

<select name="..." template:multiple-choice-field="multi,multi-enum,value">
<option value="..." template:multiple-choice-value="multi-enum,value,selected"></option>
</select>

This effectively prevents us from inserting the nested element inside the multi element.

Beware of Adding Elements into Mixtures of Elements

Although we ignore this rule with the example in this documentation, it is necessary to be aware of problems with adding and removing elements where other elements may reside. Consider part of our form data structure:

<item value="a">
<type>
<type-enum value="1"/>
</type>
<subitem value="x"/>
</item>

Provided that we control the process of adding and removing the elements, making sure that they always reside at the end of the element collection inside the item element, and that they always follow a known number of elements, we can avoid issues with more advanced features (in-page updates, for example), although using such features on the subitem elements themselves may cause problems that may only be resolved by moving the subitem elements into a container element of their own:

<item value="a">
<type>
<type-enum value="1"/>
</type>
<subitems>
<subitem value="x"/>
</subitems>
</item>

Make Sure the Output Structure Agrees with the Template

Since XSLForms templates essentially describe the presentation of an XML document, it is vital that the output form data structure agrees with the template - that is, the output structure can be properly processed by the template and that all parts of the template are displayed as expected. It is also very important to make sure that transformations on the input document produce all the necessary elements for the output document so that the resulting page gives the user the opportunity to specify data that is missing. Consider this section of an example template:

<p template:element="package">
<p template:element="author">
Name: <input template:attribute-field="name" name="..." type="text" value="..."/>
</p>
</p>

Here, if the author element is not found in the output structure, no field will be produced in the Web page, no opportunity will be given for an author to be specified, and no author information will subsequently be editable. One solution is to introduce the author element into the XML document when creating the package element - this should then "bootstrap" the process and ensure that the author details will remain editable as long as the package element exists.

Ensuring Element Structure with Document Initialisation

Although it is not necessary to use document initialisation in resources, the above case would be detected by an input/initialiser stylesheet, and the package and author elements would be added if no way of adding them was mentioned in the template. Typically, we would employ selectors to provide the ability to add elements in templates, and the above example could be extended as follows:

<p template:element="package">
<p template:element="author">
Name: <input template:attribute-field="name" name="..." type="text" value="..."/>
</p>
<p>
<input name="..." template:selector-field="add-author,author" type="submit" value="Add author" />
</p>
</p>

With the newly-added selector, we can see that author elements could at least be added by users of the application, but package elements would still be impossible to create in the user interface. The document initialisation mechanism distinguishes between these two cases by looking for selectors which mention element names; here, the template:selector-field attribute has two parts to its value:

  1. A name used to identify the selector.
  2. The name of an element: author

Since the author element is mentioned, the mechanism knows not to create such elements automatically. However, since no such selector exists for package elements, those elements are created automatically.

Selecting from the Correct Document

After document initialisation or any other transformation, it is necessary to re-evaluate selector information in the context of the updated document if such information is to be used with such updated data, noting that any changes in the structure of the such data will cause the selectors to refer to the wrong parts of documents. To make updated documents available to XSLForms, the following call can be made on the form object (the third parameter in the respond_to_form method):

form.set_document(document_name, updated_document)

The updated selectors can then be obtained as usual:

selectors = form.get_selectors()

Typically, selectors should be accessed and used before initialisation since they refer to information that must already exist and can therefore be manipulated without preparatory work being done on the documents involved.