Although some applications only require multiple-choice fields where only a single value may be chosen, in many situations it is desirable to be able to choose an arbitrary number of values for a particular field. However, up to this point, we have been content to represent form data using a single attribute on a single element to represent any given field value. With multivalued fields, we must choose a different strategy in using XML to represent such information.
Let us consider permitting multiple type values to be associated with our items. We revise our form data structure to be the following:
<?xml version="1.0"?>
<structure>
<item value="some value">
<types>
<type value="some type"/>
<type value="some other type"/>
</types>
<subitem subvalue="some other value"/>
</item>
</structure>
We shall now take advantage of those HTML form fields which permit users to select one or many values presented in a list or menu.
From the item type list many value may now be selected.Taking the example HTML code from before, we can add a definition of this new list to the template to produce something like this:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:template="http://www.boddie.org.uk/ns/xmltools/template">
<head>
<title>Example</title>
</head>
<body template:element="structure">
<form action="" method="POST">
<!-- Template text between the start and the interesting part. -->
<div template:element="item">
<p>
Some item: <input template:attribute="value" name="{template:this-attribute()}" type="text" value="{$this-value}" />
<input name="remove={template:this-element()}" type="submit" value="Remove" />
</p>
<p template:element="types">
Item type:
<select template:element="type" name="{template:list-attribute('value')}" multiple="multiple">
<option template:element="type-enum" template:expr="@value-is-set" template:expr-attr="selected"
template:value="@value" value="{@value}" />
</select>
</p>
<p>
Itself containing more items:
</p>
<p template:element="subitem">
Sub-item: <input template:attribute="subvalue" name="{template:this-attribute()}" type="text" value="{$this-value}" />
<input name="remove2={template:this-element()}" type="submit" value="Remove" />
</p>
<p>
<input name="add2={template:this-element()}" type="submit" value="Add subitem" />
</p>
</div>
<p>
<input name="add={template:this-element()}" type="submit" value="Add item" />
</p>
<!-- Template text between the interesting part and the end. -->
</form>
</body>
</html>
From the previous single-valued case, some crucial changes have been made:
types
element in the form data structure.select
element remains mapped onto the type
element in the form data structure. However, we indicate in the name of
the select
element that the value submitted maps onto a special kind of attribute.
Instead of mapping onto a single attribute on a single element, the
value maps onto a single attribute on a single element for each value submitted. So for
each value selected in the list or menu, a type
element is created with the value
attribute containing that value.select
element now has a multiple
attribute defined to permit multiple value selections.select
element, the option
element mapping onto
a type-enum
element using a different template:expr
condition than was used before.Just as in the single-valued case, the revised the form data structure for input does not quite match the structure used by the template. Therefore, we shall define an output form data structure as follows:
<?xml version="1.0"?>
<structure>
<item value="some value">
<types>
<type>
<type-enum value="some type"/>
<type-enum value="some other type"/>
</type>
</types>
<subitem subvalue="some other value"/>
</item>
</structure>
It is worth noting that the above structure does not define whether
many type
elements will exist within each types
element or whether another mechanism will be used to specify multiple
values for each type field.
In most respects, the presentation of the extra values is the same
as in the single-valued case. The result of the presentation of the
extra values is that the types
element in the
this example structure fragment...
<types>
<type>
<type-enum value="1"/>
<type-enum value="2" value-is-set="true"/>
<type-enum value="3" value-is-set="true"/>
</type>
</types>
...is transformed into something resembling this HTML code:
<p>
<select name="..." multiple="multiple">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3" selected="selected">3</option>
</select>
</p>
Numerous issues arise when considering the above transformation:
type
elements?value-is-set
attribute
come from?type
elements would have produced
many select
elements in the Web form, yet this is not
what we want; we need to restrict the number of select
elements to one per types
element whilst marking the
selected values so that they may be displayed appropriately in the list
or menu.
As in the single-valued case, we need to insert the permitted values
into the form data so that the template may visit the type-enum
elements and extract those values. However, we have now introduced
another task to this activity: to collect the selected values together
and to produce a unified type
element within
each types
element. In other words, we want to turn
something like this...
<types>
<type value="2"/>
<type value="3"/>
</types>
...into something like this:
<types>Using the same document containing all the permitted values as our source of information to be merged into the form data, we can now develop a stylesheet which performs the above transformation; this stylesheet needs to work on the following principles:
<type>
<type-enum value="1"/>
<type-enum value="2" value-is-set="true"/>
<type-enum value="3" value-is-set="true"/>
</type>
</types>
item
element (which the
stylesheet is programmed to recognise), do the following:value
attribute is retained.types
element and process it.types
element, do the
following:type
element within it.type
element, add the type-enum
elements from the
document containing the values, and if any type
elements were found within the item
element, specify
these for the activity.type-enum
elements, if any of
them have a value
attribute which matches any of the value
attributes of the found type
elements, set the special
value-is-set
attribute on that type-enum
element.The stylesheet source code can be found in examples/Common/VerySimple/Resources/structure_multivalue_types.xsl
,
whereas the document defined above which contains the values can be
found in examples/Common/VerySimple/Resources/structure_types.xml
.
To update the special WebStack resource, we now need to modify a few of the class attributes and to add a few others:
template_resources = {
"structure" : ("structure_multivalue_template.xhtml", "structure_output.xsl")
}
transform_resources = {
"types" : ["structure_multivalue_types.xsl"]
}
With these adjustments, it should now be possible to manipulate the items and subitems whilst specifying multiple type values on each item.