Menu

Making XML in a Rails App

January 17, 2007

Deepak Vohra

Ruby on Rails is a database-based web framework. An XML document may be created and parsed with Ruby on Rails. Rails provides a Ruby library called Builder to generate XML markup. The Builder package contains class Builder::XmlMarkup to generate an XML document. In this article, we will create an XML document from a database table with the Builder library.

Installing XML Builder

Before installing Builder, we need to install the Ruby on Rails framework and RubyGems, the standard Ruby package manager. Download the Ruby Windows Installer application and double-click the ruby185-21.exe application. When Ruby Setup Wizard gets started, click on Next and accept the license agreement. Select the default components to install, including the RubyGems package manager. Specify a directory to install Ruby (c:/ruby is the default) and click Next. Specify a Start menu folder and click on Install to install Ruby and RubyGems. Next, install Rails. From the c:/ruby directory--the directory in which Ruby is installed--run the following command to install Rails and dependencies.


c:/ruby>gem install rails --include-dependencies

Builder is included with the package manager RubyGems. Run the following command to install Builder 2.0.0.


C:/ruby>gem install builder

The Builder::XmlMarkup class provides the methods discussed in Table 1.

Method Description
cdata!(text) Adds a CDATA section.
comment!(comment_text) Adds a comment.
declare!(inst, *args, &block) Adds a declaration. args specifies 0 or more arguments.
instruct!(directive_tag=:xml, attrs={}) Adds a processing instruction. Attributes are specified with an array of hash entries.
new(options={}) Creates an XML markup Builder object. The following options may be specified in an array of hash entries. :target=>targetObject:indent=>indentation :margin=>initial_indentation
target!() Returns target of Builder object.
Table 1. Builder::XmlMarkup methods

We also need to install the MySQL database for creating an XML document from the database. Download MySQL 5.0. Install MySQL 5.0 with Setup.exe and create a MySQL Server instance.

Creating an XML Document from a Database

In this section we will create an XML document from a database table. Create a Rails application for generating an XML document from a database:


C:/ruby>rails databasexml

Modify the development mode settings in the app/config/database.yml file to specify the database as test. The development mode settings for the MySQL database are shown in the following listing.

development:  
adapter: mysql 
database: test  
username: root  
password: nil 
host: localhost

We will use ActiveRecord migrations to create a database table. Create a migration script by creating a model script with the following Ruby command:

C:\ruby\databasexml> ruby script/generate 
model catalog

A model script app/models/catalog.rb and a migration script db/migrate/001_create_catalogs.rb are created. The migration script class, CreateCatalogs, extends the ActiveRecord::Migration class as shown in the following listing:

class CreateCatalogs < ActiveRecord::Migration
  def self.up
    create_table :catalogs do |t|
      # t.column :name, :string
    end
  end

  def self.down
    drop_table :catalogs
  end
end

The default migration script consists of methods self.up and self.down. The self.up method is invoked to run a migration and create a database table. The create_table transformation of class ActiveRecord::Migration is used to create the database table catalogs. ActiveRecord uses pluralization to map a model class to a database table. The model class is singular and uppercase and the database table is plural and lowercase. In the example Ruby on Rails application, the model class is Catalog and the database table is catalogs.

Modify the migration script 001_create_catalogs.rb to create a database table and add data to the table. In the create_table transformation, create a table catalogs with columns journal, publisher, edition, title, and author, as shown in following listing:


class CreateCatalogs < ActiveRecord::Migration

  def self.up

    create_table :catalogs do |t|

  t.column :journal, :string, :limit => 255

  t.column :publisher, :string, :limit => 255

  t.column :edition, :string, :limit => 255

  t.column :title, :string, :limit => 255

  t.column :author, :string, :limit => 255


end


Catalog.create :journal => "IBM developerWorks", 

:publisher => "IBM", :edition => 

" October 2005", 

:title=> "JAXP validation",

:author=>"Brett McLaughlin"

Catalog.create :journal => "IBM developerWorks", 

:publisher => "IBM", :edition => "July 2006", 

:title=> "The Java XPath API",

:author=>"Elliotte Rusty Harold"

  

  end


  def self.down

    drop_table :catalogs

  end

end



Run the migration script with rake. rake is similar to J2EE's Ant. Rails provides a target called migrate to run migrations.


C:/ruby/databasexml>rake migrate

The database table catalogs is created in the MySQL database. Next, create a controller script, including a controller action gen_xml, to generate an XML document from the database table.


C:/ruby/databasexml>ruby script/generate

controller catalog gen_xml

The controller script app/controllers/catalog_controller.rb is created. Modify the model script to set the database table and establish a connection with the MySQL database. The database table is set with the set_table_name method of the ActiveRecord::Base class. The database connection is established with the establish_connection method of the ActiveRecord::Base class. The model script catalog.rb is shown below:


require 'active_record'


class Catalog < ActiveRecord::Base

set_table_name "catalogs" 

end


ActiveRecord::Base.establish_connection(

  :adapter  => "mysql",

  :host     => "localhost",

  :username => "root",

  :password =>    nil,      

  :database => "test"

)

In the controller script, modify the controller action gen_xml to retrieve data from the MySQL database. In the gen_xml method, create a Builder::XmlMarkup object.


@xml = Builder::XmlMarkup.new

Retrieve data from the MySQL database table catalogs, which was set in the model script, using the find(:all) method. The find(:all) method retrieves all the columns from the database table. To run a specific SQL statement to retrieve data, use the find_by_sql(sql)method.


@catalogs=Catalog.find(:all)

The complete controller script is shown below:


class CatalogController < ApplicationController

  def gen_xml

    @xml = Builder::XmlMarkup.new

    @catalogs=Catalog.find(:all)

    end

end

Modify the gen_xml.rhtml view template in the views/catalog directory to gen_xml.rxml. Delete the gen_xml.rhtml view template. In the RXML template, create an XML document from data retrieved from the database. Add an XML declaration.


@xml.instruct! :xml, :version=>"1.0"

Add root element catalogs.


@xml.catalogs{}

In the root element, iterate over the data retrieved from the database and create a catalog element for each row of data in the result set. The @catalogs variable was set in the controller script and represents the result set of data retrieved from the database. For example, retrieve the value of the journal column as follows:


for catalog in @catalogs

    @xml.catalog do

      @xml.journal(catalog.journal)

      …

      …

    end

The complete gen_xml.rxml file is shown below:


@xml.instruct! :xml, :version=>"1.0" 

 

@xml.catalogs{

  for catalog in @catalogs

    @xml.catalog do

      @xml.journal(catalog.journal)

      @xml.publisher(catalog.publisher)

      @xml.edition(catalog.edition)     

      @xml.title(catalog.title)

      @xml.author(catalog.author)

    end

  end

}

Next, run the Rails application to generate an XML document. Start the WEBrick web server if it is not already started.


C:/ruby/databasexml>ruby script/server

Invoke the gen_xml controller action with the URL http://localhost:3000/catalog/gen_xml. In the gen_xml controller action, data is retrieved from the MySQL database and the view template gen_xml.rxml is rendered. In the gen_xml.rxml template, an XML document is generated as shown in Figure 1.

Generating XML Document
Figure 1. Generating XML Document