Steven Pemberton, W3C/CWI
Version date: 2020-10-06
XForms is a markup language for forms and applications on the Web. This document is a tutorial introduction to XForms; although it assumes knowledge of forms in HTML and shows how to convert HTML forms to their XForms equivalent it should still be readable for people who do not know HTML. Although there is mention of additional facilities of XForms beyond those possible in HTML Forms (marked with an asterisk on the headings), it is not a full tutorial on all features of XForms. Part 2 deals with additional features that are not available in HTML Forms. An earlier version of this tutorial introduced XForms 1.0. This version is updated for XForms 1.1.
*Features not present in HTML Forms
Take this simple HTML form:
<html> <head><title>Search</title></head> <body> <form action="http://example.com/search" method="get"> Find <input type="text" name="q"> <input type="submit" value="Go"> </form> </body> </html>
The main difference in XForms is that details of the values collected and
how to submit them are gathered in the head, in an element called
model
; only the form controls are put in the body. In this case
the minimum you need to put in the head is:
<model> <submission action="http://example.com/search" method="get"/> </model>
(Elements and attributes in XForms are in lower case.)
The <form>
element is now no longer needed; the controls
in the body look like< this:
<input ref="q"><label>Find</label></input> <submit><label>Go</label></submit>
What you can hopefully work out from this is that form controls have a
<label>
element as child, the <input>
uses "ref
" instead of "name
", and there is a separate
submit
control that links to the details of the submission in the
head. So the complete example is:
<h:html xmlns:h="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/2002/xforms"> <h:head> <h:title>Search</h:title> <model> <submission action="http://example.com/search" method="get"/> </model> </h:head> <h:body> <h:p> <input ref="q"><label>Find</label></input> <submit><label>Go</label></submit> </h:p> </h:body> </h:html>
Another obvious difference is the use of h:
prefixes on the
HTML elements. This has nothing to do with XForms, but with XML which is
designed to allow you to combine different languages together. XForms is
designed to be combined with different languages, not just XHTML. XML
processors need to be told which language different elements belong to, though
one language may be the 'default' language. In the above document, XForms has
been made the default, though XHTML could have been made the default by
changing the xmlns
attributes in the head:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms"> <head> <title>Search</title> <xf:model> <xf:submission action="http://example.com/search" method="get"/> </xf:model> </head> <body> <p> <xf:input ref="q"><xf:label>Find</xf:label></xf:input> <xf:submit><xf:label>Go</xf:label></xf:submit> </p> </body> </html>
Another technique is to swap default namespaces as needed, like this:
<html xmlns="http://www.w3.org/1999/xhtml" <head> <title>Search</title> <model xmlns="http://www.w3.org/2002/xforms"> <submission action="http://example.com/search" method="get"/> </model> </head> <body> <group xmlns="http://www.w3.org/2002/xforms"> <input ref="q"><label>Find</label></input> <submit><label>Go</label></submit> </group> </body> </html>
The choice is yours. You can also choose to make neither the default, and
prefix all elements. You can choose any prefix; h:
or
x:
or html:
or form:
, it's up to you (or
at least, it ought to be; however, some implementations require you to leave
the HTML elements unprefixed, and the XForms elements prefixed).
XForms provides equivalents of all HTML Form controls. But there is a major
difference in approach: HTML mainly specifies how the control should
look, while XForms specifies what the control should do. So
while the HTML specification says that the select
element creates
a menu, and the radio
type of input
creates radio
buttons that allow a single choice to be made, XForms has the
select
and select1
elements, which only specify the
intent of the controls, to select zero or more, or only one, element from a
list. How they are presented to the user can vary across devices, or according
to a style sheet. On a mobile telephone where screen space is scarce, both
might be represented with menus, while on a larger screen both might be
represented with selectable buttons. You are allowed to give a hint to what you
want, or you may use a stylesheet to give precise styling, but if you don't, a
device, or a style sheet, may make a choice for you.
So here is how you write the equivalent of the HTML Forms controls.
First name: <input type="text" name="firstname">
is written
<input ref="firstname"><label>First name:</label></input>
There is no need to indicate that it is text: in the absence of any other
information, by default it is text (called string
in XForms). Try
it:
(Source)
By default the data is updated when you leave the control. Adding the
attribute incremental="true"
to any control means that
the data is updated as you type:
<input ref="firstname" incremental="true"><label>First name:</label></input>
(Source)
See later under 'initial values' for how to give any control an initial value.
The above two examples used, apart from the input controls, a control that
is not in HTML: output
. This control allows you to include values
as text in the document.
Your current total is: <output ref="sum"/>
or
<output ref="sum"><label>Total</label></output>
This can be used to allow the user to preview values being filled in and can also calculate values:
Total volume: <output value="height * width * depth"/>
(where height
, width
and depth
are
values collected by other controls.) Try it:
(Source)
Adding the attribute incremental="true"
to the input controls
above causes the calculated values to be updated as you type:
(Source)
If you add mediatype="image/*"
to an output control, the value will
be interpreted as a URL and displayed as an image:
<output ref="photo" mediatype="image/*"/>
There will be examples of this later
Message: <textarea name="message" rows="20" cols="80"></textarea>
is written
<textarea ref="message"><label>Message:</label></textarea>
(Source)
Styling, such as the height and width, is done using a style sheet. For instance, put this in your style sheet
textarea[ref="message"] { font-family: monospace; height: 20em; width: 80em }
Although this mimics the HTML behavior, there is no requirement that you use a monospace font, nor that you specify the width in rows and columns like this: you could use lengths, or percentages, or whatever:
textarea[ref="message"] { font-family: serif; height: 2cm; width: 20% }
If you want all your textareas to have the same dimensions, you can use
textarea { font-family: sans-serif; height: 20em; width: 80em }
You include a stylesheet in your document in the usual way (for instance
using <link>
or <style>
in HTML).
Radio buttons select one value from a number of alternatives:
Gender: <input type="radio" name="sex" value="M"> Male <input type="radio" name="sex" value="F"> Female
becomes
<select1 ref="sex"> <label>Gender:</label> <item> <label>Male</label><value>M</value> </item> <item> <label>Female</label><value>F</value> </item> </select1>
Bear in mind that this may be presented as any one of radio buttons, a
(scrollable) select area, or a menu. You may include a hint
appearance="full"
on the <select1>
to suggest
that it should be presented as radio buttons. (Use
appearance="compact"
to suggest a select area and
appearance="minimal"
to suggest a menu). Here is an example - note
that since they are all bound to the same data value, if you change one, they
all change to match:
(Source)
The section on 'initial values' later says how to preselect a value.
Checkboxes select zero or more from a list.
Flavors: <input type="checkbox" name="flavors" value="v"> Vanilla <input type="checkbox" name="flavors" value="s"> Strawberry <input type="checkbox" name="flavors" value="c"> Chocolate
is written
<select ref="flavors" appearance="full"> <label>Flavors:</label> <item> <label>Vanilla</label><value>v</value> </item> <item> <label>Strawberry</label><value>s</value> </item> <item> <label>Chocolate</label><value>c</value> </item> </select>
Similarly to select1
, you can use the appearance
attribute to effect how it is displayed:
(Source)
The section on 'initial values' says how to pre-check values.
Depending on the presence of the multiple
attribute in HTML,
menus select one, or zero or more from a list of options. You either use
<select1>
to select a single choice, or
<select>
to select zero or more.
Month: <select multiple name="spring"> <option value="Mar">March</option> <option value="Apr">April</option> <option>May</option> </select>
would be written:
<select ref="spring" appearance="minimal"> <label>Month:</label> <item><label>March</label><value>Mar</value></item> <item><label>April</label><value>Apr</value></item> <item><label>May</label><value>May</value></item> </select>
If multiple
isn't present on the HTML select
, then
use select1
instead.
The section on 'initial values' says how to preselect values.
<form method="post" enctype="multipart/form-data" ...> ... File: <input type="file" name="attachment">
is written
<submission method="form-data-post" .../> ... <upload ref="attachment"><label>File:</label></upload>
Password: <input type="password" name="pw">
is written
<secret ref="pw"><label>Password:</label></secret>
This example uses a secret
control and an extra control to
optionally show what has been typed:
(Source)
Ten years of experience with HTML Forms has shown that hardly anyone actually uses reset buttons, and yet very many Web forms include them. A problem is that often the reset button with the text "Reset" is larger than the submission button that is often marked "OK", with the result that people accidently click on reset when they mean to click on OK, sometimes losing a lot of work (few if any browsers offer an undo). Therefore, while it is possible to create a reset button in XForms, it is deliberately harder to do, in order to discourage people unless they really want one:
<input type="reset">
is therefore written
<trigger> <label>Reset all fields</label> <reset ev:event="DOMActivate"/> </trigger>
(Source)
One important difference to note with the HTML version is that fields are reset to their initial value, and are not just blanked out (you can see that in the above example if you change the values and then press on reset).
The fact that the event
attribute has a prefix, means that you
have to add the following XML Namespace to the head:
xmlns:ev="http://www.w3.org/2001/xml-events"
You will find a fuller explanation of the event markup in part 2.
Buttons have no predefined behavior, but have a behavior attached to them which is triggered when a relevant event occurs.
The button element
<input type="button" value="Show" onclick="show()">
can be written
<trigger><label>Show</label> <h:script ev:event="DOMActivate" type="text/javascript">show()</h:script> </trigger>
or
<trigger ev:event="DOMActivate" ev:handler="#show"> <label>Show</label> </trigger>
where "#show
" locates the element (for instance a
script
element) that implements the behavior:
<script id="show" ...>...
XForms has a number of built in actions that can be executed by a button; see the reset button above for an example.
<input type="image" src="..." ...>
can be written in several ways, such as by putting an image into the <label> element:
<trigger...><label><h:img src="..." .../></label></trigger>
or by specifying it in a stylesheet
<trigger id="activate" ...>
with a stylesheet rule
trigger#activate {background-image: url(button.png); background-repeat: none}
or by using an XForms <output>
:
<trigger> <label><output mediatype="image/*" value="'http://www.example.com/image.png'"/></label> </trigger>
(Likewise for <submit>
.)
Drink: <select name="drink"> <option selected value="none">None</option> <optgroup label="Soft drinks"> <option value="h2o">Water</option> <option value="m">Milk</option> <option value="oj">Juice</option> </optgroup> <optgroup label="Wine and beer"> <option value="rw">Red Wine</option> <option value="ww">White Wine</option> <option value="b">Beer</option> </optgroup> </select>
is written
<select1 ref="drink"> <label>Drink:</label> <item><label>None</label><value>none</value></item> <choices> <label>Soft drinks</label> <item><label>Water</label><value>h2o</value></item> <item><label>Milk</label><value>m</value></item> <item><label>Juice</label><value>oj</value></item> </choices> <choices> <label>Wine and beer</label> <item><label>Red wine</label><value>rw</value></item> <item><label>White wine</label><value>ww</value></item> <item><label>Beer</label><value>b</value></item> </choices> </select1>
<fieldset> <legend>Personal Information</legend> Last Name: <input name="lastname" type="text"> First Name: <input name="firstname" type="text"> Address: <input name="address" type="text"> </fieldset>
is written
<group> <label>Personal Information</label> <input ref="lastname"><label>Last name:</label></input> <input ref="firstname"><label>First name:</label></input> <input ref="address"><label>Address:</label></input> </group>
Note the consistent use of <label>
.
The one other control, apart from output
, that is not in HTML
is range
. This control allows you to specify a constraint on a
value.
<range ref="volume" start="1" end="11" step="0.5"/>
A user agent may represent this as a slider or similar.
As you will see in the next section, there is no need for hidden controls in XForms.
The attribute named ref
on each control actually refers to a
child of an instance
element in the model, where the values are
gathered before submission. If there is no instance element there (as in the
search example above), then one is silently created.
Although it is perfectly allowable to let the system create your instance for you, there are reasons why it is a good idea to include one anyway, like this for the search example:
<model> <instance><data xmlns=""><q/></data></instance> <submission action="http://example.com/search" method="get"/> </model>
From this you immediately see that the only data value submitted is called
"q". The most obvious advantage of this is the documentation value of being
able to see what is being submitted, but the system will now also check that
when you say ref="q"
that there really is a q
in the
instance.
Note that it is essential, for reasons we won't go into detail here, that
you put the xmlns=""
on your instance data, to tell the processor
that the elements here are neither XHTML nor XForms elements.
(Note that the tag <data>
has been used here, but you can
choose any tag you like.)
For initializing controls including initializing checked boxes, and selected menu items etc., you just supply an instance with pre-filled values. For the search example:
<instance><data xmlns=""><q>Keywords</q></data></instance>
would pre-fill the text control with the word Keywords.
Similarly for the example in the checkboxes section, which looks like this:
<select ref="flavors" appearance="full"> <label>Flavors:</label> <item> <label>Vanilla</label><value>v</value> </item> <item> <label>Strawberry</label><value>s</value> </item> <item> <label>Chocolate</label><value>c</value> </item> </select>
You can preselect the vanilla and strawberry checkboxes like this:
<instance><data xmlns=""><flavors>v s</flavors></data></instance>
Similarly for the menus example, which looked like this:
<select ref="spring" appearance="minimal"> <label>Month:</label> <item><label>March</label><value>Mar</value></item> <item><label>April</label><value>Apr</value></item> <item><label>May</label><value>May</value></item> </select>
You can preselect March
and April
like this:
<instance><data xmlns=""><spring>Mar Apr</spring></data></instance>
And for the optgroup
example:
<select1 ref="drink"> <label>Drink:</label> <item><label>None</label><value>none</value></item> <choices> <label>Soft drinks</label> <item><label>Water</label><value>h2o</value></item> <item><label>Milk</label><value>m</value></item> <item><label>Juice</label><value>oj</value></item> </choices> <choices> <label>Wine and beer</label> <item><label>Red wine</label><value>rw</value></item> <item><label>White wine</label><value>ww</value></item> <item><label>Beer</label><value>b</value></item> </choices> </select1>
Preselect the value none
like this:
<instance><data xmlns=""><drink>none</drink></data></instance>
The reason that XForms does not need hidden controls is that any values in
the instance that haven't been bound to by a control are by definition not
visible to the user. So if you want to add a hidden value results
to the search form, you change the instance to:
<instance><data xmlns=""><q/><results>10</results></data></instance>
You don't have to specify the initial instance in the document itself, because you can load it from an external resource, like this:
<instance src="http://example.org/forms/templates/t21.xml"/>
and the document t21.xml can then contain your data, like
<data><w>640</w><h>480</h><d>8</d></data>
(You don't need the xmlns=""
in external instances, though it
doesn't do any harm either.)
Loading external instances gives you immense power. This is because the
ref
attribute on the forms controls doesn't just let you select an
identifier as HTML's name
does, but in fact can be any XPath
expression. XPath lets you select any element or attribute in an XML
document.
This means that once you have learnt XPath, you can bring in any
XML document as instance, even an XHTML document, bind controls to it, and
submit it. For instance to bind to the <title>
element in an
XHTML document, you can use
<input ref="/h:html/h:head/h:title">...
(i.e. the title
element within the head
element
within the html
element, all in the XHTML namespace), or
<input ref="/h:html/h:body/@class">...
which is the class
attribute on the body
element.
For example, suppose a shop has very unpredictable opening hours (perhaps it depends on the weather), and they want to have a Web page that people can go to to see if it is open. Suppose the page in question has a single paragraph in the body:
<p>The shop is <strong>closed</strong> today.</p>
Well, rather than teaching the shop staff how to write HTML to update this, you can make a simple form to edit the page instead:
<model> <instance src="shop/status.xhtml"/> <submission action="shop/status.xhtml" method="put"/> </model ... <select1 ref="/h:html/h:body/h:p/h:strong"> <label>The shop is now:</label> <item> <label>Open</label><value>open</value> </item> <item> <label>Closed</label><value>closed</value> </item> </select1> <submit><label>OK</label></submit>
(This example really does load the above XHTML file, but the save won't work:)
(Source)
Note that for this to work, the page in question that is being changed must be correct XHTML, (and not HTML, since only XHTML is an XML document), and your server must accept the "put" method (not all servers do). However, if the XHTML document in question is in a file on the local machine, then you can get the instance from the file, and write it back with a submit. See below.
HTML only allows you to submit the data to one server, in a single way.
XForms allows you to have different submit controls binding to different submission elements in the head to submit the data to different servers, or in different ways.
For instance, the search example could allow the user to submit the search string to different search engines:
<model> <instance><data xmlns=""><q/></data></instance> <submission action="http://example.com/search" method="get" id="com"/> <submission action="http://example.org/search" method="get" id="org"/> </model>
and then in the body:
<submit submission="org"><label>Search example.org</label></submit> <submit submission="com"><label>Search example.com</label></submit>
Note how which submission to use is identified with the 'id' attribute. The first submission element in the model is the default one, so it's also possible to write:
<model> <instance><data xmlns=""><q/></data></instance> <submission action="http://example.com/search" method="get"/> <submission action="http://example.org/search" method="get" id="org"/> </model>
and then in the body:
<submit submission="org"><label>Search example.org</label></submit> <submit><label>Search example.com</label></submit>
but not that a risk of doing this is that you then can't move the submission elements around to change their order.
Just as with HTML there are a number of ways to submit the data. In HTML how
to submit is expressed in two attributes, method
and
enctype
; in Xforms it is expressed in method
only:
HTML | XForms |
---|---|
method="get" | method="get" |
method="post" enctype="application/x-www-form-urlencoded" |
method="urlencoded-post" |
method="post" enctype="multipart/form-data" |
method="form-data-post" |
There are some new ways of submission; the most interesting are
method="post"
which posts the results as an XML document, and
method="put"
which puts the results as an XML document. An
interesting use of this is something like:
<submission action="file:results.xml" method="put"/>
which saves your results to the local filestore by using the
file:
scheme.
Since, as shown above, you can have more than one submission per form, this means that for a large form, you could have separate 'save to disk' and 'submit' buttons.
The default when values have been submitted is for the result returned by
the server to replace the whole document, just as with HTML. However, there are
other options, specified with the attribute replace
on the
submission
element. The value replace="instance"
replaces only the instance, and replace="none"
leaves the form
document as-is without replacing it.
For instance, for an address-change form for a bank, you can provide two buttons, one to prefill the form with name and address based on the account number, and one to submit the changed results:
<model> <instance><data xmlns=""> <accountnumber/><name/><address/> </data></instance> <submission method="get" action="http://example.com/prefill" id="prefill" replace="instance"/> <submission method="get" action="http://example.com/change" id="change" replace="none"/> </model> ... <input ref="accountnumber"><label>Account Number</label></input> <submit submission="prefill"><label>Find</label></submit> <input ref="name"><label>Name</label></input> <textarea ref="address"><label>Address</label></textarea> <submit submission="change"><label>Submit</label></submit>
The 'find' button will replace the instance with a new instance containing the details of the person with the account number, which you can then change; the 'submit' button will then send the changed instance back, leaving the form as-is in the browser to allow further changes or to input a new account number to prefill.
It will look like this (this is a mock-up, where the changed value is not submitted, but it gives you the idea):
(Source)
In HTML you can specify that controls are disabled, or read-only but the only way you can change the property is with scripting.
XForms offers easy ways to control these properties, but has other properties you can specify as well:
Note that in XForms it is the collected value that has the property, not the control, but the property shows up on all controls bound to the value.
These properties use a <bind>
element that goes in the
<model>
. To use bind
, you must have an explicit
<instance>
element.
To disable controls you use the relevant
property. For
instance, to say that the credit card number only needs to be filled in if the
person is paying by credit, you can write:
<model> <instance><data xmlns=""> <amount/><method/><cc/><expires/> </data></instance> <bind nodeset="cc" relevant="../method='credit'"/> <bind nodeset="expires" relevant="../method='credit'"/> </model>
This states that the fields cc
and expires
are
only relevant when method
has the value credit
, and
will therefore be disabled for other values of method
. You have to
say "../method
" rather than just method
, because in a
bind
you are talking about the thing referred to in the
nodeset
(which might be a structured element itself). It is as if
you have done a 'change directory' to that element. If you said just
"method
", it would refer to a child element of cc
or
expires
. You can also use absolute addressing, like
/data/method
, which would have the same effect as
../method
in this case.
The controls could be written like this (but note that there is no indication that they may get disabled: that is inherited from the value they refer to):
<select1 ref="method"><label>Method of payment:</label> <item><label>Cash</label><value>cash</value></item> <item><label>Credit card</label><value>credit</value></item> </select1> <input ref="cc"><label>Card number:</label></input> <input ref="expires"><label>Expiry date:</label></input>
Try it:
(Source)
This can be simplified by using a structured instance:
<model> <instance><data xmlns=""> <amount/><method/> <cc> <number/><expires/> </cc> </data></instance> <bind nodeset="cc" relevant="../method='credit'"/> </model>
and the controls then reference the children of 'cc
':
<input ref="cc/number"><label>Card number:</label></input> <input ref="cc/expires"><label>Expiry date:</label></input>
although grouping can be used to reset the context of the
ref
s:
<group ref="cc"> <input ref="number"><label>Card number:</label></input> <input ref="expires"><label>Expiry date:</label></input> </group>
A browser is free to decide how disabled controls are presented (and it may also allow you to specify in a stylesheet how they should look), but typically they will be grayed out in the normal way, or hidden entirely. The stylesheet rule could look like:
input::disabled {display: none}
Similarly to relevant
, you can specify a condition under which
a value is read-only. For instance:
<model> <instance><data xmlns=""> <variant>basic</variant><color>black</color> </data></instance> <bind nodeset="color" readonly="../variant='basic'"/> </model>
This example says that the default value of color
is
black
, and can't be changed if variant
has the value
basic
. Try it:
(Source)
(This example will be changed below so that the value of color is also reset
to black if the variant is reset to basic. See the calculate
property shortly).
The stylesheet rule for a readonly element is
input::read-only {...}
A useful new feature in XForms is the ability to state that a value must be supplied before the form is submitted. The simplest case is just to say that a value is always required. For instance, with the search example:
<model> <instance><data xmlns=""><q/></data></instance> <bind nodeset="q" required="true()"/> <submission .../> </model>
but like the readonly
and relevant
attributes, you
can use any XPath expression to make a value conditionally required:
<bind nodeset="state" required="../country='USA'"/>
which says that the value for state
is required when the value
for country
is "USA
". Try it:
(Source)
It is up to the browser to decide how to tell you that a value is required, but it may also allow you to define it in a stylesheet, such as:
input::required { border: thin red solid }
This property allows you to add extra constraints to a value. For instance:
<bind nodeset="year" constraint=". > 1970"/>
constrains the year to be after 1970. Note the XPath use of "." to mean "this value". (">" has to be written as > because of XML rules, but you should be used to that already).
You can combine values, such as:
<bind nodeset="death" constraint=". >= ../birth"/>
Try it:
(Source)
A control, apart from the label can also contain an alert that explains what the restrictions are on a value being collected:
<input ref="death"><label>Year of death</label> <alert>Death year may not be earlier than birth</alert> </input>
It is possible to indicate that a value in the instance is calculated from other values. For instance:
<bind ref="years" calculate="../death - ../birth"/>
When a value is calculated like this, it automatically becomes
readonly
.
(Source)
There are a number of functions available, including arithmetic, string manipulation, date handling, and conditionals using 'if'.
The read-only example above can be adapted to use a constraint to ensure the default value of color applies for basic models:
<model> <instance><data xmlns=""> <variant>deluxe</variant><color>yellow</color> </data></instance> <bind nodeset="color" readonly="../variant='basic'" calculate="if(../variant='basic', 'black', .)"/> </model>
This says that if the variant is basic, then color is set to black, otherwise color keeps the value it has got.
(Source)
Another useful new feature is the ability to give a value a type. The browser can then check that the values match the required type.
For instance, if the search example is actually only for searching for numbers (for instance for searching in a bug database), you only have to add:
<bind nodeset="q" type="integer"/>
This will prevent the value being submitted unless it is an integer. Try it
(this example also uses an alert
element):
(Source)
If you want to collect the URL of someone's homepage, then you can specify
<bind nodeset="homepage" type="anyURI"/>
You will find that some user agents do special things when they know the data type of a value. For instance, when they know that the value is a date, they pop up a date picker rather than require you to type in the characters of the date. Like this:
<bind nodeset="when" type="date"/> ... <input ref="when"><label>Date:</label><input>
(Source)
Similarly, if a value is a boolean, it gets represented as a check box:
<bind nodeset="agree" type="boolean"/> ... <input ref="agree"><label>I agree to all conditions</label></input>
(Source)
There are a number of built-in types you can use, including:
select
)All these types are built in to XForms. If you need to use types defined elsewhere, you can use a prefix in the usual way:
type="xsd:float"
(as usual adding the declaration for the prefix xsd).
If you have several binds referring to the same value, you can combine them:
<bind nodeset="q" type="integer" required="true()"/>
For instance, a credit-card number is a data type, but credit card numbers also have a sort of check-sum built in, which is represented by a constraint:
<bind nodeset="cc" type="card-number" constraint="is-card-number(.)"/>
For more than one form in a document, you need one model per form, but then
you need to identify which form each control refers to. You do this with an
id
attribute on each model, and a model
attribute on
each control:
<model id="search"> <instance><data xmlns=""><q/></data></instance> <submission id="s" .../> </model> <model id="login"> <instance><data xmlns=""><user/><passwd/></data></instance> <submission id="l" .../> </model> ... <input model="search" ref="q"><label>Find</label></input> <submit submission="s"><label>Go</label></submit> ... <input model="login" ref="user"><label>User name</label></input> <secret model="login" ref="passwd"><label>Password</label></secret> <submit submission="l"><label>Log in</label></submit>
There are times when you need more than one instance. For instance, it can be useful in computations to have one instance that contains the values for the current tax regulations, and another instance to collect the values for a particular person. This is easy, since you can have as many instances as you want in a model:
<model>
<instance><data xmlns=""><name/><age/><salary/><taxrate/></data></instance>
<instance id="tax" src="tax.xml"/>
<instance id="currencies" src="currencies.xml"/>
...
</model>
To identify which instance you mean, you use the instance
function:
<input ref="instance('tax')/minimumwage">... <output ref="instance('currencies')/eur">...
The first instance in a model is the default, and 'unadorned' references always refer to that:
<input ref="age">...
The instance
function works in calculations too:
<bind nodeset="taxrate" calculate="if(../salary > instance('tax')/limit, instance('tax')/high, instance('tax')/low)"
If there is a bind
in the model, you can refer to that from the
control instead of directly to the instance value. This allows you to change
the details of how the instance is structured without having to change the
controls. It also means you don't have to specify which model is involved:
<model> <instance><data xmlns=""><q/></data></instance> <submission id="s" .../> <bind id="query" nodeset="q" required="true()"/> </model> ... <input bind="query"><label>Find</label></input>
(Note that the bind
attribute is a reference to an
id
on a bind
element; it is not an XPath
expression.)
As mentioned in the introduction, this is not a full tutorial on XForms. Here are the main features not treated here:
These are all treated in detail in part 2.