As you probably know, there are a lot of "template view" technologies out
there.  The most popular, and also a J2EE standard, is JSP.  Another
one is Velocity.  One could also name XML+XSL.

All these technologies have pros and cons, but they all have in common that
they are mixing two different languages in a single source.  The amount of
interlace varies, based on the technology you use and it’s sometimes hard to
draw the line.  Is a JSP page an HTML or a Java source?

These technologies also have different ways to solve the "escape in / escape
out" problem.  In JSP, you use special markers to insulate the Java code
from HTML.  In Velocity, you use # and $ to refer to Velocity code. 
None of these methods are real showstoppers but they can end up producing some fairly
ugly templates.

Is there no really clean way to solve this problem?

Well, there is.

Ruby.

In a previous entry, I used a mix of two features in Ruby
(closures and dynamicity, and more particularly, method_missing) to solve the
following three problems in one fell swoop:

  • Make sure each open tag gets closed automatically.
  • Automatically indent.
  • Integrate cleanly with the Ruby syntax.

Let me give a quick example from the LogAnalyzer utility I have been
discussing these past days.  This piece of code generates the HTML to
display a list of referrers:


def createMiddleReport
  xml = XML.new
  @referrers.referrers.each { |date, refs|
    xml.p {
      xml.b("Referrers for #{date}")
    }
    xml.table {
      refs.each { |ref, ref2|
        xml.tr {
          xml.td {
            xml.a({ "href"
=> ref }) {
             
xml.append(ref)
            }
          }
        }
      }
    }
  }

 
xml.to_xml
end

Notice how this code happily mixes templating and logic.  I iterate
whenever I have to and I insert the content into the HTML string when the time
is right.  Other technologies will subtly impose their programming model on
your code, for example by making you compute the generated code and store it in
a HashMap, or assign it to a variable which you can then use.

With this method, there is no need to escape in and out of HTML:  it is
automatically covered by the method invocations on the XML instance.

Here is another example:


xml = XML.new
xml.html {
  xml.head {
    xml.title("Statistics for
http://beust.com/weblog
")
  }
  xml.body {
    xml.table{
      xml.tr {
        xml.td({ "valign"
=> "top" }) {
         
xml.append(v.createLeftSideReport)
        }
        xml.td({ "valign"
=> "top" }) {
         
xml.append(v.createMiddleReport)
        }
      }
    }
  }
}

File.open(OUTPUT_MAIN, "w") { |f|
  f << xml.to_xml
}

If you are curious, you can take a look at the
final result, and
also download xml.rb.

Alright, let’s be a little bit more
serious now.

Of course, saying that Ruby is the ultimate template view technology should be
taken with a grain of salt.  Obviously, this is not an option if you are a
Java programmer.  You should also note that Ruby happens to have two very
handy functionalities that make this trick possible, the method_missing hack is
actually more due to Ruby being dynamically typed than anything else. 
Also, if your language of choice doesn’t support closures, you will be reduced
to something like XMLStringBuffer, which I described in a
previous entry
It is not as pretty as what you just saw, but it fits the bill pretty well.