In Part 1 of this four-part series, you began to design a Web application that would let patients enter information at the doctor's office. It discussed how you can use XForms, DB2 pureXML, and Ruby on Rails to create such an application, and you did some experimentation with using these technologies together. In this article, Part 2, you will begin to implement the application. You will design your first XForm and create a Ruby on Rails back-end to insert the data from the form into DB2. You will see how you can use these three technologies to leverage XML all the way across your application.
This article assumes familiarity with XML and with Web applications in general. Prior
exposure to the three core technologies, XForms, DB2 pureXML, and Ruby on Rails, is
helpful of course, but definitely not necessary. The article was written using the
Mozilla XForms plugin version 0.8.0.3. This provides XForms runtime support in any
Mozilla browser such as Firefox. Another very useful Mozilla plugin is XForms Buddy.
This provides a debugger for XForms. Version 0.5.6 was used in this article. You will
also need the DB2 database server from IBM. This article uses DB2 Express-C version 9.5.
This is available for Windows®, Linux®, and UNIX® systems. Finally, you will need Ruby on
Rails. This article uses Ruby 1.8.6 with Rails 1.2.5. This article also uses the Mongrel Web server in conjunction with Rails. This is available through Ruby Gems (just type gem install mongrel from the command line). See Resources for download links.
Part 1 discussed how the technologies you are using, XForms, DB2 pureXML, and Ruby on Rails, allow you to use XML on the front and back ends of your application. One nice thing about this design is that it puts the XML data front-and-center. The design of your XML data model defines how you implement the XForms-based front end as well as how you retrieve data from DB2 using Ruby on Rails on the back end. So the logical place to start developing this application is to design the XML data model.
The application will allow patients to enter information needed by the doctor and the staff in the office. You will need information such as the patient's name, insurance company, age, co-pay amount, and of course their symptoms. With all of that in mind, Listing 1 shows what a typical data model instance might look like.
Listing 1. Typical XML instance of patient information
<?xml version="1.0" encoding="UTF-8"?>
<Info>
<FirstName>John</FirstName>
<MiddleName>David</MiddleName>
<LastName>Smith</LastName>
<Age>33</Age>
<Insurer>HealthCo</Insurer>
<Id>555-69-1212</Id>
<PolicyHolder>true</PolicyHolder>
<Copay>10</Copay>
<Symptoms>Cough, Fever</Symptoms>
</Info>
|
Most of these are simple strings, with a few exceptions. Middle name should be an optional field. Age is an integer, and must be non-negative. The same is true of co-pay. Policy holder is a Boolean flag. You will define the Id to follow a pattern of three digits, two digits, and four digits. With all of that in mind, Listing 2 shows an XML schema describing the patient data model.
Listing 2. Patient schema
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://developerworks.ibm.com/patient"
xmlns="http://developerworks.ibm.com/patient"
elementFormDefault="qualified"
xmlns:this="http://developerworks.ibm.com/patient">
<xs:simpleType name="policyId">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{3}-[0-9]{2}-[0-9]{4}"/>
</xs:restriction>
</xs:simpleType>
<xs:element name="Info">
<xs:complexType>
<xs:sequence>
<xs:element name="FirstName" type="xs:NMTOKENS"/>
<xs:element name="MiddleName" type="xs:NMTOKEN" minOccurs="0"/>
<xs:element name="LastName" type="xs:NMTOKENS"/>
<xs:element name="Age" type="xs:nonNegativeInteger"/>
<xs:element name="Insurer" type="xs:NMTOKENS"/>
<xs:element name="Id" type="this:policyId" />
<xs:element name="PolicyHolder" type="xs:boolean"/>
<xs:element name="Copay" type="xs:nonNegativeInteger"/>
<xs:element name="Symptoms" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
|
With your XML data model defined, you can now create an XForms that allows a user to create an instance of this data model.
Now you know what data that you want patients to enter into your application. This makes defining the XForms very straightforward. You simply create form elements that correspond to the elements in your data model. The type of form element is based on the data type of the data element. With that in mind, Listing 3 shows the XForms for the patient information.
Listing 3. Patient information XForms
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms">
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=ISO-8859-1" />
<title>Patient Information</title>
<xf:model>
<xf:instance>
<Info xmlns="">
<FirstName/>
<MiddleName/>
<LastName/>
<Age/>
<Insurer/>
<Id/>
<PolicyHolder/>
<Copay/>
<Symptoms/>
</Info>
</xf:instance>
<xf:submission action="http://localhost:3000/kiosk/create"
method="post" id="submit-info"/>
</xf:model>
</head>
<body>
<p>
<div id="firstName">
<xf:input ref="FirstName">
<xf:label>First Name:</xf:label>
</xf:input>
</div>
<div id="middleName">
<xf:input ref="MiddleName">
<xf:label>Middle Name:</xf:label>
</xf:input>
</div>
<div id="lastName">
<xf:input ref="LastName">
<xf:label>Last Name:</xf:label>
</xf:input>
</div>
<div id="age">
<xf:input ref="Age">
<xf:label>Age:</xf:label>
</xf:input>
</div>
<div id="insurer">
<xf:input ref="Insurer">
<xf:label>Name of Insurance Provider:</xf:label>
</xf:input>
</div>
<div id="idNumber">
<xf:input ref="Id">
<xf:label>Insurance ID Number(###-##-####):</xf:label>
</xf:input>
</div>
<div id="holder">
<xf:select1 ref="PolicyHolder">
<xf:label>Are you the policy holder?</xf:label>
<xf:item>
<xf:label>Yes</xf:label>
<xf:value>true</xf:value>
</xf:item>
<xf:item>
<xf:label>No</xf:label>
<xf:value>false</xf:value>
</xf:item>
</xf:select1>
</div>
<div id="copay">
<xf:input ref="Copay">
<xf:label>Co-pay :$</xf:label>
</xf:input>
</div>
<div id="symptoms">
<xf:textarea ref="Symptoms">
<xf:label>Please describe your symptoms:</xf:label>
</xf:textarea>
</div>
<div id="submit">
<xf:submit submission="submit-info">
<xf:label>Submit Information</xf:label>
</xf:submit>
</div>
</p>
<a href="kiosk/list">Back to List</a>
</body>
</html>
|
Here is a quick explanation of the XForms in Listing 3. You have one model and one instance. The instance is a blank version of the patient information data model defined previously. You also have a submission that is part of the model. The submission will take your model instance and post it to the URL specified in the submission action attribute. In the body of the form, you have a series of XForms elements. Each one is bound to the model instance using a ref XPath. Whatever values the user enters in data in the form will be bound to the model instance. Load the XForms in a browser and you should see something similar to Figure 1.
Figure 1. The patient XForms

Not exactly the prettiest Web page, but it is a functional XForm. A few interesting things are worth mentioning:
.
- First, the page is an XHTML page, not a usual HTML page. If you changed the page extension to .html or .htm, then it will not render properly. That is because XForms require XHTML and thus the Mozilla plugin will not activate on an HTML page.
- Next, since it is XHTML, it still supports CSS. This is the easiest way to change the look of the page. You will use some CSS shortly as part of data validation.
- Finally, notice that the URL was http://localhost:3000/patient.xhtml. In the example above, the page was served from a Ruby on Rails application using the Mongrel Web server. The page is a static page, so you can simply copy it to the public directory of your Rails application. You can use the default WEBrick Web server, but it requires additional configuration to serve XHTML pages. Mongrel on the other hand needs no extra configuration for XHTML pages.
As mentioned earlier, submitting the form will cause a POST of the model instance. However, before you start to process that post, you should perform some validation.
One of the most common tasks in data entry is validation of the input data. It is often preferable to do this on the client, to prevent the submission of invalid data to the back-end of a system. This usually involves writing JavaScript to extract data and then running a rule (maybe a regular expression) on it. Luckily XForms simplifies this quite a bit. XForms is all about XML and data validation has a well defined syntax in XML: XML schema. Add validation to the XForms you created with the previously defined schema in Listing 2, as shown in Listing 4.
Listing 4. XForms model with schema for validation
<title>Patient Information</title>
<style type="text/css">
@namespace xf url("http://www.w3.org/2002/xforms");
xf|input {
display: table-row;
line-height: 2em;
}
xf|label {
display: table-cell;
text-align: right;
font-family: Ariel, Helvetica, sans-serif;
font-weight: bold;
font-size: small;
padding-right: 5px;
width: 250px;
}
xf|*{
display: table-row;
line-height: 2em;
}
#submitLabel{
display: table-row;
}
*:required {
background-color: yellow;
}
*:invalid {
background-color: yellow;
}
</style>
<xf:model id="patientModel" schema="patient.xsd">
<xf:instance xmlns="" id="patient">
<p:Info>
<FirstName></FirstName>
<MiddleName></MiddleName>
<LastName></LastName>
<Age></Age>
<Insurer></Insurer>
<Id></Id>
<PolicyHolder></PolicyHolder>
<Copay></Copay>
<Symptoms></Symptoms>
</p:Info>
</xf:instance>
<xf:submission action="http://localhost:3000/kiosk/create"
method="post"
id="submit-info"/>
</xf:model>
|
Notice that your model now references a schema (patient.xsd). XForms will load and validate against this schema automatically. Also notice you have added some CSS to show invalid data. If you bring this up in your browser it should look like Figure 2.
Figure 2. XForms with Validation and CSS.

The user must fill in the required fields in order to submit the form. The color changes automatically when a valid value is entered and the focus moves to a new form field. Think of the JavaScript you might normally write for this. Instead, you accomplished it with an XSD and some CSS.
XForms gives you many ways to do validation. You do not have to use an XML schema, but it does provide a simple way especially in the case of data that can be easily described through a schema. With client side validation in place, you can concentrate on processing the submitted data on the server.
You might have noticed earlier that a URL for your form submission is already defined. If you are familiar with Ruby on Rails, then this URL should look pretty familiar. Convention over configuration, and following the Rails convention, the URL /patient/create corresponds to the create action on the patient controller. You can set this up easily using a Ruby generation script as in Listing 5.
Listing 5. Generating the patient scaffolding
>ruby script/generate scaffold patient kiosk
exists app/controllers/
exists app/helpers/
create app/views/kiosk
exists app/views/layouts/
exists test/functional/
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
skip app/models/patient.rb
identical test/unit/patient_test.rb
identical test/fixtures/patients.yml
create app/views/kiosk/_form.rhtml
create app/views/kiosk/list.rhtml
create app/views/kiosk/show.rhtml
create app/views/kiosk/new.rhtml
create app/views/kiosk/edit.rhtml
create app/controllers/kiosk_controller.rb
create test/functional/kiosk_controller_test.rb
create app/helpers/kiosk_helper.rb
create app/views/layouts/kiosk.rhtml
identical public/stylesheets/scaffold.css
|
This generates a lot more than you need. You can delete unused files. The two important
things it creates for you are the patient class and the kiosk_controller class. The kiosk_controller class is, as you might guess, the controller that
will handle the request from your XForms. Now take a look at the model and controller and how you will modify them to save the XML from your XForms.
You used the Rails scaffolding to accelerate the development of your application. In
many Rails applications, you can use the scaffolding to actually handle the interaction
with the database without making any changes to the controller. That is possible by
leveraging the object-relational mapping code in Rails's ActiveRecord class that is the
base class for all models (including your patient class.
ActiveRecord was not designed to handle XML, so you will need to modify the generated
classes. To start, look at the patient class in Listing 6.
Listing 6. Default
patient classclass Patient < ActiveRecord::Base end |
As you can see, by default the Patient class simply extends ActiveRecord. ActiveRecord dynamically creates accessors based on the column names of the database table that it is mapped to. It has a constructor that takes in a hash of name/value pairs. This is used by the application controller to simply pass in the form data directly. You can take advantage of this and modify the patient class in Listing 7.
Listing 7. Modified
patient class
require 'rexml/document'
class Patient < ActiveRecord::Base
def information=(value)
self[:information] = value.to_s
end
end
|
You only made a slight change, but it is an important one. You want to keep the value of information as a string internally so that it will be serialized as a string when ActiveRecord inserts it into the database. But what is going to be passed in to your model? That is handled by the controller. Listing 8 shows the default controller.
Listing 8. Default Kiosk controller
class KioskController < ApplicationController
def index
list
render :action => 'list'
end
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
verify :method => :post, :only => [ :destroy, :create, :update ],
:redirect_to => { :action => :list }
def list
@patient_pages, @patients = paginate :patients, :per_page => 10
end
def show
@patient = Patient.find(params[:id])
end
def new
@patient = Patient.new
end
def create
@patient = Patient.new(params[:patient])
if @patient.save
flash[:notice] = 'Patient was successfully created.'
redirect_to :action => 'list'
else
render :action => 'new'
end
end
def edit
@patient = Patient.find(params[:id])
end
def update
@patient = Patient.find(params[:id])
if @patient.update_attributes(params[:patient])
flash[:notice] = 'Patient was successfully updated.'
redirect_to :action => 'show', :id => @patient
else
render :action => 'edit'
end
end
def destroy
Patient.find(params[:id]).destroy
redirect_to :action => 'list'
end
end
|
Earlier you defined the action URL for the XForms as /kiosk/create, thus the create method above is what will be called. Rails thinks that it is
getting a series of HTML form elements on submission, not an XML document. So you will
modify this method slightly to parse the XML document that is sent in by the XForms you
wrote. Listing 9 shows the modified create method.
Listing 9. Modified
create method
def create
doc = REXML::Document.new("<Info></Info>")
params[:Info].each_pair do |key,value|
if (key.index(':') == nil) #namespace attributes
el = REXML::Element.new key
el.add_text value
doc.root.add el
else
doc.root.add_attribute key,value
end
end
@patient = Patient.new
@patient.information = doc
if @patient.save
flash[:notice] = 'Patient was successfully created.'
redirect_to :action => 'list'
else
render :action => 'new'
end
end
|
The first thing you might notice is that you are using REXML to create an XML document. REXML is a standard library included with Ruby. The XML document from XForms comes in as the Info parameter and is parsed as an object. You simply iterate over it and transform it back into XML. This is all you need to do to get Rails to insert your document into the database. Now you can test it out.
To test the application, you simply start up your server using the usual ruby script/server start command. Then point the browser to the XForms as in Figure 2. Fill out the form and click Submit Information. You should see the screen in Figure 3.
Figure 3. List of patients

Where did this UI come from? It is the standard list UI provided by Rails scaffolding. Notice that it shows your Info field with a blob of unformatted XML. If you scroll to the right, you should see controls to view, edit, and delete the patient. The viewing and deleting both work as is! The editing does not, nor does the New Patient link at the bottom of the page. You must modify the links to use the XForms, since that is what you want to use to enter data. That's what Part 3 of this series will help you do!
You saw how to use XForms to create a data entry form for patients to enter their information. XForms takes care of binding patient data to an XML document and can even validate against an XML schema. Your application submits this XML document to a Ruby on Rails controller. Ruby makes it easy to parse this input as XML and to serialize that XML as a string. DB2 understands the serialized XML string and can store it natively using pureXML technology. Rails is even able to display this data with no special work on your part. From here, you can use DB2 XML/SQL syntax to query the XML data or retrieve it and use Ruby to navigate and extract data.
| Description | Name | Size | Download method |
|---|---|---|---|
| Part 2 sample code | part2_doctorsOffice.zip | 7KB | HTTP |
Information about download methods
Learn
- XForms and Ruby on Rails at the doctor's office, Part 1: Setting up IBM DB2 9 pureXML (Michael Galpin, developerWorks, December 2007): Examine how XForms, DB2 pureXML, and Ruby on Rails can all help more rapidly build XML-centric Web applications.
- XForms and Ruby on Rails at the doctor's office, Part 3: Implementing the nurse and doctor XForm (Tyler Anderson, developerWorks, June 2008: Create Web apps easily with XForms, DB2 pureXML, and Ruby. In Part 3, you make a form for nurses to edit existing patient data.
- XForms and Ruby on Rails at the doctor's office, Part 4: Implementing the doctor and patient lookup XForm (Tyler Anderson, developerWorks, June 2008): Integrate XForms, IBM DB2 pureXML, and Ruby to rapidly build XML-centric Web apps. Complete the sample app with a new XForm to look up patients by last name.
- For a great introduction to XForms read the three-part series Introduction to XForms (Chris Herbroth, developerWorks, September 2006).
- Did you know you can use XForms and Ajax together? See how in the XForms tip: Combining Ajax and XForms (Nicholas Chase, developerWorks, October 2006).
- Go even further with XForms and Ajax by using it with the Google Web Toolkit in Integrate XForms with the Google Web Toolkit, Part 1: Introducing GWT's JavaScript Native Interface (Michael Galpin, developerWorks, September 2007).
- Read one of the first in-depth tutorials on GWT in Ajax for Java developers: Exploring the Google Web Toolkit (Philip McCarthy, developerWorks, June 2006).
- Get started with Ruby on Rails and DB2 in An introduction to Ruby on Rails for DB2 developers (Edd Dumbill, developerWorks, June 2006).
- Read all about using DB2 and Ruby on Rails together in DB2 and Ruby on Rails, Part 1: Getting started with DB2 and Ruby on Rails (John Chun, et al., developerWorks, May 2007).
- See how to use DB2's pureXML with Ruby on Rails in DB2 and Ruby on Rails, Part2: DB2 and pureXML with Ruby on Rails (John Chun, et al., developerWorks, June 2007).
- Find out how to use DB2 to enhance the built-in unit
testing facilities in Rails in DB2 and Ruby on Rails, Part 3: Testing with DB2 and Ruby on Rails (John Chun, et al., developerWorks, June 2007).
- Get the scoop on the latest enhancements to DB2 in Overview of new DB2 Version 9.5 pureXML enhancements (Manaj Sardana, developerWorks, November 2007).
- Learn about using XQuery with DB2 in Query DB2 XML data with XQuery (Don Chamberlin and Cynthia Saracco, developerWorks, April 2006).
- Read about the REXML library for working with XML in Ruby in XML Matters: The REXML library (David Mertz, developerWorks, March 2002).
- Check out IBM developerWorks' Ajax Resource Center
- Visit the XForms home at W3C.
- IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.
- XML technical library: See the developerWorks XML Zone for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.
- developerWorks technical events and webcasts: Stay current with technology in these sessions.
- The technology
bookstore: Browse for books on these and other technical topics.
- Podcasts: Tune in and catch up with interesting interviews that include IBM technical experts.
Get products and technologies
- Get the XForms extension for Mozilla, Firefox, or Seamonkey.
- XForms Buddy is Mozilla/Firefox extension that allows you to see the instance data of an XForm. It updates automatically if the instance data changes.
- Get DB2 Express-C version 9.5 from IBM.
- Get Ruby 1.8.6 with Rails 1.2.5.
- IBM
trial software for product evaluation: Build your next project with trial software available for download directly from developerWorks, including application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
Discuss
- Participate in the discussion forum.
- XML zone discussion forums: Participate in any of several XML-related discussions.
- developerWorks XML zone: Share your thoughts: After you read this article, post your comments and thoughts in this forum. The XML zone editors moderate the forum and welcome your input.
- developerWorks blogs: Check out these blogs and get involved in the developerWorks community.
Comments (Undergoing maintenance)





