xforms basics - the melonfire community - trog

28
Community Trog Copyright notice: This article is copyright Melonfire, 2014. All rights reserved. All source code, brand names, trademarks and other content contained herein is proprietary to Melonfire, 2014. All rights reserved. Source code within this article is provided with NO WARRANTY WHATSOEVER. It is meant for illustrative purposes only, and is NOT recommended for use in production environments. Copyright infringement is a violation of law. Printed from http://www.melonfire.com/community/columns/trog/article.php?id=224 XForms Basics (part 1) Use XForms to manage the display, input and processing of form data on the Web. X Hits The Spot A year or two ago, XML was heard about more often than it was seen, a technology that was sufficiently arcane enough to keep all but the most hardened geeks at bay. No more is this the case; today, XML is most definitely in the mainstream, and proving its mettle by making all kinds of new and unique applications possible (witness the success of Amazon.com's AWS service, or the Google APIs, both based on XML technology). XML isn't resting on its laurels, though. As the technology is becoming more and more popular, XML development groups operating under the aegis of the World Wide Web Consortium are rapidly inventing new and interesting ways to use it. One of the more interesting ideas is XForms, which uses XML to manage the display, input and processing of user-inputted data on the Web. If you're at all serious about using XML, you're going to need to understand XForms. And over the course of this tutorial, I'm going to assist you in this endeavour by explaining the fundamentals of the XForms data model, together with some examples of how it can be used. Before we get going, though, a few disclaimers: First, I don't claim to be an expert on XForms. Much of the material in this tutorial is based on my own research with the XForms specifications and varied XForms implementations, or gleaned from late-night email conversations over beer and stale pizza. In other words - caveat emptor! Second, as new XML standards are proposed and disposed, the material here may become invalid; you should always refer to the most current standard or recommendation for up-to-date information. This tutorial is based on the W3C's XForms 1.0 recommendation dated 14 October 2003, at http://www.w3.org/TR/2003/REC-xforms-20031014/ Now that I have that off my chest - let's get started! Out With The Old... Before getting into the details of how XForms works, it's important to understand the context in which it was developed, and the need and rationale behind it. You know that HTML already allows user interaction with a Web application, through the use of forms and associated form controls like text entry fields, checkboxes and radio buttons. However, The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=224 1 of 9 4/22/2014 8:14 AM

Upload: ajay-j-verma

Post on 27-Apr-2017

222 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: XForms Basics - The Melonfire Community - Trog

Community

Trog

Copyright notice:

This article is copyright Melonfire, 2014. All rights reserved.

All source code, brand names, trademarks and other content contained herein is proprietary to

Melonfire, 2014. All rights reserved.

Source code within this article is provided with NO WARRANTY WHATSOEVER. It is meant for

illustrative purposes only, and is NOT recommended for use in production environments.

Copyright infringement is a violation of law.

Printed from http://www.melonfire.com/community/columns/trog/article.php?id=224

XForms Basics (part 1)Use XForms to manage the display, input and processing of form data on the Web.

X Hits The Spot

A year or two ago, XML was heard about more often than it was seen, a technology that was

sufficiently arcane enough to keep all but the most hardened geeks at bay. No more is this the case;

today, XML is most definitely in the mainstream, and proving its mettle by making all kinds of new

and unique applications possible (witness the success of Amazon.com's AWS service, or the Google

APIs, both based on XML technology).

XML isn't resting on its laurels, though. As the technology is becoming more and more popular, XML

development groups operating under the aegis of the World Wide Web Consortium are rapidly

inventing new and interesting ways to use it. One of the more interesting ideas is XForms, which

uses XML to manage the display, input and processing of user-inputted data on the Web.

If you're at all serious about using XML, you're going to need to understand XForms. And over the

course of this tutorial, I'm going to assist you in this endeavour by explaining the fundamentals of

the XForms data model, together with some examples of how it can be used.

Before we get going, though, a few disclaimers:

First, I don't claim to be an expert on XForms. Much of the material in this tutorial is based on my

own research with the XForms specifications and varied XForms implementations, or gleaned from

late-night email conversations over beer and stale pizza. In other words - caveat emptor!

Second, as new XML standards are proposed and disposed, the material here may become invalid;

you should always refer to the most current standard or recommendation for up-to-date

information. This tutorial is based on the W3C's XForms 1.0 recommendation dated 14 October

2003, at http://www.w3.org/TR/2003/REC-xforms-20031014/

Now that I have that off my chest - let's get started!

Out With The Old...

Before getting into the details of how XForms works, it's important to understand the context in

which it was developed, and the need and rationale behind it.

You know that HTML already allows user interaction with a Web application, through the use of

forms and associated form controls like text entry fields, checkboxes and radio buttons. However,

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=224

1 of 9 4/22/2014 8:14 AM

Page 2: XForms Basics - The Melonfire Community - Trog

although HTML forms are simple to understand and easy to use, they do have a couple of

drawbacks:

1. HTML forms can usually be viewed (and used) only in a Web browser - they don't render too well

on handhelds, cellphones or other devices.

2. Processing form input in the Web world usually requires the services of a programmer, who must

code the business logic need for form data validation, input parsing and further data manipulation

and processing.

3. Unless you put in a great deal of thought at the design stage (and sometimes not even then),

HTML forms cannot be easily reused across different applications, or even within an application.

These drawbacks might seem trivial in the context of today's Internet - it ain't broke, you're

probably thinking, so why fix it? - but they assume serious proportions in the context of an XML

world, which is built around data and the relationships inherent in it.

...In With The New

XForms was designed to address these drawbacks, and also breathe fresh life into traditional

approaches to handling user input in a client-server paradigm.

If you take a look at the requirements document for XForms - it's available online at

http://www.w3.org/TR/xhtml-forms-req - you'll see that XForms was designed to enable the

"separation of the data being collected from the markup of the controls collecting the individual

values". Right at the outset, then, the XForms specification makes a clear distinction between the

form model (what the form does) and its controls (what it looks like).

A simple example of this might be a form which asks for your gender - in a Web browser, you'd be

presented with radio buttons or a drop-down list, while on a cellphone, you'd be asked to enter a

particular number corresponding to the choices. This distinction between form (no pun intended)

and function makes it possible to use a single form model on multiple platforms and devices, by

defining what the form is supposed to do once, and then further defining the user interface for each

device or platform to be supported separately.

XForms also come with built-in data typing capabilities and event handlers, making it possible to

validate user input without having to resort to complex scripting or server-side business logic.

XForms can even be integrated with the validation rules laid down in XML Schemas, to further

centralize application logic and reduce the impact of changes in business rules.

Another good thing about XForms, especially as we move to a more XML-centric world, is its native

support for the XML standard. Data entered into an XForm is usually submitted to the receiving

application in XML format. This simplifies integration with third-party tools (which are gradually

becoming XML-aware) and also reduces the need for complex data processing and manipulation

routines, as the submitted data can easily be parsed using standard SAX or DOM interfaces.

There's only one problem - while the theory is certainly exciting, practical implementation still

leaves a lot to be desired. The W3C's XForms site at http://www.w3.org/MarkUp/Forms/ lists a

number of different XForms implementations, but the technology has yet to make an appearance in

any popular browser; this makes it harder to test and research.

Of the different implementations available, the examples in this tutorial were tested with

FormsPlayer (http://www.formsplayer.com/), though you will also get good results with X-Smiles, a

Java browser (http://www.x-smiles.org/) and Novell's XForms (http://www.novell.com/xforms).

Expect to spend some time with the documentation for each of these implementations to get your

XForms development environment up and running (tip: I found FormsPlayer to be the simplest to

install, as it integrates directly with Internet Explorer 6.0)

What's In A Name?

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=224

2 of 9 4/22/2014 8:14 AM

Page 3: XForms Basics - The Melonfire Community - Trog

Let's start with a simple example that demonstrates the functionality of XForms.

<html xmlns=" http://www.w3.org/1999/xhtml" ; xmlns:xforms=" http://www.w3.org/2002/xforms/cr"> ;<head>

<!-- define the form model --><xforms:model id="enter"> <xforms:instance> <user> <name /> </user> </xforms:instance></xforms:model>

<basefont face="Arial"></head>

<body><font size="+1">What's In A Name?</font><br /><br / >

<!-- define the form interface --><xforms:input id="txtname" model="enter" ref="/user /name"> <xforms:label>Name</xforms:label> <xforms:hint>Enter your name, then press TAB</xf orms:hint></xforms:input>

<br />

<!-- do something with the input -->Welcome to XForms, <xforms:output model="enter" ref ="/user/name" />

</body></html>

Let's look at this line by line.

The first basic rule when dealing with XForms is that they cannot exist as independent entities;

instead, they're designed to be integrated with XHTML (or other markup) documents. That's why the

XForm above is enclosed within a regular XHTML document, and why the XHTML namespace has

been referenced at the top.

<html xmlns=" http://www.w3.org/1999/xhtml" ; xmlns:xforms=" http://www.w3.org/2002/xforms/cr"> ;...</html>

Note that in addition to the XHTML namespace, when dealing with XForms, you'll also need to

specify the XForms namespace, which is currently "http://www.w3.org/2002/xforms/cr";.

<!-- define the form model --><xforms:model id="enter">...</xforms:model>

The second basic rule when working with XForms is this: every XForm consists of two primary

components, a form model (which specifies functionality) and one or more form controls (which

handles presentation).

The form model, indicated by the <xforms:model> element, defines what the form does. This model

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=224

3 of 9 4/22/2014 8:14 AM

Page 4: XForms Basics - The Melonfire Community - Trog

defines the data to be captured/modified by the form as well as the logical components that govern

how the form behaves on user interaction (including where the form should be submitted and how

to handle the various form events). The model also includes information on the bindings between

the form controls and the instance data, and can optionally link to external XML Schemas for

validation purposes.

The <xforms:model> element is usually accompanied with an "id" attribute, which contains a name

for the model; this name is used by the form controls in order to link the interface section of the

form to the correct form model. Obviously, this also means that you can have multiple models with

a single XHTML file, and link to each one by its name. Additionally, since the form model only

defines how the form works and has nothing to do with its presentation, it can easily be reused,

either within the same application or in other applications or platforms.

Typically, the <xforms:model> element appears within the <head> of the document, and encloses

an <xforms:instance> element.

<!-- define the form model --><xforms:model id="enter"> <xforms:instance> <user> <name /> </user> </xforms:instance></xforms:model>

The <xforms:instance> element defines the "instance data" for the form. This instance data is an

XML tree representation of the values associated with the form, and it can be defined inline (as

above) or imported from an external XML file. In this case, the XML structure is pretty simple - a

single root element called <user> encompassing one child element called <name>.

Normally, the <xforms:model> element would also contain information on where the form is to be

submitted via the <xforms:submission> element, data bindings via the <xforms:bind> element and

event handlers via the <xforms:action> element - I'll be discussing those shortly, so don't worry too

much about them for the moment.

Once the form model has been defined, it's time to define the other half of the puzzle - the form

controls, or how the form looks. XForms provides a bunch of elements to accomplish this - by and

large, they map neatly into the HTML form controls you're already familiar with, and appear within

the <body> of the document.

<!-- define the form interface --><xforms:input id="txtname" model="enter" ref="/user /name"> <xforms:label>Name</xforms:label> <xforms:hint>Enter your name, then press TAB</xf orms:hint></xforms:input>

The first (and simplest) of these controls is the <xforms:input> element, which represents a text

entry field. Note my use of the "model" attribute to tell the XForms processor which form model this

control belongs to, and the "ref" attribute to tell it which node in the instance data tree this

particular value maps to. XPath expressions are used in the latter - in case you don't know what

those are, take a look at http://www.melonfire.com/community/columns/trog/article.php?id=83 and

they should make a little more sense to you.

<!-- do something with the input -->Welcome to XForms, <xforms:output model="enter" ref ="/user/name" />

Another useful (though not often used) form control is the <xforms:output> element, which is used

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=224

4 of 9 4/22/2014 8:14 AM

Page 5: XForms Basics - The Melonfire Community - Trog

to display the value of a particular node from the XML instance data tree. Note again my usage of

the "model" and "ref" attributes to link the control to the model and instance data tree defined in

the <head> of the document.

If you were to try viewing the XForm above in an XForms-capable browser, you'd see something like

this:

Pretty cool, huh?

Welcome To Nowhere

The previous example demonstrated two of the form controls available in XForms. However, there

are lots more - here's a brief list:

<xforms:input> a single-line text entry field

<xforms:secret> a single-line text entry field which masks user input, good forpasswords

<xforms:select> a list field allowing multiple selection

<xforms:select1> a list field allowing selection of only a single item from thelist

<xforms:textarea> a multi-line text entry field

<xforms:upload> a file upload field

<xforms:range> a field which restricts entry t o a range of values

<xforms:submit> a form submission field

<xforms:output> a field for displaying values f rom the instance data

In addition, the XForms specification also defines the following elements, which may be attached to

the controls above:

<xforms:label> descriptive information for the corresponding control

<xforms:help> help information for the corres ponding control

<xforms:hint> brief usage information for the corresponding control

Here's an example demonstrating some of them in action:

<html xmlns=" http://www.w3.org/1999/xhtml" ; xmlns:xforms=" http://www.w3.org/2002/xforms/cr"> ;

<head>

<!-- form model --><xforms:model id="immigration"> <xforms:instance src="immigration.xml" />

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=224

5 of 9 4/22/2014 8:14 AM

Page 6: XForms Basics - The Melonfire Community - Trog

</xforms:model><basefont face="Arial">

</head>

<body>

<!-- define interface controls --><table cellspacing="5" cellpadding="5" border="0"><tr><td colspan="2" align="center"><font color="red" si ze="4">Welcome toImmigration</font></td></tr>

<tr><td> <xforms:input id="txtname" model="immigration" r ef="/immigrant/name"> <xforms:label>Name</xforms:label> <xforms:hint>Enter your name here</xforms:hin t> </xforms:input></td></tr>

<tr><td> <xforms:input id="txtcitizenship" model="immigra tion" ref="/immigrant/citizenship"> <xforms:label>Citizenship</xforms:label> <xforms:hint>Enter your country of origin her e</xforms:hint> </xforms:input></td>

</tr><tr><td align="left"> <xforms:select1 model="immigration" ref="/immigr ant/purpose" appearance="full"> <xforms:label>Purpose of visit</xforms:label> <xforms:hint>Please state the purpose of your visit</xforms:hint> <xforms:item> <xforms:label>Business</xforms:label> <xforms:value>B</xforms:value> </xforms:item> <xforms:item> <xforms:label>Pleasure</xforms:label> <xforms:value>P</xforms:value> </xforms:item> <xforms:item> <xforms:label>Other</xforms:label> <xforms:value>O</xforms:value> </xforms:item> </xforms:select1></td></tr>

<tr><td align="left"> <xforms:select model="immigration" ref="/immigra nt/immunization"appearance="full"> <xforms:label>Immunization</xforms:label> <xforms:hint>Please select the diseases that you have been immunizedagainst</xforms:hint> <xforms:item> <xforms:label>Smallpox</xforms:label> <xforms:value>100</xforms:value> </xforms:item> <xforms:item> <xforms:label>Malaria</xforms:label> <xforms:value>113</xforms:value> </xforms:item>

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=224

6 of 9 4/22/2014 8:14 AM

Page 7: XForms Basics - The Melonfire Community - Trog

<xforms:item> <xforms:label>Yellow fever</xforms:label> <xforms:value>56</xforms:value> </xforms:item> <xforms:item> <xforms:label>Typhoid</xforms:label> <xforms:value>174</xforms:value> </xforms:item> </xforms:select></tr>

<tr><td align="left"> <xforms:textarea model="immigration" ref="/immig rant/address"> <xforms:label>Address in home country</xforms :label> </xforms:textarea></td></tr></table>

</body></html>

First up, the definition of the XForms model. Unlike the previous example, I've defined the instance

data tree in a separate file and imported it via the "src" attribute.

<!-- form model --><xforms:model id="immigration"> <xforms:instance src="immigration.xml" /></xforms:model><basefont face="Arial">

Here's what "immigration.xml" looks like:

<?xml version="1.0" encoding="iso-8859-1"?><!-- immigration.xml --><immigrant> <name /> <citizenship /> <purpose /> <immunization /> <address /></immigrant>

You've already seen how to use an <xforms:input> element in previous examples, so I won't go into

the details again. Do note, however, my usage of the <xforms:label> and <xforms:hint> elements

within it - these come in handy to provide descriptive human-readable information about the

control.

<xforms:input id="txtname" model="immigration" r ef="/immigrant/name"> <xforms:label>Name</xforms:label> <xforms:hint>Enter your name here</xforms:hin t> </xforms:input>

The <xforms:select1> element allows the user to select one item from a series of options:

<xforms:select1 model="immigration" ref="/immigr ant/purpose" appearance="full"> <xforms:label>Purpose of visit</xforms:label> <xforms:hint>Please state the purpose of your visit</xforms:hint>

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=224

7 of 9 4/22/2014 8:14 AM

Page 8: XForms Basics - The Melonfire Community - Trog

<xforms:item> <xforms:label>Business</xforms:label> <xforms:value>B</xforms:value> </xforms:item> <xforms:item> <xforms:label>Pleasure</xforms:label> <xforms:value>P</xforms:value> </xforms:item> <xforms:item> <xforms:label>Other</xforms:label> <xforms:value>O</xforms:value> </xforms:item> </xforms:select1>

Within the <xforms:select1> element, the list of available choices are defined via one or more

<xforms:item> elements, each of which must have a label and value; the former is displayed to the

user and the latter is passed to the server on submission.

A special "appearance" attribute in the <xforms:select1> element can be used to control the display

of the element in the browser ("full" for a list of all values, "minimal" for a minimum number of

values, and "compact" for a scrollable list).

Similar, though not identical to the above, is the <xforms:select> element, which allows the user to

select more than one value from the options available.

<xforms:select model="immigration" ref="/immigra nt/immunization"appearance="full"> <xforms:label>Immunization</xforms:label> <xforms:hint>Please select the diseases that you have been immunizedagainst</xforms:hint> <xforms:item> <xforms:label>Smallpox</xforms:label> <xforms:value>100</xforms:value> </xforms:item> <xforms:item> <xforms:label>Malaria</xforms:label> <xforms:value>113</xforms:value> </xforms:item> <xforms:item> <xforms:label>Yellow fever</xforms:label> <xforms:value>56</xforms:value> </xforms:item> <xforms:item> <xforms:label>Typhoid</xforms:label> <xforms:value>174</xforms:value> </xforms:item> </xforms:select>

As before, the choices are defined via a series of <xforms:label> and <xforms:value> elements,

while the "appearance" attribute can be used to control the appearance of the control ("full" for a

list of all values, "minimal" for a minimum number of values, and "compact" for a scrollable list).

Finally, the <xforms:textarea> element is used to display a multi-line text entry box, suitable for

use with large blocks of text.

<xforms:textarea model="immigration" ref="/immig rant/address"> <xforms:label>Address in home country</xforms :label> </xforms:textarea>

And here's what it all looks like:

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=224

8 of 9 4/22/2014 8:14 AM

Page 9: XForms Basics - The Melonfire Community - Trog

Now, all this is fine and dandy - but how about submitting the form and actually doing something

with the user's data?

Well, that's a whole new kettle of fish, one which involves jumping through a complicated series of

hoops involving the <xsd:submission> element. I don't plan to discuss it now - instead, I'm going to

defer it to the second segment of this tutorial and instead encourage you to spend the interim

playing with the various form controls to understand how they work. Each control comes with

specific properties that can be used to customize its behaviour - so take a look at the specification,

get comfortable with them, try out a couple of implemetations, and come back next week to take

the next step in our XForms journey!

Note: Examples are illustrative only, and are not meant for a production environment. Melonfire

provides no warranties or support for the source code described in this article. YMMV!

Copyright notice:

This article is copyright Melonfire, 2014. All rights reserved.

All source code, brand names, trademarks and other content contained herein and proprietary to

Melonfire, 2014. All rights reserved.

Source code within this article is provided with NO WARRANTY WHATSOEVER. It is meant for

illustrative purposes only, and is NOT recommended for use in production environments.

Copyright infringement is a violation of law.

Printed from http://www.melonfire.com/community/columns/trog/article.php?id=224

Copyright © 1998-2014 Melonfire. All rights reservedTerms and Conditions | Feedback

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=224

9 of 9 4/22/2014 8:14 AM

Page 10: XForms Basics - The Melonfire Community - Trog

Community

Trog

Copyright notice:

This article is copyright Melonfire, 2014. All rights reserved.

All source code, brand names, trademarks and other content contained herein is proprietary to

Melonfire, 2014. All rights reserved.

Source code within this article is provided with NO WARRANTY WHATSOEVER. It is meant for

illustrative purposes only, and is NOT recommended for use in production environments.

Copyright infringement is a violation of law.

Printed from http://www.melonfire.com/community/columns/trog/article.php?id=226

XForms Basics (part 2)Find out how to submit XForms data to a server-side script or save it to a local client file.

Revving Up

In the first part of this series, I gave you a quick introduction to the newly-released XForms 1.0

specification, by explaining the fundamental concepts of the XForms model. I showed you how to

define an XForms model and form instance data, as well as the logical components that govern how

the form behaves on user interaction. I also took you on a whirlwind tour of the various input

controls available in XForms 1.0 - as you will have seen, these controls correspond closely with the

controls available in traditional HTML, and then some.

Now, all this is fine and dandy - but how about submitting the form and actually doing something

with the user's data? Well, that's where this article comes in. Over the next few pages, I'm going to

answer this vexing question, showing you how to handle form submissions on both the server and

the client. XForms offers the creative developer an immense amount of control over the process,

primarily by doing away with the traditional name=value submission format in favour of standard

XML markup for user data.

I won't just stop there, though. Once you've understood how to store user data on the server with

XForms, I'll show you how to control the quality of that data by having XForms validate user input

at the time of submission. As you'll see, XForms' built-in support for data validation means you don't

need JavaScript or server-side logic any more. Instead, you can quality-control user input through

built-in XForms constructs or - if you want to get really advanced - hook your XForms up to an XML

Schema to enforce more sophisticated validation and typing rules.

Excited? I hope so.

Welcome To Immigration

I'll begin with a simple XForm, one that you're already familiar with from the previous segment of

this tutorial:

<html xmlns=" http://www.w3.org/1999/xhtml" ; xmlns:xforms=" http://www.w3.org/2002/xforms/cr"> ;

<head>

<!-- form model --><xforms:model id="immigration">

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=226

1 of 12 4/22/2014 8:13 AM

Page 11: XForms Basics - The Melonfire Community - Trog

<xforms:instance src="immigration.xml" /> <xforms:submission id="submit" action="/tmp/immi grant.xml" method="put" /></xforms:model><basefont face="Arial">

</head>

<body>

<!-- define interface controls --><table cellspacing="5" cellpadding="5" border="0"><tr><td colspan="2" align="center"><font color="red" si ze="4">Welcome toImmigration</font></td></tr>

<tr><td> <xforms:input id="txtname" model="immigration" r ef="/immigrant/name"> <xforms:label>Name</xforms:label> <xforms:hint>Enter your name here</xforms:hin t> </xforms:input></td></tr>

<tr><td> <xforms:input id="txtcitizenship" model="immigra tion" ref="/immigrant/citizenship"> <xforms:label>Citizenship</xforms:label> <xforms:hint>Enter your country of origin her e</xforms:hint> </xforms:input></td>

</tr><tr><td align="left"> <xforms:select1 model="immigration" ref="/immigr ant/purpose" appearance="full"> <xforms:label>Purpose of visit</xforms:label> <xforms:hint>Please state the purpose of your visit</xforms:hint> <xforms:item> <xforms:label>Business</xforms:label> <xforms:value>B</xforms:value> </xforms:item> <xforms:item> <xforms:label>Pleasure</xforms:label> <xforms:value>P</xforms:value> </xforms:item> <xforms:item> <xforms:label>Other</xforms:label> <xforms:value>O</xforms:value> </xforms:item> </xforms:select1></td></tr>

<tr><td align="left"> <xforms:select model="immigration" ref="/immigra nt/immunization"appearance="full"> <xforms:label>Immunization</xforms:label> <xforms:hint>Please select the diseases that you have been immunizedagainst</xforms:hint> <xforms:item> <xforms:label>Smallpox</xforms:label> <xforms:value>100</xforms:value> </xforms:item> <xforms:item> <xforms:label>Malaria</xforms:label>

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=226

2 of 12 4/22/2014 8:13 AM

Page 12: XForms Basics - The Melonfire Community - Trog

<xforms:value>113</xforms:value> </xforms:item> <xforms:item> <xforms:label>Yellow fever</xforms:label> <xforms:value>56</xforms:value> </xforms:item> <xforms:item> <xforms:label>Typhoid</xforms:label> <xforms:value>174</xforms:value> </xforms:item> </xforms:select></tr>

<tr><td align="left"> <xforms:textarea model="immigration" ref="/immig rant/address"> <xforms:label>Address in home country</xforms :label> </xforms:textarea></td></tr></table>

<xforms:submit submission="submit"> <xforms:label>Save</xforms:label> <xforms:hint>Save the information entered above to a local file</xforms:hint></xforms:submit>

</body></html>

Looks familiar? It should - this is the same form I used to demonstrate the various input controls

earlier, with one important addition: the ability to actually do something with the data once it has

been entered by the user.

The XForms specification defines an <xforms:submission> element, that specifies how form

submission is to be handled. Typically, this element appears in the <head> of the document, within

an <xforms:model> element, and contains information on the URL to which the form is to be

submitted, the method of submission, and the format and structure of the submitted XML. Here's an

example:

<xforms:submission id="submit" action="/tmp/immigra nt.xml" method="put" />

This is similar to the data that appears in the standard HTML <form> tag. Note the addition of an

"id" element - this is used to link the <xforms:submission> element with the actual form submit

button - and the method used (PUT, because in this first example, I'll be writing the form data to a

local file, not a server storage engine).

The <xforms:submission> element is only part of the puzzle. The other half is the submit button

itself, represented by the <xforms:submit> input control (remember this from last time's lesson?).

Here's what it looks like:

<xforms:submit submission="submit"> <xforms:label>Save</xforms:label> <xforms:hint>Save the information entered above to a local file</xforms:hint></xforms:submit>

Pretty standard, this - like other input controls, it contains optional <xforms:label> and

<xforms:hint> elements to give the user additional information on what it's supposed to do. The

novel thing here, though, is the additional "submission" attribute, which associates this submit

button with the <xforms:submission> element defined in the XForms model. Because of this link,

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=226

3 of 12 4/22/2014 8:13 AM

Page 13: XForms Basics - The Melonfire Community - Trog

the <xforms:submit> element will trigger the "action" specified in the <xforms:submission>

element when invoked.

Now, let's give it a whirl to see it if works as advertised. Enter some data into the form and hit the

"Save" button. Then, navigate to the location specified in the "action" attribute and open up the

target file in a text editor. You should see the data you entered, formatted in XML as per your form

model. Here's an example:

<!-- immigration.xml--><immigrant><name>Chewbacca</name><citizenship>Tatoo ine</citizenship><purpose>B</purpose><immunization>56 113 100</immun ization><address>PlanetTatooine</address></immigrant>

Behind the scenes, here's what happens when the form is submitted:

1. An "xforms-submit" event is triggered (more on events shortly).

2. The instance data tree beginning at the root specified in the <xforms:submission> element is

selected. If no root is specified (as in the example above), the entire instance data tree is selected.

3. The selected instance data is validated as per validation rules that may be specified in the XForm.

If an error occurs in validation, processing stops and an exception is generated.

4. If the data passes all the validation tests, it is serialized and submitted using the information

provided in the "method" and "action" attributes of the <xforms:submission> element.

Data Overload

The previous example showed you how to store the information provided by the user in a local file

on the client. Though this seems interesting at first glance, it isn't very useful in real life (when was

the last time you wanted to do this?) Most often, you would want the data to be sent to the server,

safe and secure in a database or other storage engine. How does XForms stand up to this challenge?

Pretty well, actually - and it even adds some interesting attributes to control the data being

submitted.

In order to demonstrate, I'll revise the previous example to submit the user data to a server-side

script, which takes care of adding it to a MySQL database. In this example, the database is called

"db1", the table is called "immigrants", and the SQL code to create the table looks like this:

CREATE TABLE `immigrants` ( `id` int(11) NOT NULL auto_increment, `name` varchar(30) NOT NULL default '', `citizenship` varchar(50) NOT NULL default '', `purpose` char(1) NOT NULL default '', `immunization` varchar(50) NOT NULL default '', `address` varchar(255) NOT NULL default '', PRIMARY KEY (`id`))

As you can see, this is pretty straightforward stuff, with each field of the table mapping to a node in

the XML file created in the previous example.

Next up, altering the XForm model to point to a server-side PHP script instead of a local file:

<!-- form model --><xforms:model id="immigration"> <xforms:instance src="immigration.xml" /> <xforms:submission id="submit" action="/scripts/ register.php" method="post" />

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=226

4 of 12 4/22/2014 8:13 AM

Page 14: XForms Basics - The Melonfire Community - Trog

</xforms:model>

Notice that no change is needed to the form input controls, or any other section of the XForm - this

is an example of the separation between form and function that XForms promises.

Finally, here's the PHP script that takes the submitted form data and converts it into an INSERT

query:

<?php

// initialize some variables;$currentTag = "";$values = array();$allowedFields = array("name", "citizenship", "purp ose", "immunization", "address");

// database parameters$host = "localhost";$usr = "john";$pwd = "doe";$db = "db1";

// handlersfunction startElementHandler($parser, $name, $attri butes){ global $currentTag; $currentTag = $name;}

function endElementHandler($parser, $name){ global $values, $currentTag; global $connection, $table; if(strtolower($name) == "immigrant") { // generate SQL $query = "INSERT INTO immigrants"; $query .= "(name, citizenship, purpose, immun ization, address)"; $query .= "VALUES(\"" . join("\",\"",$values) . "\");"; // uncomment for debug purposes // print $query; // execute query $result = mysql_query($query) or die("Error i n query: $query. " .mysql_error()); // reset variables $values = array(); $currentTag = ""; }}

function characterDataHandler($parser, $data){ global $currentTag, $values, $allowedFields; $currentTag = strtolower($currentTag); if(in_array($currentTag, $allowedFields) && trim ($data) != "") { $values[$currentTag] = mysql_escape_string($d ata); } }

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=226

5 of 12 4/22/2014 8:13 AM

Page 15: XForms Basics - The Melonfire Community - Trog

$parser = xml_parser_create();

// get the XML data$data = $HTTP_RAW_POST_DATA;

// set SAX parser optionsxml_parser_set_option($parser,XML_OPTION_CASE_FOLDI NG,0);xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE ,1);

// set element handlersxml_set_element_handler($parser, "startElementHandl er", "endElementHandler");xml_set_character_data_handler($parser, "characterD ataHandler");

// connect to database$conn = mysql_connect($host, $usr, $pwd) or die("Un able to connect to the database");mysql_select_db($db) or die("Unable to select datab ase");

// parse XMLif (!xml_parse($parser, $data )){ die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser)));}

// clean upxml_parser_free($parser);mysql_close();

?>

Now try it out and see for yourself - enter some data into the form, submit it and then check the

database to see if your values were inserted correctly. Here's what you might see:

mysql> SELECT * FROM immigrants;+----+-----------+-------------+---------+--------- -----+-----------------+| id | name | citizenship | purpose | immuniza tion | address |+----+-----------+-------------+---------+--------- -----+-----------------+| 1 | Chewbacca | Tatooine | B | 56 113 | Planet Tatooine |+----+-----------+-------------+---------+--------- -----+-----------------+1 row in set (0.00 sec)

How did this happen? Well, unlike traditional forms, which submit data using name-value pairs,

XForms submits data as a well-formed XML document. This document can then be parsed using

either a DOM or SAX parser, or even transferred directly to any other application that understands

XML.

PHP comes with a built-in SAX parser, which is what I've used in the example above to parse the

XML document. SAX, or the Simple API for XML, is one of the most common methods of parsing an

XML document. Essentially, a SAX parser reads the XML document sequentially, triggering specific

user-defined functions when it finds an opening tag, character data, closing tag, CDATA block and so

on. In the example above, these user-defined functions are called startElementHandler(),

endElementHandler() and characterDataHandler().

$parser = xml_parser_create();xml_set_element_handler($parser, "startElementHandl er", "endElementHandler");xml_set_character_data_handler($parser, "characterD ataHandler");

Of these, the major work in the script above is done by the characterDataHandler() function - this

reads the various values entered by the user from the XML document tree and builds the SQL query

after using the mysql_escape_string() function to make the values ready for insertion in the

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=226

6 of 12 4/22/2014 8:13 AM

Page 16: XForms Basics - The Melonfire Community - Trog

database.

function characterDataHandler($parser, $data){ global $currentTag, $values, $allowedFields; $currentTag = strtolower($currentTag); if(in_array($currentTag, $allowedFields) && trim ($data) != "") { $values[$currentTag] = mysql_escape_string($d ata); } }

The script above won't make much sense to you unless you've played a little with SAX. In case you

haven't, drop by http://www.melonfire.com/community/columns/trog/article.php?id=71 and find out

what you missed, then come back here and review the script again. You can also read more about

SAX at http://www.saxproject.org/ and http://www.xmlphp.com/

You can also parse the XML document submitted by the XForm using the DOM - I leave that to you

as an exercise.

A Custom Job

In addition to the attributes you've already seen, the <xforms:submission> element also comes with

a bunch of others, which can assist in customizing the manner in which the form data is submitted.

Here's a brief list:

"ref" - specifies the node to use as root when submitting instance data, defaults to /

"version" - specifies XML version to use when submitting form data

"indent" - toggles indenting of XML data in form submission

"encoding" - specifies XML encoding to use when submitting form data

"omit-xml-declaration" - toggles XML declaration when submitting form data

"standalone " - toggles standalone declaration when submitting form data

"replace" - specifies what to do with the response to the submission

Consider the following example, which demonstrates some of these in action:

<html xmlns=" http://www.w3.org/1999/xhtml" ; xmlns:xforms=" http://www.w3.org/2002/xforms/cr"> ;

<head>

<!-- form model --><xforms:model id="information"> <xforms:instance> <user> <name /> <email /> <age /> </user> </xforms:instance> <xforms:submission id="submit" ref="/user/name" action="/tmp/user.xml"method="put" indent="yes" omit-xml-declaration="no" />

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=226

7 of 12 4/22/2014 8:13 AM

Page 17: XForms Basics - The Melonfire Community - Trog

</xforms:model><basefont face="Arial">

</head>

<body>

<!-- define interface controls --><table cellspacing="5" cellpadding="5" border="0"><tr><td> <xforms:input id="txtname" model="information" r ef="/user/name"> <xforms:label>Name</xforms:label> <xforms:hint>Enter your name here</xforms:hin t> </xforms:input></td></tr>

<tr><td> <xforms:input id="txtemail" model="information" ref="/user/email"> <xforms:label>Email address</xforms:label> <xforms:hint>Enter your email address here</x forms:hint> </xforms:input></td>

<td> <xforms:input id="txtage" model="information" re f="/user/age"> <xforms:label>Age</xforms:label> <xforms:hint>Enter your age here</xforms:hint > </xforms:input></td>

</table>

<xforms:submit submission="submit"> <xforms:label>Save</xforms:label> <xforms:hint>Save the information entered above to a local file</xforms:hint></xforms:submit>

</body></html>

In this case, I've explicitly told the XForms processor to include the XML declaration in the final form

submission, but to only include that part of the instance data tree beginning with the element

<name>. Here's the output:

<?xml version="1.0" encoding="ISO-8859-1"?><name>Ha rish</name>

It's important to note, also, that XForms supports submitting data in more than just PUT and POST

methods, and that if you really need to, you can even replicate the behaviour of traditional HTML

forms by submitting your data in the standard name=value format. The method atribute of the

<xforms:submission> element can take any of the values "post", "get", "put", "multipart-post" and

"form-data-post" - take a look at the specification to see what each one of these does.

Not My Type

Speak to any Web developer, and they're sure to complain about the need to write complex

JavaScript code to carry out elementary data validation on form input. With XForms, they are no

longer hostage to JavaScript - XForms is closely integrated with XML Schema, and can use XML

Schema datatypes to perform both simple and complex form validation. Take a look at the next

example, which illustrates:

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=226

8 of 12 4/22/2014 8:13 AM

Page 18: XForms Basics - The Melonfire Community - Trog

<html xmlns=" http://www.w3.org/1999/xhtml" ; xmlns:xforms=" http://www.w3.org/2002/xforms/cr"> ;<head>

<!-- define the form model --><xforms:model id="enter"> <xforms:instance> <user xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" ; xmlns:xsd=" http://www.w3.org/2001/XMLSchema"> ; <name xsi:type="xsd:string" /> <age xsi:type="xsd:integer" /> <dob xsi:type="xsd:date" /> <height xsi:type="xsd:float" /> <weight xsi:type="xsd:decimal" /> <immunizaton xsi:type="xsd:boolean" /> </user> </xforms:instance></xforms:model>

<basefont face="Arial">

</head>

<body>

<font size="+1">So you wanna join The Army?</font>< br /><br />

<!-- form controls --><xforms:input id="txtname" model="enter" ref="/user /name"> <xforms:label>Name</xforms:label> <xforms:hint>Enter your name</xforms:hint> <xforms:alert>Haven't you got a name, mate?</xfo rms:alert></xforms:input>

<xforms:input id="txtage" model="enter" ref="/user/ age"> <xforms:label>Age</xforms:label> <xforms:hint>Enter your age in years</xforms:hin t> <xforms:alert>Can't you read? Tell me your age!< /xforms:alert></xforms:input>

<xforms:input id="txtdob" model="enter" ref="/user/ dob"> <xforms:label>Date of birth</xforms:label> <xforms:hint>Enter your date of birth</xforms:hi nt> <xforms:alert>You can forget your birthday gift, brother!</xforms:alert></xforms:input>

<xforms:input id="txtheight" model="enter" ref="/us er/height"> <xforms:label>Height</xforms:label> <xforms:hint>Enter your height in feet and inche s</xforms:hint> <xforms:alert>Don't have a measuring tape, do yo u?</xforms:alert></xforms:input>

<xforms:input id="txtweight " model="enter" ref="/u ser/weight"> <xforms:label>Weight</xforms:label> <xforms:hint>Enter your weight in pounds</xforms :hint> <xforms:alert>Come on fatso, 'fess up!</xforms:a lert></xforms:input>

<xforms:input id="boolimmunization" model="enter" r ef="/user/immunization"> <xforms:label>Have you been immunized against ma jor diseases?</xforms:label> <xforms:hint>Enter your immunization status</xfo rms:hint> <xforms:alert>Don't lie, we have syringes with l arge needles!</xforms:alert></xforms:input>

</body></html>

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=226

9 of 12 4/22/2014 8:13 AM

Page 19: XForms Basics - The Melonfire Community - Trog

At first glance, the above example looks much like the examples we have discussed so far. But a

closer inspection of the model reveals a subtle difference...

<xforms:model id="enter"> <xforms:instance> <user xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" ; xmlns:xsd=" http://www.w3.org/2001/XMLSchema"> ; <name xsi:type="xsd:string" /> <age xsi:type="xsd:integer" /> <dob xsi:type="xsd:date" /> <height xsi:type="xsd:float" /> <weight xsi:type="xsd:decimal" /> <immunizaton xsi:type="xsd:boolean" /> </user> </xforms:instance></xforms:model>

For starters, I have two new namespaces, one for XML Schema and the second for the XML Schema

instance. Both these are required for the new features that I'm going to introduce in this example.

Next, take a closer look at the definition of the XForms model. You'll see that each element contains

a new "xsi:type" attribute. This attribute, which references datatypes from the XML Schema

namespace (hence the "xsd:" namespace identifier) makes it possible to easily use those datatypes

within XForms. Once datatypes have been defined in this manner, and links to the form controls

have been set up via "ref" attributes, the XForms processor will generate an error if the data

entered into a field does not match the datatype associated with it in the form model.

How is this error handled? Simple - with the new <xforms:alert> element, which can be used to

display control-specific errors or alerts. Take a look at this snippet, which illustrates:

<xforms:input id="txtage" model="enter" ref="/user/ age"> <xforms:label>Age</xforms:label> <xforms:hint>Enter your age in years</xforms:hin t> <xforms:alert>Can't you read? Tell me your age!< /xforms:alert></xforms:input>

Here, if the user does not enter data consistent with the definition for the control, the message

specified in the <xforms:alert> field will be displayed.

The Number Game

If you have special needs, you can even create your own datatypes using XML Schema, instead of

restricting yourself to the pre-defined datatypes. Consider the following example, which illustrates:

<html xmlns=" http://www.w3.org/1999/xhtml" ; xmlns:xforms=" http://www.w3.org/2002/xforms/cr"> ;

<head>

<!-- form model --><xforms:model id="information" schema="users.xsd"> <xforms:instance> <user> <name xsi:type="xsd:string" /> <email xsi:type="xsd:string" /> <age xsi:type="adultsOnly" /> </user> </xforms:instance> <xforms:submission id="submit" ref="/user/name" action="/scripts/save.cgi"method="post" indent="yes" omit-xml-declaration="no " />

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=226

10 of 12 4/22/2014 8:13 AM

Page 20: XForms Basics - The Melonfire Community - Trog

</xforms:model>

<basefont face="Arial">

</head>

<body>

<!-- define interface controls --><table cellspacing="5" cellpadding="5" border="0"><tr><td> <xforms:input id="txtname" model="information" r ef="/user/name"> <xforms:label>Name</xforms:label> <xforms:hint>Enter your name here</xforms:hin t> </xforms:input></td></tr>

<tr><td> <xforms:input id="txtemail" model="information" ref="/user/email"> <xforms:label>Email address</xforms:label> <xforms:hint>Enter your email address here</x forms:hint> </xforms:input></td>

<td> <xforms:input id="intage" model="information" re f="/user/age"> <xforms:label>Age</xforms:label> <xforms:hint>Enter your age here</xforms:hint > </xforms:input></td>

</table>

<xforms:submit submission="submit"> <xforms:label>Save</xforms:label></xforms:submit>

</body></html>

You'll notice that I've defined a custom type in the form model - something called "adultsOnly". The

definition for this type is stored in an XML Schema, and it only allows you to enter values equal to

or over 18 into the corresponding field. Take a look:

<?xml version="1.0" encoding="UTF-8"?><xsd:schema xmlns:xsd=" http://www.w3.org/2001/XMLSchema"> ; <xsd:simpleType name="adultsOnly"> <xsd:restriction base="xsd:integer"> <xsd:minInclusive value="18" /> </xsd:restriction></xsd:simpleType></xsd:schema>

And that's about it for today. In this article, I began by discussing the XForms submission process,

and explained how to use the <xforms:submission> element to save form input to a local file with

the PUT method, and how to pass it to a server-side script for storage in a MySQL database. I also

showed you a real-world example of the latter, by using the PHP SAX parser to parse the instance

document generated by an XForms submission and convert it into an SQL query string.

Next, I taught you how XForms significantly simplifies the task of input validation, by integrating

with XML Schema datatypes and allowing you to validate user input against those datatypes. Here

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=226

11 of 12 4/22/2014 8:13 AM

Page 21: XForms Basics - The Melonfire Community - Trog

too, I showed you a couple of different examples, one using XML Schema built-in datatypes and the

other using my own custom types.

Next week, I'll be delving a little deeper into the XForms specification, explaining binding, form

events, and built-in functions. Until then...stay healthy!

Note: Examples are illustrative only, and are not meant for a production environment. Melonfire

provides no warranties or support for the source code described in this article. YMMV!

Copyright notice:

This article is copyright Melonfire, 2014. All rights reserved.

All source code, brand names, trademarks and other content contained herein and proprietary to

Melonfire, 2014. All rights reserved.

Source code within this article is provided with NO WARRANTY WHATSOEVER. It is meant for

illustrative purposes only, and is NOT recommended for use in production environments.

Copyright infringement is a violation of law.

Printed from http://www.melonfire.com/community/columns/trog/article.php?id=226

Copyright © 1998-2014 Melonfire. All rights reservedTerms and Conditions | Feedback

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=226

12 of 12 4/22/2014 8:13 AM

Page 22: XForms Basics - The Melonfire Community - Trog

Community

Trog

Copyright notice:

This article is copyright Melonfire, 2014. All rights reserved.

All source code, brand names, trademarks and other content contained herein is proprietary to

Melonfire, 2014. All rights reserved.

Source code within this article is provided with NO WARRANTY WHATSOEVER. It is meant for

illustrative purposes only, and is NOT recommended for use in production environments.

Copyright infringement is a violation of law.

Printed from http://www.melonfire.com/community/columns/trog/article.php?id=228

XForms Basics (part 3)Perform calculations on form input values and get a crash course in the XForms event

model.

Endgame

In the previous article, I showed you how to manage user input in the XForms model. I discussed

the process of submitting an XForm and - more importantly - validating user input prior to

submission using built-in XML Schema support.

In this concluding segment, I'll introduce you to some of XForms' more arcane features. First, the

concept of binding, which allows developers to implement a number of useful features quickly -

calculating values instantly, enforcing basic validation rules, taking decisions on the fly or rendering

a particular node non-writable.

Next, I'll briefly show you how you can use XPath functions within an XForms model definition, and

illustrate how functions like sum() and avg() allow you to perform complex calculations in a simple

and smooth manner. I'll also take a quick look at the XForms event processing model, explaining the

important phases and showing you a basic example of how triggers and actions work.

Let's get started, shall we?

Operating With Extreme Caution

You've already seen how various XML technologies integrate seamlessly with each other when it

comes to XForms. In fact, in the last part of this tutorial, I showed you how to re-use an XML

Schema datatype definition in an XForms model, and how to use XPath expressions to reference and

bind instance data with the XForms user interface. But why stop there? You can also use logical,

comparison and arithmetic operators and functions with XPath expressions, in order to perform

calculations using the instance data in an XForms model.

In order to do this, you need to first understand the <xforms:bind> element, which makes it

possible to bind instance data elements to specific properties and constraints. The <xforms:bind>

element comes with a number of additional attributes, which can be used to specify whether a

particular element of the instance data is required, read-only, constrained to specific values or

compliant with a specific type.

Consider the following example, which demonstrates:

<!-- form model -->

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=228

1 of 7 4/22/2014 8:14 AM

Page 23: XForms Basics - The Melonfire Community - Trog

<xforms:model id="account"> <xforms:instance> <account> <name /> <number /> </account> </xforms:instance><xforms:bind id="accountNumberRequired" nodeset="/a ccount/number" required="true()"/></xforms:model>

In this case, the bind definition states that the account number is required in order for the form to

be submitted. This is a very fundamental example of input validation. With normal HTML forms,

you'd need to write client-side and server-side code to manage this requirement; with XForms, it

comes built-in!

In case you were wondering where this bind definition gets used, the XForms specification states

that user interface elements can then be linked to the definition, simply by adding a "bind" attribute

to the interface control (instead of the traditional "ref" attribute). Here's an example:

<!-- define the form interface --><xforms:input bind="accountNumberRequired"> <xforms:label>Account number</xforms:label></xforms:input>

Money, Money, Money

Of course, the "required" attribute is just one example of what XForms calls "model item

properties". Another one is the "relevant" attribute, which specifies when a particular element of the

instance data is enabled or disabled. Consider the following example, which illustrates:

<!-- form model --><xforms:model id="tran"> <xforms:instance> <transaction> <type /> <amount /> <checkNumber /> </transaction> </xforms:instance><xforms:bind nodeset="/transaction/checkNumber" rel evant="/transaction/type='check'"/></xforms:model>

Basically, this says that when performing a transaction (in this case, a bank account transaction

which is either a deposit or a withdrawal) the check number is only relevant when the transaction

involves a check.

Of course, it's up to the implementation to decide how to handle this particular property. Some

implementations might disable the field for data entry during cash transactions, others might hide

it, and still others might pop up a warning.

You'll notice, also, that the "relevant" property contains an equality test. Model item properties can

contain comparison tests, so long as these conform to the rules laid down for XPath expressions.

Here's another example, this one illustrating the use of a comparison test with the previously-

explained "required" property by requiring the entry of a tax identification number for transactions

greater than $50,000:

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=228

2 of 7 4/22/2014 8:14 AM

Page 24: XForms Basics - The Melonfire Community - Trog

<!-- form model --><xforms:model id="taxes"> <xforms:instance> <transaction> <name /> <amount /> <taxID /> </transaction> </xforms:instance><xforms:bind id="taxIDRequired" nodeset="/transacti on/taxID" required="/transaction/amount &gt; 50000" /></xforms:model>

Shop Till You Drop

It's also possible to specify that a particular element of the instance data be read-only via the

"readonly" property. Consider the following example:

<!-- form model --><xforms:model id="shop"> <xforms:instance> <item> <code /> <price /> <discount>2.00</discount> <quantity /> <grossTotal /> <netTotal /> </item> </xforms:instance><xforms:bind nodeset="/item/discount" readonly="tru e()" /></xforms:model>

In this case, since you don't want users messing with the discount rate, you can use the "readonly"

property to make it non-modifiable. As before, you can combine this with comparison tests to make

the property's relevance conditional.

One extremely useful property in this context - and one you'll probably be using a lot - is the

"calculate" property, which lets you calculate some of the form data on the fly. Consider the

following extension of the example above, which illustrates:

<!-- form model --><xforms:model id="shop"> <xforms:instance> <item> <code /> <price /> <discount>2.00</discount> <quantity /> <grossTotal /> <netTotal /> </item> </xforms:instance><xforms:bind nodeset="/item/discount" readonly="tru e()" /><xforms:bind nodeset="/item/grossTotal" calculate=" /item/price * /item/quantity" /><xforms:bind nodeset="/item/netTotal" calculate="/i tem/grossTotal - ((item/grossTotal* /item/discount)/100)" /></xforms:model>

In this case, the "calculate" property has been used to dynamically calculate the value of the

<grossTotal> element from the values of the <price> and <quantity> elements. The <netTotal> is

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=228

3 of 7 4/22/2014 8:14 AM

Page 25: XForms Basics - The Melonfire Community - Trog

then again calculated from the <grossTotal> by accounting for the <discount>.

In case you were wondering why I haven't used a "readonly" property for the two dynamically-

calculated values - I don't need to, since these values are automatically made read-only when a

"calculate" property is used on them.

The Bookworm Turns

In addition to simple comparison tests, you can also use XPath arithmetic and non-arithmetic

functions in an XForms model. Consider the following example, which illustrates:

<html xmlns=" http://www.w3.org/1999/xhtml" ; xmlns:xforms=" http://www.w3.org/2002/xforms/cr" ; xmlns:xsd=" http://www.w3.org/2001/XMLSchema"> ;<head><!-- define the form model --><xforms:model id="bookstore"> <xforms:instance> <inventory> <books> <title>Be Cool</title> <author>Elmore Leonard</author> <price>7.97</price> <quantity>150</quantity>

<title>Mystic River</title> <author>Dennis Lehane</author> <price>25.00</price> <quantity>86</quantity>

<title>Hit List</title> <author>Lawrence Block</author> <price>23.76</price> <quantity>26</quantity>

<title>Silent Joe</title> <author>T. Jefferson Parker</author> <price>24.99</price> <quantity>268</quantity>

<title>The Travel Detective</title> <author>Peter Greenberg</author> <price>34.87</price> <quantity>9</quantity> </books>

<totalInventory />

<mostExpensive />

<leastExpensive />

<averageCost /> </inventory> </xforms:instance> <xforms:bind nodeset="/inventory/books/totalInve ntory" calculate="sum(/inventory/books/quantity)" /> <xforms:bind nodeset="/inventory/books/mostExpen sive" calculate="max(/inventory/books/price)" /> <xforms:bind nodeset="/inventory/books/leastExpe nsive" calculate="min(/inventory/books/price)" /> <xforms:bind nodeset="/inventory/books/averagePr ice" calculate="avg(/inventory/books/price)" />

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=228

4 of 7 4/22/2014 8:14 AM

Page 26: XForms Basics - The Melonfire Community - Trog

</xforms:model></head>

<body><!-- define the form interface --><!-- loop over the instance data --><xforms:repeat nodeset="/inventory/books"> <xforms:input id="txttitle" ref="title"> <xforms:label>Title</xforms:label> </xforms:input> <xforms:input id="txtauthor" ref="author"> <xforms:label>Author</xforms:label> </xforms:input> <xforms:input id="txtprice" ref="price"> <xforms:label>Price</xforms:label> </xforms:input> <xforms:input id="txtquantity" ref="quantity"> <xforms:label>Quantity</xforms:label> </xforms:input></xforms:repeat>

<!-- print calculated values -->Total inventory: <xforms:output ref="/inventory/boo ks/totalInventory" /> <br />

Price of most expensive book: <xforms:output ref="/ inventory/books/mostExpensive" /><br />

Price of least expensive book: <xforms:output ref=" /inventory/books/leastExpensive"/> <br />

Average price: <xforms:output ref="/inventory/books /averagePrice" />

</body></html>

As usual, all the action is centered around the definition of the XForms model. This time around, the

instance data has been populated with the inventory of the neighbourhood bookstore, and XPath

functions like sum(), min(), max() and avg() have been used to perform calculations on that data,

and assign the results of those calculations to specific summary elements in the instance data. This

data is then displayed in the form using the <xforms:output> element.

You'll also notice a new element in the form above - the <xforms:repeat> element. This element

gives XForms authors the ability to loop over a collection of nodes without having to resort to

complex "while" or "for" loops. In this example, the <xforms:repeat> element causes the XForms

processor to iterate over the <books> collection from the instance data, and display the values of

the title, author, price and quantity. The "nodeset" attribute specifies the node over which iteration

should take place, while the loop counter is handled internally by the processor. Looping will stop

once no further match is found for the "nodeset" criteria.

Why stop just at numeric functions, though? This next example uses the days-from-date() function

to calculate the number of days between an entered date and January 01 1970.

The XForms model will look something like this:

<!-- form model --><xforms:model id="dateCalculator"> <xforms:instance> <calc> <dt /> <numDays /> </calc> </xforms:instance><xforms:bind nodeset="/calc/numDays" calculate="day s-from-date(/calc/dt)" /></xforms:model>

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=228

5 of 7 4/22/2014 8:14 AM

Page 27: XForms Basics - The Melonfire Community - Trog

Pretty straightforward, isn't it?

An Event To Remember

It was the introduction of events in client-side scripting languages like JavaScript and VBScript that

brought about the rise of the dynamic Web site. However, inconsistencies in implementation across

browsers meant that developers had to grapple with multiple lines of code to make Web sites cross-

browser compatible. XForms has put an end to this misery, at least so far as form events are

concerned.

The XForms 1.0 specification divides the process of event handling into four phases:

Initialization: This is the very first stage, wherein the XForms processor "wakes up" and begins

construction of the data model using the instance data provided. This is also the stage where all

relevant XML Schemas are loaded, and all form controls (with their associated bindings) are

initialized.

Interaction: Interaction events are fired as a result of action from the user - for example, keyboard

navigation to a new input control, mouse clicks, data entry or item selection. A number of different

events can occur in this phase, and each one has a default action associated with it.

Notification: Notification events don't usually have a default action associated with them; rather,

they're triggered as a result of a change in the form state, such as a form control receiving focus or

a button being clicked.

Error handling: These events occur due to errors in XForm processing, such as illegal binding

expressions or illegal XPath references. Errors may be either fatal or non-fatal, depending on their

severity.

OK, now enough of the theory. Let's look at a simple example:

<!-- define the form model --><xforms:model id="bankAccount"> <xforms:instance> <account> <openingBalance>10000</openingBalance> <withdrawal /> <closingBalance /> </account> </xforms:instance>

<xforms:bind id="nodeClosingBalance" nodeset="/a ccount/closingBalance" />

</xforms:model>

<!-- define the form interface --><xforms:input id="txtwithdraw" ref="/account/withdr awal"> <xforms:label>Amount to withdraw</xforms:label> <xforms:hint>Please enter the amount you wish to withdraw</xforms:hint></xforms:input>

<xforms:trigger><xforms:label>Calculate Closing Balance</xforms:lab el><xforms:setvalue ev:event="DOMActivate" bind="nodeC losingBalance" value="/account/openingBalance - /account/withdrawal" /></xforms:trigger>

By definition, the <xforms:trigger> element is the XForms counterpart of the regular HTML form

button. When clicked, it generates a DOMActivate event, which is a catch-all event type fired

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=228

6 of 7 4/22/2014 8:14 AM

Page 28: XForms Basics - The Melonfire Community - Trog

whenever any event (pressing a button, selecting an option) occurs. The <xforms:setvalue>

element, which is used to set the value for a particular node after computing it from an XPath

expression, listens for this event and acts when it receives it. In this case, the action involves

subtracting the withdrawal amount from the opening balance to obtain a new closing balance.

A number of other event types are available in the XForms model - you've already seen one of the

other important ones, the xforms-submit event, in the previous segment of this tutorial. There are

too many to list here, so you should take a look at the specification (and the excellent examples

included within it), to better understand this topic.

Link Out

And that's about all I have for you. Over the course of this three-part tutorial, I introduced you to

the new XForms 1.0 specification, and showed you how to create a data model and bind its elements

to form input controls. I also explained the various XForms input controls, and showed you how they

map into the standard HTML form controls.

Next, I discussed the process of submitting an XForm, with a look at the <xforms:submission>

element and the "submit" input control. I also showed you how to perform primitive datatype

validation in an XForm using built-in XML Schema datatypes, and how to extend this to perform

more complex validation by integrating your own custom datatypes into the XForms model.

Finally, in this concluding part, I introducing the concept of binding using the <xforms:bind>

element, which allows you to disable or enable input controls, mark them as read-only, enforce

special constraints on your input controls, and even calculate values on the fly - tasks which earlier

required complex JavaScript, but are now as simple as combining XPath expressions. I also looked at

some XPath functions, and showed you how you can use them within your binding expressions for

greater flexibility in calculations. I wrapped things up with a brief introduction to the XForms event

model - this is a fairly complex topic, and one which requires in-depth understanding of the XML

Events specification as well, so if you'd like to learn more about it, be prepared to spend some time

on research (with the specification in hand).

I hope you enjoyed this article, and that it gave you sufficient grounding to get you started with

XForms. XForms is one of the more interesting emerging XML technologies, and you can expect to

see it grow more powerful in subsequent iterations. So go on - it's time to practice!

Note: Examples are illustrative only, and are not meant for a production environment. Melonfire

provides no warranties or support for the source code described in this article. YMMV!

Copyright notice:

This article is copyright Melonfire, 2014. All rights reserved.

All source code, brand names, trademarks and other content contained herein and proprietary to

Melonfire, 2014. All rights reserved.

Source code within this article is provided with NO WARRANTY WHATSOEVER. It is meant for

illustrative purposes only, and is NOT recommended for use in production environments.

Copyright infringement is a violation of law.

Printed from http://www.melonfire.com/community/columns/trog/article.php?id=228

Copyright © 1998-2014 Melonfire. All rights reservedTerms and Conditions | Feedback

The Melonfire Community - Trog http://www.melonfire.com/community/columns/trog/print.php?id=228

7 of 7 4/22/2014 8:14 AM