以下内容引自:http://www.w3.org/MarkUp/Forms/2003/xforms-for-html-authors.html
Steven Pemberton, W3C/CWI
Version date: 28 October 2003
XForms is the new markup language for forms on the Web. This document is a quick introduction to XForms for HTML Forms authors. It shows you how to convert existing forms to their XForms equivalent. It assumes knowledge of HTML Forms, so is not a beginner's tutorial. 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.
*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. So in this case the minimum you need to put in the head is:
<model> <submission action="http://example.com/search" method="get" id="s"/> </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 submission="s"><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" id="s"/> </model> </h:head> <h:body> <h:p> <input ref="q"><label>Find</label></input> <submit submission="s"><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:f="http://www.w3.org/2002/xforms"> <head> <title>Search</title> <f:model> <f:submission action="http://example.com/search" method="get" id="s"/> </f:model> </head> <body> <p> <f:input ref="q"><f:label>Find</f:label></f:input> <f:submit submission="s"><f:label>Go</f:label></f:submit> </p> </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.
In the future, XHTML2 will allow you to write forms without prefixes.
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).
See later under 'initial values' for how to give any control an initial value.
Message: <textarea name="message" rows="20" cols="80"></textarea>
is written
<textarea ref="message"><label>Message:</label></textarea>
Styling, such as the height and width here, is done using a style sheet. For instance, put this in your style sheet
textarea[ref="message"] { font-family: sans-serif; height: 20em; width: 80em }
Although this mimics the HTML behavior, there is no requirement that you use a sans serif 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 }
The easiest way to include a style sheet in your document is to add this at the beginning of the document:
<?xml version="1.0"?> <?xml-stylesheet href="style.css" type="text/css"?>
where 'style.css' is the name of your stylesheet.
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).
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>
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>
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>Clear all fields</label> <reset ev:event="DOMActivate"/> </trigger>
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.
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"
<input type="image" src="..." ...>
is written 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}
(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>
.
XForms has two controls that are not in HTML, output
and range
.
The output
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 submitted.
You can also calculate values:
Total volume: <output value="height * width * depth"/>
(where height
, width
and depth
are values collected by other controls.)
This control allows you to specify a constraint on a value.
<range ref="volume" start="1" end="10" 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" id="s"/> </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 we've used the tag <data>
here, but you can choose any tag you like.)
For initialising controls including initialising 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 we want to add a hidden value results
to the search form, we 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, we can make a simple form to edit the page instead:
<model> <instance src="http://www.example.com/shop/status.xhtml"/> <submission action="http://www.example.com/shop/status.xhtml" method="put" id="change"/> </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 submission="change"><label>OK</label></submit>
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).
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>
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.
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.
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.
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>
If we used a structured instance, we could simplify this:
<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>
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
.
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
".
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.
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).
It is possible to indicate that a value in the instance is calculated from other values. For instance:
<bind ref="volume" calculate="../height * ../width * ../depth"/>
When a value is calculated like this, it automatically becomes readonly
.
There are a number of functions available, including arithmetic, string manipulation, date handling, and conditionals using 'if'.
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), then we only have to add:
<bind nodeset="q" type="xsd:integer"/>
This will prevent the value being submitted unless it is an integer.
(You then need to add xmlns:xsd="http://www.w3.org/2001/XMLSchema"
to the root element.)
If you want to collect the URL of someone's homepage, then you can specify
<bind nodeset="homepage" type="xsd: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.
There are a number of useful built-in types you can use, including:
select
)
If you have several binds referring to the same value, you can combine them:
<bind nodeset="q" type="xsd:integer" required="true()"/>
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></input> <submit submission="l"><label>Log in</label></submit>
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:
Events and actions: how to handle events and built-in actions.
Schemas: how to define your own types.
p3ptype: identifying privacy-related values.
Switch: wizard-like behavior of filling in a form in stages.
Repeat: shopping-cart like behavior where items can be added and deleted.
本文地址:http://com.8s8s.com/it/it43222.htm