Researcher at the Dutch national research centre CWI (first European Internet site - 1988, whole of Europe connected to North America with 64kb link!).
Co-designed the programming language ABC, that was later used as the basis for Python.
In the late 80's designed and built a browser, with extensible markup, stylesheets, vector graphics, client-side scripting, etc. Ran on Mac, Unix, Atari ST.
Organised 2 workshops at the first Web conference in 1994, incuding one on Client-side Computing (this was before Javascript)
Co-author of HTML4, CSS, XHTML, XML Events, XForms, RDFa, etc
Chaired the W3C HTML WG for a decade. Still chair Forms WG
XForms, as the name suggests, was originally designed as a replacement for HTML Forms.
The first version did roughly that, but thanks to generality in the design we realised that with small changes it could do much more: you could use it for other applications as well.
The resultant design is XForms 1.1.
A new version XForms 2.0 is in preparation.
XForms has input, output, and a processing engine. That's all you need for an application.
Although an application may not look like a form, all it is doing is taking some input from the user, and responding to it.
Experience with projects defined with XForms has shown:
Around a ten-times saving in costs, compared with traditional methods.
Because (as you will see) you specify what you are trying to achieve and not how to achieve it, in XForms there is far less administration to worry about. This means: shorter programs.
How much shorter?
One correspondent who was converting a large collection of apps for a company from Javascript to XForms reported that the XForms were about ¼ the size.
Research has shown that development costs of software are dominated by debugging (90%). Other research has shown that the number of bugs in a program don't grow linearly with the size of the program, but the 1.5th power of the length of the program. So a program 10 times larger has 30 times as many bugs (and thus costs 30 times more to produce).
So that means we should expect the production time and cost to reduce to one eighth, about an order of magnitude. And indeed this seems to match experience.
A certain company makes BIG machines (walk in): user interface is very demanding — traditionally needed 5 years, 30 people.
With XForms this became: 1 year, 10 people.
Do the sums. Assume one person costs 100k a year. Then this has gone from a 15M cost to a 1M cost. They have saved 14 million! (And 4 years.)
Manager: I want you to come back to me in 2 days with estimates of how long it will take your teams to make the application
Two days later:
Programming man: I'll need 30 days to work out how long it will take to program it
XForms man: I've already made the application.
XForms, first released in 2002, is a markup language originally designed -- as the name suggests -- to update how forms are handled on the web.
The design was done by doing requirements analysis, and observation of how forms were being done on the web then, and trying to do it better.
Obvious things that were needed included:
Particularly in the use of fixed strings rather than (potentially) calculated values for such things as the submission URI.
As a consequence this restricted what was possible with the language.
As a consequence, XForms 1.1 (2009) addressed these shortcomings, as well as adding a number of 'low-hanging fruits' which various implementations had added.
The resultant language turned out to be far more than a forms language, but a declarative application language.
Since XForms has input, output, and a processing engine, XForms is Turing-complete, and much more than just forms was now possible with the language.
XForms 2.0 is now in preparation. Based on experience with XForms 1.1, it has generalised even further.
There are two essential elements to XForms:
The first is to separate the data from the user interface.
You can see at a glance what data is being used and what is being returned
You can see much more clearly the relationships between differerent values
You can reuse models in different forms.
You can liken them to "data sheets" in the same way as CSS "style sheets".
The second part is that the controls, rather than expressing how they should look (radio buttons, menu, etc), express their intent ("this control selects one value from a list").
You then use styling to say how they should be represented, possibly with different styling for different devices (as a menu on a small screen, as radio buttons on a large screen).
These three controls are all identical (and bound to the same data), except they are presented differently. (All examples in these slides are live)
In a similar way to the use of style sheets, particular choices of interaction are not hard-wired.
Device independence: you can use use different presentations on different devices
Accessibility: since the control states what it does, you can present a suitable alternative for accessibility use.
<model> <instance> <data xmlns=""> <firstname/> <secondname/> </data> </instance> </model>
<input incremental="true" ref="firstname"> <label>First name:</label> </input> <input incremental="true" ref="secondname"> <label>Second name:</label> </input> Your name is: <output value="concat(firstname, ' ', secondname)"/>
<instance> <data xmlns=""> <init>1</init> <cycle>1.5</cycle> <start>1991</start> <end>2013</end> </data> </instance>
<input incremental="true" ref="init"> <label>Initial</label> </input> <input incremental="true" ref="cycle"> <label>Cycle</label> </input> <input incremental="true" ref="start"> <label>Start</label> </input> <input incremental="true" ref="end"> <label>End</label> </input> Final: <output value="init * power(2, (end - start) div cycle)" />
Now to restrict the input to numbers:
<model> <instance> <data xmlns=""> <init>1</init> <cycle>1.5</cycle> <start>1991</start> <end>2013</end> </data> </instance> <bind nodeset="init" type="double" /> <bind nodeset="cycle" type="double"/> <bind nodeset="start" type="double"/> <bind nodeset="end" type="double"/> /model>
In fact this can be expressed even shorter in this case:
<model> <instance> <data xmlns=""> <init>1</init> <cycle>1.5</cycle> <start>1991</start> <end>2013</end> </data> </instance> <bind nodeset="*" type="double" /> /model>
This is because the nodeset
attribute (and the ref attribute on
input
etc.) is an XPath expression. (XForms 1: XPath 1; XForms 2:
XPath 2).
<input incremental="true" ref="init"> <label>Initial</label> <alert>Must be a number</alert> </input>
How this gets displayed depends on the implementation, and the use of style sheets.
In XForms 1, a distinction was made between a single-node binding
and a multiple-node binding. You used ref
for one and
nodeset
for the other.
In XForms 2.0, this distinction is gone at the markup level: you use
ref
for both.
<instance> <data xmlns=""> <init>1</init> <cycle>1.5</cycle> <start>1991</start> <end>2013</end> <iterations/> <final/> </data> </instance> <bind nodeset="*" type="xf:double"/> <bind nodeset="iterations" calculate="(../end - ../start) div ../cycle"/> <bind nodeset="final" calculate="../init * power(2, ../iterations)"/>
Iterations: <output ref="iterations"/> Final: <output ref="final"/>
XForms 1 allowed only one bind per node, so you had to combine binds:
<bind nodeset="sum" type="integer" calculate="../a + ../b" />
XForms 2 allows you to have several binds for one node, as long as they don't conflict.
<bind nodeset="end" constraint=". > ../start"/>
You can use an <alert>
with this too:
<input incremental="true" ref="end"> <label>End</label> <alert>Must be a number, and greater than 'start'</alert> </input>
We have our initial data that looks like this:
<instance> <data xmlns=""> <init>1</init> <cycle>1.5</cycle> <start>1991</start> <end>2013</end> <iterations/> <final/> </data> </instance>
However, it is entirely possible to move that out of the form:
<instance src="data.xml"/>
and the data in a file:
<data> <init>1</init> <cycle>1.5</cycle> <start>1991</start> <end>2013</end> <iterations/> <final/> </data>
The source of the instance data may be anything addressable with a URL
<instance src="http://en.wikipedia.org/w/api.php?action=opensearch&format=xml..."
XForms 1: data must be XML
XForms 2: data can be XML, JSON, CSV, and optionally other types, such as VCard. The data still looks like XML to the form.
So we have now seen types, calculations and constraints.
There are three other properties of data: relevant, readonly and required.
You can make any value required, either conditionally or unconditionally. The indicators are added automatically by the system. Try "USA" as a country: you will see State becomes required:
<model> <instance> <data xmlns=""> <name/> <country/> <state/> </data> </instance> <bind nodeset="name" required="true()"/> <bind nodeset="state" required="../country = 'USA'"/> </model>
And in the body (nothing special here):
<input incremental="true" ref="name"> <label>Name</label> <alert>May not be empty</alert> </input> <input incremental="true" ref="country"> <label>Country</label> </input> <input incremental="true" ref="state"> <label>State</label> <alert>May not be empty</alert> </input>
But in this case, the state isn't relevant for all countries.
So in this version we will say that the state is only relevant if the country is USA, and if relevant, always required. Again, try typing "USA" as the country:
<bind nodeset="name" required="true()"/> <bind nodeset="state" required="true()" relevant="../country = 'USA'"/>
Note that we have made no change to the body in this case. The control appears and disappears based purely on the relevance of the value.
Using stylesheets, you can also choose just to grey out non-relevant fields, rather than making them disappear.
The final model-item property is readonly
, which
unsurprisingly conditionally makes a value read-only.
<bind nodeset="status" readonly="../role = 'beginner'" />
Of course you don't normally want people to enter their country textually,
but by selecting. Here you use the <select>
control:
<select1 class="select1" appearance="minimal" ref="country"> <label>Country:</label> <item> <label>Belgium</label> <value>BE</value> </item> <item> <label>France</label> <value>FR</value> </item> <item> <label>Germany</label> <value>DE</value> </item> ...etc... </select1>
"Appearance" is a hint to the implementation, and may have the values full, compact or minimal.
Especially in the countries case, it is better to have the data in one central place, even more so if there are several controls using the same data.
We can do that by creating an additional instance for the country data (you have some freedom here in the format). We'll keep it small here:
<instance id="countries"> <countries xmlns=""> <country code="BE">Belgium</country> <country code="FR">France</country> <country code="DE">Germany</country> <country code="NL">Netherlands</country> <country code="UK">United Kingdom</country> <country code="USA">United States of America</country> </countries> </instance>
Then in the body:
<select1 ref="country"> <label>Country</label> <itemset nodeset="instance('countries')/country"> <label ref="."/> <value ref="@code"/> </itemset> </select1>
Of course, even better is to put the countries data in one place centrally, and then use.
<instance id="countries" src="countries.xml"/>
Then when a country changes its name, or a country disappears, or new one appears, you can change it once, and all your forms will be updated!
<instance id="default"> <data xmlns=""> <lang>Nederlands</lang> <name/> <age/> <gender/> </data> </instance> <instance id="q" src="labels.xml"/>
<questions> <set name="Nederlands"> <language>Taal</language> <name>Naam</name> <age>Leeftijd</age> ... <set name="English"> ...
<input ref="name"> <label> <output ref="instance('q')/set[@name=instance('default')/lang]/name"/> </label> </input>
Now you can just add a new set of labels for a new language to the labels file, and the form will update to the new language automatically.
Some forms/apps are perfectly standalone (for instance a form to calculate the date of Easter for a year.)
But of course you often need to submit data.
XForms allows you to submit any instance, serialized in a number of different ways, and then specify what should happen with the returned data. You have fairly fine-grain control over when data is submitted.
For instance
<model> <instance> <data xmlns=""> <q/><n>10</n> </data> </instance> <submission action="http://example.com/search" method="get" /> </model>
and then:
<body> <input ref="q" label="Search"/> <submit label="Go"/> </body>
Clicking on the submit button would cause the instance data to be submitted to the URL in the action attribute, with the data URL-encoded , eg:
http://example.com/search?q=test&n=10
The whole document would be replaced with the result.
However, an application normally wants to get the results and do something
with it. To this end, the submission element has an attribute
replace
. Usually you want to put the results in a named instance,
for which you use replace="instance"
<submission action="http://example.com/search" method="get" replace="instance" instance="results"/>
In XForms 1: returned data must in general be XML if it is to replace an instance
In XForms 2: also allowed JSON, CSV, and optionally other types.
Suppose you want to preload an instance with some data, for instance an address, change the address, and then save it.
First step is to get the address:
<instance id="reference"> <data xmlns=""> <reference/> </data> </instance> <instance id="address"/>
<submission ref="instance('reference')" action="http://whatever" method="get" replace="instance" instance="address"/>
<submission ref="instance('address')" action="..." method="..." replace="none"/>
Similar to the onclick
style of processing, but generalised,
XForms allows you to catch and respond to events. The whole of the XForms
processing model has events that you can respond to. For instance
<setvalue ev:event="xforms-ready" ref="state" value="0"/>
Which sets an instance value when XForms starts.
<setfocus ev:event="xforms-ready" control="search"/>
which positions the focus on an initial control when XForms starts.
<send ev:event="xforms-value-changed" submission="submit1"/>
Which causes data to be submitted when the value bound to a control changes.
There is a control <switch>
that allows you to switch
between different interface elements:
<switch> <case id="init"> ... </case> <case id="next"> ... </case> ... <switch>
You toggle between the different cases with a <toggle>
action:
<toggle ev:event="..." case="next"/>
XForms 2 will add to this, by allowing the switch to be data-driven:
<switch caseref="state"> ...
Example
There are a number of ways you can implement XForms
A big advantage of server-side implementations is 'write once, run anywhere', since the server can sniff the device and deliver a version suitable for that device. Novell had a ground-breaking example of that.
Many companies use XForms either internally or externally, and have their own implementations, either for internal use or for licensing. For instance:
As you would expect with a new technology, first adopters are within companies and vertical industries that have control over the software environment used.
Very close to going to last call.
Already got (partial) implementations.
Hopefully ready next year.