Tuesday, October 7, 2008

Using Ruby and ERB to dynamically create XML files from templates

Here is a simple way to dynamically create XML files from templates. Actually, it could be any type of file. I chose XML format, because I work with plenty of XML at work. And I use this technique in a test setup.

For our example template, here is a very basic XML file, called ERB_example.xml.

<email>
<to><%= $name %></to>
<from><%= $me %></from>
<date><%= Time.now %></date>
<subject><%= $hello %></subject>
On your way home, please pick up the following from the store:
% $list.each do |thing|
* <%= thing %>
% end
<%= $signoff %>
</email>


As you can see, it has the basic elements of an email message, I have tags surrounded by <%= and %>. Anything inside these tags are treated like a Ruby expression and are evaluated. I also have two occurrences of just %. These are treated as the other tags if they are at the start of the line. (Note that I did not indent those lines!) This is useful for us because we cannot nest the <%= and %> tags. (Try it!)

Just to make things easier for this example, I am using global variables for most of these tokens. I also have an expression Time.now which will substitute the date and time. Now to our Ruby script, ERB_example.rb.

require 'rubygems'
require 'erb'

# set up some variables that we want to replace in the template
$hello = "Hola"
$me = "Tu mama"
$name = "Mi'jito"
$list = [ "milk", "eggs", "bread"]
$signoff = "Te quiero mucho."

# method update_tokens takes template_file, expecting globals
# to be set, and will return an updated string with tokens replaced.
# you can either save to a new file, or output to the user some
# other way.
def update_tokens(template_file)
template = ""
open(template_file) {|f|
template = f.to_a.join
}
updated = ERB.new(template, 0, "%<>").result

return updated
end

new_xml=update_tokens(Dir.getwd+"/ERB_example.xml")
puts new_xml


Note that in our third argument to ERB.new, we are telling ERB two things. First, the % says to process any % at the beginning of a line. Second, the <> says to omit any newline for lines beginning with <% and ending with %>.

So, our final output when we run this little script is as follows:

<email>
<to>Mi'jito</to>
<from>Tu mama</from>
<date>Tue Oct 07 14:22:10 -0500 2008</date>
<subject>Hola</subject>
On your way home, please pick up the following from the store:
* milk
* eggs
* bread
Te quiero mucho.
</email>


You can find out more about ERB at the Ruby Standard Library Documentation.

No comments: