XForms, a combination of two of the most successful experiments ever performed with the Web: XML and forms.
--Micah Dubinko
For my current contract they could have saved months of effort by using XForms instead of standard HTML forms. We're talking thousands and thousands of lines of JSP code that could be thrown in the trash. I love nothing more than throwing code away ... love it.
--Kimbro Staken
It's not surprising that XForms is raising hackles and ruffling feathers since it has the potential to displace a language that a lot of people have spent a lot of time learning and building businesses around. But just as I gave up assembler programming to use C, so I now gladly drop spaghetti-script for XForms. It's not perfect and there are plenty of new features that I would like to see introduced, but its most important role has been to demonstrate that we don't need to be wedded to the old approaches for ever, and that new solutions are possible, and here today.
--Mark Birbeck
I personally like XForms. However, I think it is a lost cause on the popular Web for three reasons:
It's not backwards compatible with existing Web content and existing Web browsers,
It uses too many levels of abstraction to be understood by most authors.
It requires the use of many namespace prefixes.
None of these problems really have anything to do with XForms features per se. It is IMHO possible to bring many of XForms features (especially the declarative constraints ideas) to authors without introducing the other problems. For instance, by just extending HTML's form features instead of making a totally new language.
--Ian Hickson, Opera
Mix presentation and content
Limited user interface widgets
No client side validation
Round trips to server required to do anything significant
No data type aware controls
Excessively simple data model: a list of name=value pairs; all values are strings
Limited to browser environments; not good enough for rich user interfaces
JavaScript can help with some but not all of this
Users turn JavaScript off.
JavaScript often not supported by robots and other non-standard browsers
JavaScript has accessibility problems
Cross-browser incompatibilities make JavaScript hard to author.
3GL web apps: AJAX, GWT
4GL web apps: XForms, Web Apps 1.0, HTML forms
Principle of least power (security, accessibility)
Principle of most power (power)
Easy to deploy; zero install
Straight-forward to author
Excessively simple data model: a list of name=value pairs; all values are strings
Machine accessible (Doesn't require a human to fill them out)
Widely available
Strong typing for easier input validation
XML format for input data
Much more internationalizable and localizable
Much more accessible to handicapped users
Far more device independent: scales from cell phones to servers
Scriptless actions
An XForm has three parts:
A model that shows the data to be submitted.
One or more abstract user interface controls (the view), each of which is bound to a particular element in the model via an XPath expression.
A submission (the controller) that connects the user interface to the model
Each form has a model that shows the data to be submitted:
<model xmlns="http://www.w3.org/2002/xforms" id="p1"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<instance>
<doughnuts xmlns="http://www.example.org/doughnuts/">
<quantity xsi:type="xsd:nonNegativeInteger"/>
</doughnuts>
</instance>
<submission>
We'll fill this in later...
</submission>
</model>
The single child element
of the instance
element is sent to the server.
The XML element sent to the server can have any well-formed structure and use any namespace.
In XHTML, this model
is contained in
the head
of the document.
Each form has a group of input
elements
that specifies the user interface for the model:
<input xmlns="http://www.w3.org/2002/xforms"
model="p1"
ref="/doughnuts/quantity">
<label>Quantity</label>
</input>
There can (and generally will be)
be more than one input
element in the group.
The group can appear anywhere in the XHTML document, interspersed with other markup.
The browser updates the model as the user fills in data.
The browser checks the data the user enters against the schema.
A submit
element in the HTML body
draws a user interface control that enables the user
to submit the form:
<submit xmlns="http://www.w3.org/2002/xforms" submission="q0">
<label>Order</label>
</submit>
A submission
element in the
model
specifies where and how the data is transmitted:
<model xmlns="http://www.w3.org/2002/xforms" id="p1"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<instance>
<doughnuts xmlns="http://www.example.org/doughnuts/">
<quantity xsi:type="xsd:nonNegativeInteger"/>
</doughnuts>
</instance>
<submission action="http://www.example.org/formprocessor.php"
method="post" id="q0" />
</model>
When the user submits the form, the browser
posts
the model element to the URL specified by the action
attribute.
The server responds with an HTTP 200 OK and a typical HTML page (or with various error messages)
<?xml version="1.0"?>
<!-- <!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"xhtml1-strict.dtd"> -->
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<head>
<title>Doughnuts!</title>
<model xmlns="http://www.w3.org/2002/xforms" id="p1">
<instance>
<doughnuts xmlns="http://www.example.org/doughnuts/">
<quantity xsi:type="xsd:nonNegativeInteger"/>
</doughnuts>
</instance>
<submission action="http://sinex.tml.hut.fi:8080/xforms/request"
method="post" id="q0" />
</model>
</head>
<body>
<h1>Order Doughnuts</h1>
<input xmlns="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events"
model="p1"
ref="/doughnuts/quantity"
class="edit" >
<label>Quantity</label>
</input>
<p>
I can put any XHTML markup and text here I like.
The form can be interspersed throughout the page.
Namespaces are used to tell which elements are XHTML
and which are XForms.
</p>
<submit xmlns="http://www.w3.org/2002/xforms" submission="q0">
<label>Order</label>
</submit>
</body>
</html>
Receive the contents of the instance as an XML document:
POST /xforms/request HTTP/1.1
Content-type: application/xml
Accept: application/xml.application/xhtml+xml;q=0.9,text/plain;q=0.8,image/png
User-Agent: X-Smiles/0.93/20050131
Accept-language: en-us,en;q=0.5
Host: sinex.tml.hut.fi:8080
Content-length: 290
<?xml version="1.0" encoding="ISO-8859-1"?>
<doughnuts xmlns="http://www.example.org/doughnuts/">
<quantity xsi:type="xsd:nonNegativeInteger">32</quantity>
</doughnuts>
Process in PHP, Servlets, JSP, ASP, CGI, etc.
Use any XML API you like
Respond with a standard HTTP response header and document body
Various attributes can be placed on the submission
element to control the serialization of the submitted instance document:
<submission
action="http://www.example.org/formprocessor.php"
method="post" id="q0"
version="1.0"
indent="false"
encoding="ISO-8859-1"
omit-xml-declaration="true"
/>
version
: 1.0 or 1.1
indent
: whether or not to pretty print the submission
encoding
: Character encoding for the submission
omit-xml-declaration
: whether or not to include an XML declaration with the submission
cdata-section-elements
: list of elements whose contents are emitted as CDATA sections rather than using & escaping or numeric character references
Mostly these are copied from XSLT. However values are "true"
and "false"
rather than "yes"
and "no"
.
Default is replace="all"
<submission replace="instance"/>
indicates that only
the instance data in the document should be replaced with the content
of the response
output
elements in the original
XHTML document can show the new data
Like XMLHttpRequest but no scripting
Put a schema
attribute on the
model
element.
<model xmlns="http://www.w3.org/2002/xforms" id="p1"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
schema="doughnuts.xsd" >
<instance>
<doughnuts xmlns="http://www.example.org/doughnuts/">
<quantity/>
</doughnuts>
</instance>
<submission action="http://www.example.org/formprocessor.php"
method="post" id="q0" />
</model>
Useful for more complex constraints: derived types, complex types, etc.
Fill in the value rather than using an empty element.
<model xmlns="http://www.w3.org/2002/xforms" id="p1"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<instance>
<doughnuts xmlns="http://www.example.org/doughnuts/">
<quantity xsi:type="xsd:nonNegativeInteger">12</quantity>
</doughnuts>
</instance>
<submission action="http://www.example.org/formprocessor.php"
method="post" id="q0" />
</model>
input
: a basic text field
textarea
: a multiline text field
select
: choose any number of items from a list
select1
: choose one item from a list
submit
: send the form data as specified in the model's submission
secret
: passwords and the like
output
: display non-editable value
upload
: upload a file or data stream
range
: choose from a range of values
trigger
: for an event
Certain common attributes apply to all controls:
<forms:input
id="state_shipping"
class="data_entry"
ref="order/shipTo/state"
cols="4"
model="shipping"
style="font-family: Helvetica, sans"
appearance="compact">
<forms:label>State:</forms:label>
</forms:input>
id
attribute for linking and CSS
class
attribute for CSS
ref
attribute selects the one node in the model this control updates
nodeset
attribute selects several nodes in the model this control updates
cols
attribute to specify number of characters
model
attribute to choose between multiple forms
style
attribute to attach CSS
appearance
attribute to choose full, compact, or minimal display
<forms:input
accesskey="r"
navindex="3"
incremental="false"
inputmode="upperCase">
<forms:label>State:</forms:label>
</forms:input>
accesskey
keyboard shortcut to move to control
navindex
tab order
incremental="true"
update the model in real time as the data is typed.
inputmode
to choose script or script subset (upper or lower case, digits, symbols, kana, arabic, traditionalHanzi, etc.)
label
is required:
<input xmlns="http://www.w3.org/2002/xforms"
model="p1"
ref="/doughnuts/quantity">
<!-- Always shown -->
<label>Quantity</label>
<!-- If the user asks -->
<help>Tell us how many doughnuts you want; e.g. 3</help>
<!-- tool tip or some such -->
<hint>They're really yummy!</hint>
<!-- If the user makes a mistake -->
<alert>
<output ref="/doughnuts/quantity"/> is not a valid number of doughnuts.
</alert>
</input>
help
, hint
, and alert
are optional
Must appear in this order:
label
, help
, hint
, and alert
Multiline text
<textarea ref="message/body">
<label>Message Body</label>
<hint>Enter the text of your message here</hint>
</textarea>
Choose any number of items from a list
Can be implemented as checkboxes, combo box, something else
<select ref="pz:toppings">
<label>Flavors</label>
<choices>
<item>
<label>Pepperoni</label>
<value>pprn</value>
</item>
<item>
<label>Ham</label>
<value>ham</value>
</item>
<item>
<label>Pineapple</label>
<value>pnnp</value>
</item>
<item>
<label>Anchovies</label>
<value>anch</value>
</item>
<item>
<label>Garlic</label>
<value>garl</value>
</item>
<item>
<label>Sausage</label>
<value>ssge</value>
</item>
</choices>
</select>
Choose exactly one item from a list
May be implemented as radio buttons, choice menu, something else
<select1 ref="cc:type">
<label>Credit Card</label>
<item>
<label>American Express</label>
<value>amex</value>
</item>
<item>
<label>Visa</label>
<value>visa</value>
</item>
<item>
<label>Mastercard</label>
<value>mc</value>
</item>
</select1>
Allow the user to specify a value not in the list
selection="open"
attribute
<select ref="pz:toppings" selection="open">
<label>Flavors</label>
<choices>
<item>
<label>Pepperoni</label>
<value>pprn</value>
</item>
<item>
<label>Ham</label>
<value>ham</value>
</item>
<item>
<label>Pineapple</label>
<value>pnnp</value>
</item>
<item>
<label>Anchovies</label>
<value>anch</value>
</item>
<item>
<label>Garlic</label>
<value>garl</value>
</item>
<item>
<label>Sausage</label>
<value>ssge</value>
</item>
</choices>
</select>
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="forms.xsl"?>
<form xmlns:xfm="http://www.w3.org/2002/xforms" height="30cm">
<xfm:model id="form1">
<xfm:submission id="submit1" method="post"
target="http://localhost:8080/examples/servlet/XFormsServlet"/>
<xfm:schema src="simple1.xsd"/>
<xfm:instance id="instance1" xmlns="">
<?xml2-stylesheet type="text/xsl" href="../demo/fo/submit.xsl"?>
<purchaseOrder>
<shipTo>
<firstname></firstname>
<lastname></lastname>
<email></email>
<organization></organization>
<subject></subject>
<comment></comment>
</shipTo>
<itemlist>xsmiles_personal xsmiles_support</itemlist>
</purchaseOrder>
</xfm:instance>
</xfm:model>
<h1>X-Smiles Feedback</h1>
<xfm:input xform="form1" ref="purchaseOrder/shipTo/firstname" cols="30">
<xfm:label>FIRST NAME:</xfm:label>
</xfm:input>
<xfm:input ref="purchaseOrder/shipTo/lastname" cols="30">
<xfm:label>LAST NAME:</xfm:label>
</xfm:input>
<xfm:input xform="form1" ref="purchaseOrder/shipTo/email" cols="30">
<xfm:label>EMAIL:</xfm:label>
</xfm:input>
<xfm:input xform="form1" ref="purchaseOrder/shipTo/organization" cols="30">
<xfm:label>ORGANIZATION:</xfm:label>
</xfm:input>
<xfm:select1 xform="form1" ref="purchaseOrder/shipTo/subject"
style="list-ui:radio;hip:hop">
<xfm:hint>Please select one</xfm:hint>
<xfm:label>SUBJECT:</xfm:label>
<xfm:item>Compliment</xfm:item>
<xfm:item>Opinion</xfm:item>
<xfm:item>Criticism</xfm:item>
<xfm:item>Suggestion</xfm:item>
<xfm:item>Error</xfm:item>
</xfm:select1>
<xfm:textarea xform="form1" ref="purchaseOrder/shipTo/comment" rows="5"
style="font-size:10px; font-weight:bold; color:red; width:200px; height:70px;">
<xfm:label>Please enter your comments in the area below:</xfm:label>
</xfm:textarea>
<xfm:submit name="Submit" ref="test" submission="submit1">
<xfm:hint>Click to submit</xfm:hint>
<xfm:label>Submit</xfm:label>
</xfm:submit>
</form>
An input whose data is hidden
<secret ref="/userinfo/password">
<label>Password</label>
<hint>Mother's maiden name</hint>
</secret>
Choose some data stream to upload: file, camera phone photo, video, audio recording, etc.
ref
attribute identifies part of model that holds the Base-64 encoded contents
mediatype
attribute specifies the types of files the user can select
filename
element identifies part of model that holds the filename
mediatype
element identifies part of model that holds the MIME type of the file
Can submit as multipart/related rather than just Base-64 encoding everything
<upload ref="patch" mediatype="text/*">
<label>Select image:</label>
<filename ref="@name" />
<mediatype ref="@mimetype" />
</upload>
Selects from a range of numeric or date-time values
start
attribute specifies minimum
end
attribute specifies maximum
step
attribute specifies increment
incremental="true"
attribute updates model in real time
Can be implemented as a slider, dial, list of possible values, or something else
<range ref="/settings/volume" start="1" end="11" step="0.1">
<label>Volume</label>
<hint>These go to 11.</hint>
</range>
Not editable
ref
attribute points to current value of model piece using XPath
value
attribute calculates using XPath expression
Mutually exclusive
Page updates as user fills in form without JavaScript or server round-trip
Total: <output ref="order/total" />
Tax: <output value="0.825 * order/total" />
Changing the widget does not require changing the markup.
<?xml version="1.0" encoding="ISO-8859-1"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xfm="http://www.w3.org/2002/xforms"
xml:lang="fi">
<meta:meta xmlns:meta="http://www.xsmiles.org/2002/metadata"
name="Datatype-Aware Controls"
description="Tests datatype awareness of XForms implementation" />
<head>
<style type="text/css">
body {
background-color: #dddddd;
}
input,output,range {display:block;}
input::value {
width: 200px;
font-weight:bold;
}
output::value {
width: 200px;
font-weight:bold;
color:blue;
background-color: #dddddd;
}
label
{
color:black;
}
</style>
<link rel="stylesheet" type="text/css" href="../xforms.css" />
<xfm:model id="form1" schema="simple.xsd">
<xfm:submission id="submit1" method2="postxml" localfile="temp2.xml"
target2="http://www.hut.fi/"/>
<xfm:instance id="instance1" xmlns="">
<?xml2-stylesheet type="text/xsl" href="../demo/fo/submit.xsl"?>
<purchaseOrder>
<shipTo>
<volume>2</volume>
<name>Alice Smith</name>
<street>123 Maple Street</street>
<city type="ao">Mill Valley</city>
<state>CA</state>
<zip>16</zip>
<shipped>false</shipped>
<selection>Ghana</selection>
<static>
<data>333</data>
</static>
<text>Original</text>
<date>2002-10-23</date>
</shipTo>
<itemlist>xsmiles_personal xsmiles_support</itemlist>
</purchaseOrder>
</xfm:instance>
</xfm:model>
</head>
<body>
<h1>Adaptive inputs</h1>
<p>The inputs in this page adapt to the datatype of the bound instance
item. (Note that there are 2 inputs per item, to show that data flows
in/out between the controls and the instance.</p>
<h2><input></h2>
<p>
<xfm:input model="form1" ref="shipTo/street"
incremental="true" inputmode="test">
<xfm:label>xsd:string</xfm:label>
<xfm:hint>This should be plain text textfield.</xfm:hint>
</xfm:input>
<xfm:input model="form1" ref="shipTo/street"
incremental="false" inputmode="test">
<xfm:label>xsd:string</xfm:label>
<xfm:hint>This should be plain text textfield.</xfm:hint>
</xfm:input>
</p>
<p>
<xfm:input model="form1" ref="shipTo/date" >
<xfm:label>xsd:date</xfm:label>
<xfm:hint>This should be a calendar control.</xfm:hint>
</xfm:input>
<xfm:input model="form1" ref="shipTo/date" >
<xfm:label>Ship By:</xfm:label>
<xfm:hint>This should be a calendar control.</xfm:hint>
</xfm:input>
</p>
<p>
<xfm:input model="form1" ref="shipTo/shipped">
<xfm:label>xsd:boolean</xfm:label>
<xfm:hint>This should be checkbox.</xfm:hint>
</xfm:input>
<xfm:input model="form1" ref="shipTo/shipped">
<xfm:label>Are you married?</xfm:label>
<xfm:hint>This should be checkbox.</xfm:hint>
</xfm:input>
</p>
<p>
<xfm:input model="form1" ref="shipTo/zip">
<xfm:label>xsd:decimal</xfm:label>
<xfm:hint>This should be decimal inputbox.</xfm:hint>
</xfm:input>
<xfm:input model="form1" ref="shipTo/zip">
<xfm:label>xsd:decimal</xfm:label>
<xfm:hint>This should be decimal inputbox.</xfm:hint>
</xfm:input>
</p>
<h2><range></h2>
<p>
<xfm:range model="form1" ref="shipTo/zip" start="-1.5" end="20.5" step="1.5">
<xfm:label>xsd:decimal</xfm:label>
<xfm:hint>This should be a slider.</xfm:hint>
</xfm:range>
<xfm:range model="form1" ref="shipTo/zip" start="4.0">
<xfm:label>xsd:decimal</xfm:label>
<xfm:hint>This should be a slider.</xfm:hint>
</xfm:range>
</p>
<h2><output></h2>
<xfm:output model="form1" ref="shipTo/street"
incremental="true" inputmode="test">
<xfm:label>xsd:string</xfm:label>
<xfm:hint>This should be an output string.</xfm:hint>
</xfm:output>
<xfm:output model="form1" ref="shipTo/date" >
<xfm:label>xsd:date</xfm:label>
<xfm:hint>This should be an output string.</xfm:hint>
</xfm:output>
<xfm:output model="form1" ref="shipTo/shipped">
<xfm:label>xsd:boolean</xfm:label>
<xfm:hint>This should be an output string.</xfm:hint>
</xfm:output>
<xfm:output model="form1" ref="shipTo/zip">
<xfm:label>xsd:decimal</xfm:label>
<xfm:hint>This should be an output string.</xfm:hint>
</xfm:output>
<xfm:submit name="Submit" submission="submit1">
<xfm:hint>Click to submit</xfm:hint>
<xfm:label>Submit</xfm:label>
</xfm:submit>
</body>
</html>
<?xml version="1.0" encoding="ISO-8859-1"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xforms="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:my="test"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<meta:meta
xmlns:meta="http://www.xsmiles.org/2002/metadata"
name="XForms Controls"
description="Tests all XForms controls in single document" />
<head>
<link rel="stylesheet" type="text/css" href="xforms.css" />
<xforms:model id="form1">
<xforms:submission id="submit1" method="post"
action="http://sinex.hut.mediapoli.com:8080/xforms/request"/>
<xforms:instance id="instance1" xmlns="" >
<my>
<input>Initial input</input>
<secret>Initial secret</secret>
<output>Initial output</output>
<textarea>Initial textarea</textarea>
<range>5</range>
<select1>1</select1>
<select>1</select>
<selectboolean>true</selectboolean>
<message>Message read from the instance</message>
<upload xsi:type="xsd:base64Binary"/>
</my>
</xforms:instance>
<xforms:bind nodeset="/my/selectboolean" type="xsd:boolean"/>
</xforms:model>
</head>
<body>
<p>
<h1>All XForms form controls</h1>
<p class="headline"><textarea></p>
<xforms:textarea ref="/my/textarea">
<xforms:label>Textarea Form Control</xforms:label>
</xforms:textarea>
<xforms:textarea ref="/my/textarea">
<xforms:label>Textarea Form Control</xforms:label>
</xforms:textarea>
<p class="headline"><input></p>
<p>
<xforms:input ref="/my/input" xmlns:my="test">
<xforms:label>Input Form Control</xforms:label>
</xforms:input>
</p>
<p class="headline"><output></p>
<xforms:output ref="/my/output" xmlns:my="test">
<xforms:label>Input Form Control</xforms:label>
</xforms:output>
<p class="headline"><secret></p>
<xforms:secret ref="/my/secret">
<xforms:label>Secret Form Control</xforms:label>
</xforms:secret>
<p class="headline"><upload></p>
<xforms:upload ref="/my/upload">
<xforms:label>Select File</xforms:label>
</xforms:upload>
<p class="headline"><select1></p>
<p>
<xforms:select1 ref="/my/select1" appearance="full">
<xforms:label>appearance="full"</xforms:label>
<xforms:item>
<xforms:value>1</xforms:value>
<xforms:label>1st</xforms:label>
</xforms:item>
<xforms:item>
<xforms:value>2</xforms:value>
<xforms:label>2nd</xforms:label>
</xforms:item>
<xforms:item>
<xforms:value>3</xforms:value>
<xforms:label>3rd</xforms:label>
</xforms:item>
</xforms:select1>
<xforms:select1 ref="/my/select1" appearance="compact">
<xforms:label>appearance="compact"</xforms:label>
<xforms:item>
<xforms:label>1st</xforms:label>
<xforms:value>1</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>2nd</xforms:label>
<xforms:value>2</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>3rd</xforms:label>
<xforms:value>3</xforms:value>
</xforms:item>
</xforms:select1>
<xforms:select1 ref="/my/select1" appearance="full">
<xforms:label>appearance="full"</xforms:label>
<xforms:item>
<xforms:label>1st</xforms:label>
<xforms:value>1</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>2nd</xforms:label>
<xforms:value>2</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>3rd</xforms:label>
<xforms:value>3</xforms:value>
</xforms:item>
</xforms:select1>
<xforms:select1 ref="/my/select1" appearance="minimal">
<xforms:label>appearance="minimal"</xforms:label>
<xforms:item>
<xforms:label>1st</xforms:label>
<xforms:value>1</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>2nd</xforms:label>
<xforms:value>2</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>3rd</xforms:label>
<xforms:value>3</xforms:value>
</xforms:item>
</xforms:select1>
</p>
<p class="headline"><select></p>
<p>
<xforms:select ref="/my/select">
<xforms:label>select Form Control</xforms:label>
<xforms:item>
<xforms:label>1st</xforms:label>
<xforms:value>1</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>2nd</xforms:label>
<xforms:value>2</xforms:value>
</xforms:item>
<xforms:item>
<xforms:label>3rd</xforms:label>
<xforms:value>3</xforms:value>
</xforms:item>
</xforms:select>
</p>
<p class="headline"><button></p>
<xforms:trigger>
<xforms:label>Click Me</xforms:label>
<xforms:message level="ephemeral" ev:event="click" ref="/my/message"/>
</xforms:trigger>
<p>
<xforms:selectboolean ref="/my/selectboolean">
<xforms:label>Selectboolean</xforms:label>
</xforms:selectboolean>
</p>
<p class="headline"><selectBoolean> (X-Smiles extension)</p>
<p>
<xforms:input ref="/my/selectboolean">
<xforms:label>input</xforms:label>
</xforms:input>
</p>
<p class="headline"><submit></p>
<xforms:submit>
<xforms:label>Submit Me</xforms:label>
</xforms:submit>
<p class="headline"><selectBoolean> (X-Smiles extension)</p>
<p class="headline"><reset></p>
<xforms:trigger>
<xforms:label>Reset</xforms:label>
<xforms:reset ev:event="DOMActivate"/>
</xforms:trigger>
</p>
</body>
</html>
Send mail+attachments
URL Generation (Demonstrates GET)
<instance>
<my:order>
<my:item>
<my:amount />
<my:discount />
</my:item>
</my:order>
</instance>
<bind nodeset="my:item/my:discount"
calculate="../my:amount * 0.1"
type="xsd:decimal" />
bind
element in the model associates an XPath calculation with particular elements in the instance
nodeset
attribute chooses the nodes whose values are calculated
calculate
attribute contains the XPath expression that's evaluated to give the values for those nodes
Optional type
attribute specifies schema type for the expression result
Side-effect free (unlike JavaScript)
<?xml version="1.0" encoding="ISO-8859-1"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xforms="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:my="test">
<head>
<link rel="stylesheet" type="text/css" href="xformsdemo.css" />
<xforms:model id="form1">
<xforms:submission id="submit1" method2="postxml"
localfile="temp2.xml" target2="http://www.hut.fi/"/>
<xforms:instance id="instance1" xmlns="" >
<sms>
<number>555-556</number>
<text/>
<length>
<current>0</current>
<left></left>
<maximum>160</maximum>
</length>
</sms>
</xforms:instance>
<xforms:bind ref="/sms/length/current"
calculate="string-length(/sms/text)"/>
<xforms:bind ref="/sms/length/left"
calculate="../maximum - ../current"
constraint="/sms/length/left > -1"/>
</xforms:model>
</head>
<body>
<p class="headline">SMS Message</p>
<p>This example demonstrates the incremental changes to the instance.
Every character typed into the message will trigger the calculation of
the remaining characters.</p>
<p>
<xforms:input ref="/sms/number">
<xforms:label>Telephone number</xforms:label>
</xforms:input>
</p>
<p>
<xforms:output ref="/sms/length/left" >
<xforms:label>Characters left</xforms:label>
</xforms:output>
</p>
<p>
<xforms:textarea ref="/sms/text" incremental="true">
<xforms:label>Message</xforms:label>
</xforms:textarea>
</p>
<p>
<xforms:trigger>
<xforms:label>Duplicate</xforms:label>
<xforms:setvalue ev:event="DOMActivate" ref="/sms/text" value="concat(.,.)"/>
</xforms:trigger>
</p>
<p>
<xforms:submit submission="submit1">
<xforms:label>Send</xforms:label>
</xforms:submit>
</p>
</body>
</html>
All XPath 1.0 functions: starts-with()
, number()
, count()
, string-length(),
etc.
Spec defined extension functions:
boolean boolean-from-string(string)
: true if the argument is "true" or "1", false if the argument is "false" or "0"; otherwise an exception is thrown
string if(boolean, string, string)
: ternary (?:
) operator
number avg(node-set)
: arithmetic mean
number min(node-set)
: smallest numeric value, or NaN
number max(node-set)
: largest numeric value, or NaN
number count-non-empty(node-set)
: number of non-empty nodes in the argument
index(string)
: the current 1-based position of the repeat index for the identified repeat
element
string property(string)
: XForms property
string now()
: current time
number days-from-date(string)
: number of days since January 1, 1970
number seconds-from-dateTime(string)
: number of seconds since midnight, January 1, 1970
number seconds(string)
: number of seconds in a duration
number months(string)
: number of months in a duration
node-set instance(string)
: instance data by ID
User and vendor defined extension functions
Repeating forms
Triggers
Events
Actions to be invoked in response to events
Vendor extensions
Other binding attributes:
relevant
readonly
required
constraint
FormsPlayer free-beer plug-in for Internet Explorer 6 on Windows
X-Smiles is open source and written in Java
Work is ongoing to integrate XForms into Mozilla
Mozquito DENG zero-install XForms uses Flash
Novell Java XForms Engine
Oracle XForms Engine for Mobile Devices
IBM XML Forms Package can "compile" XForms+XHTML into pure HTML
XForms is not a Web standard. It's a relatively new spec seeing early-adopter use in intranets.
--Brendan Eich
Non-Web, non-browser environments that need forms such as OpenOffice 2.0
Early adopter intranets that can install plug-ins
Server-side conversion to legacy HTML+JavaScript
Intranets that can standardize on Firefox
You can update a document rather than replacing it
You can update parts of a document as the user types data in the form without travelling to the server first
You can freely mix HTML and forms controls throughout the document. Layout is much simpler.
Complex data can be submitted in arbitrarily complex XML; no more mapping everything to ASCII name=value query strings
Current implementations are shaky
Not zero install (yet)
GET is trickier than POST
PUT and DELETE support
power
, luhn
, current
and property
XPath extension functions
An e-mail address datatype
An ID card number datatype
A duplicate
action element and a corresponding xforms-duplicate event
A destroy
action element and a corresponding xforms-destroy event
An xforms-close event
An xforms-submit-serialize event
Inline rendition of non-text media types
Works in today's web browsers, including IE
Less ambitious
Scripting dependent
Richer UI but not richest
A worse-is-better solution?
XForms Essentials by Micah Dubinko, O'Reilly, 2003
XForms: XML Powered Web Forms by T.V. Raman, Addison-Wesley, 2003
XForms for HTML Authors by Steven Pemberton
This presentation: http://www.cafeconleche.org/slides/sd2008west/xforms/
XForms 1.0 specification: http://www.w3.org/TR/xforms/
Top 10 XForms Engines: http://www.xml.com/pub/a/2005/02/09/xforms.html