Sign In/My Account | View Cart  
advertisement


Listen Print

Choosing a Templating System
by Perrin Harkins | Pages: 1, 2, 3, 4

The Contenders

OK, now that you know something about what separates these tools from one another, let's take a look at the top choices for Perl templating systems. This is not an exhaustive list: I've only included systems that are currently maintained, well-documented and have managed to build up a significant user community. In short, I've left out about dozen less-popular systems. At the end of this section, I'll mention a few systems that aren't as commonly used but may be worth a look.

SSI

SSI is the granddaddy of templating systems, and the first one that many people used since it comes as a standard part of most Web servers. With mod_perl installed, mod_include gains some additional power. Specifically, it is able to take a new #perl directive that allows for in-line subroutine calls. It can also efficiently include the output of Apache::Registry scripts by using the Apache::Include module.

The Apache::SSI module implements the functionality of mod_include entirely in Perl, including the additional #perl directive. The main reasons to use it are to post-process the output of another handler (with Apache::Filter) or to add your own directives. Adding directives is easy through subclassing. You might be tempted to implement a complete template processor in this way, by adding loops and other constructs, but it's probably not worth the trouble with so many other tools out there.

SSI follows the callback model and is mostly a mini-language, although you can sneak in bits of Perl code as anonymous subs in #perl directives. Because SSI uses a repeated parse implementation, it is safe to use it on large numbers of files without worrying about memory bloat.

SSI is a great choice for sites with fairly simple templating needs, especially ones that just want to share some standard headers and footers between pages. However, you should consider whether your site will eventually need to grow into something with more flexibility and power before settling on this simple approach.

HTML::Mason

http://www.masonhq.com/

Mason has been around for a few years, and has built a loyal following. It was originally created as a Perl clone of some of the most interesting features from Vignette StoryServer, but has since become its own unique animal. It comes from a publishing background, and includes features oriented toward splitting pages into re-useable chunks, or ``components.''

Mason uses in-line Perl with a compilation approach, but has a feature to help keep the Perl code out of the HTML coder's way. Components (templates) can include a section of Perl at the end of the file that is wrapped inside a special tag indicating that it should be run first, before the rest of the template. This allows programmers to put all the logic for a component down at the bottom away from the HTML, and then use short in-line Perl snippets in the HTML to insert values, loop through lists, etc.

Mason is a site development framework, not just a templating tool. It includes a handy caching feature that can be used for capturing the output of components or simply storing data that is expensive to compute. It is currently the only tool that offers this sort of caching as a built-in. It also implements an argument parsing scheme that allows a component to specify the names, types and default values that it expects to be passed, either from another component or from the values passed in the URI query string.

While the documentation mostly demonstrates a callback execution model, it is possible to use Mason in a pipeline style. This can be accomplished in various ways, including building special components called ``autohandlers,'' which run before anything else for requests within a certain directory tree. An autohandler could do some processing and set up data for a display template that includes only minimal in-line Perl. There is also support for an object-oriented site approach, applying concepts such as inheritance to the site directory structure. For example, the autohandler component at /store/book/ might inherit a standard layout from the autohandler at /store/, but override the background color and navigation bar. Then /store/music/ can do the same, with a different color. This can be a powerful paradigm for developing large sites. Note that this inheritance is only supported at the level of methods defined in autohandler components. You can't override the component /store/foo.html with another one at /store/book/foo.html.

Mason's approach to debugging is to create ``debug files'' that run Mason outside of a Web server environment, providing a fake Web request and activating the debugger. This can be helpful if you're having trouble getting Apache::DB to behave under mod_perl, or using an execution environment that doesn't provide built-in debugger support.

Another unique feature is the ability to leave the static text parts of a large template on disk, and pull them in with a file seek when needed rather than keeping them in RAM. This exchanges some speed for a significant savings in memory when dealing with templates that are mostly static text.

There are many other features in this package, including filtering of HTML output and a page previewing utility. Session support is not built-in, but a simple example showing how to integrate with Apache::Session is included. Mason's feature set can be a bit overwhelming for newbies, but the high-quality documentation and helpful user community go a long way.

HTML::Embperl

http://perl.apache.org/embperl/

Embperl makes its language choice known up front: embedded perl. It is one of the most popular in-line Perl templating tools and has been around longer than most of the others. It has a solid reputation for speed and ease of use.

It is commonly used in a callback style, with Embperl intercepting URIs and processing the requested file. However, it can optionally be invoked through a subroutine call from another program, allowing it to be used in a pipeline style. Templates are compiled to Perl bytecode and cached.

Embperl has been around long enough to build an impressive list of features. It has the ability to run code inside a Safe compartment, support for automatically cleaning globals to make mod_perl coding easier, and extensive debugging tools including the ability to e-mail errors to an administrator.

The main thing that sets Embperl apart from other in-line Perl systems is its tight HTML integration. It can recognize TABLE tags and automatically iterate over them for the length of an array. It automatically provides sticky form widgets. An array or hash reference placed at the end of a query string in an HREF or SRC attribute will be automatically expanded into query string ``name=value'' format. META HTTP-EQUIV tags are turned into true HTTP headers.

Another reason people like Embperl is that it makes some of the common tasks of Web application coding so simple. For example, all form data is always available just by reading the magic variable %fdat. Sessions are supported just as easily, by reading and writing to the magic %udat hash. There is also a hash for storing persistent application state. HTML-escaping is automatic (though it can be toggled on and off).

Embperl includes something called EmbperlObject, which allows you to apply OO concepts to your site hierarchy in a similar way to the autohandler and inheritance features of Mason, mentioned above. This is a convenient way to code sites with styles that vary by area, and is worth checking out. EmbperlObject includes the ability to do overrides on a file level. This means that you can have a directory like /store/music that overrides specific templates and inherits the rest from a parent directory.

One drawback of older versions of Embperl was the necessity to use built-in replacements for most of Perl's control structures like ``if'' and ``foreach'' when they are being wrapped around non-Perl sections. For example:

  [$ if ($foo) $]
    Looks like a foo!
  [$ else $]
    Nope, it's a bar.
  [$ endif $]

These may seem out of place in a system based around in-line Perl. As of version 1.2b2, it is possible to use Perl's standard syntax instead:

  [$ if ($foo) { $]
    Looks like a foo!
  [$ } else { $]
    Nope, it's a bar.
  [$ } $]

At the time of this writing, a new 2.x branch of Embperl is in beta testing. This includes some interesting features such as a more flexible parsing scheme that can be modified to users' tastes. It also supports direct use of the Perl debugger on Embperl templates and provides performance improvements.

Apache::AxKit

http://axkit.org/

AxKit is the first mod_perl page generation system to be built from the ground up around XML. Technically, AxKit is not a templating tool but rather a framework for stringing together different modules that generate and transform XML data. In fact, it can optionally use Template Toolkit as an XML transformation language. However, it deserves coverage here since it is also the home of some templating tools that are not represented elsewhere.

In its simplest form, AxKit maps XML files to XSL stylesheets that it can process using commonly available XSLT modules like XML::XSLT or XML::Sablotron. The rules for mapping a stylesheet to a request are flexible, and they can incorporate query strings, cookies and other attributes of the request. The idea is that you can use this feature to handle a wide variety of clients with differing display capabilities by choosing the right stylesheet.

Recognizing that not everyone is a fan of XSL's somewhat obtuse syntax, Matt Sergeant has provided an alternate stylesheet language called XPathScript. XPathScript allows you to write a stylesheet using text with embedded Perl code. This is similar to the other embedded Perl templating tools, but the focus is on using the built-in XPath functions for querying an XML document and manipulating the retrieved data. XPathScript can also be used in a declarative fashion, specifying the formatting of particular elements in the XML input. For example, this snippet will change all <foo> tags in an XML document to BAR in the output::

  <%
    $t->{'foo'}{pre}   = 'BAR';
    $t->{'foo'}{post}    = '';
    $t->{'foo'}{showtag} = 0;
  %>
  <%= apply_templates() %>

By using XPathScript's include function (which looks just like SSI), you can build libraries of useful transformations that use this technique.

This is all well and good if you have a bunch of XML files sitting on a disk somewhere, but what about dynamic content? AxKit handles this by allowing you to substitute a different data source for the default file-based one. This can include running some dynamic code on each request to generate the XML data that will be transformed. The distribution includes a module for doing this called XSP. XSP is a language for building an XML DOM using in-line Perl and tag libraries. The tag libraries are specified as stylesheets that can turn XML tags into Perl code. This is demonstrated through the included SQL tag library, which allows you to write an XSP page using XML tags that will connect to a database, execute queries and generate an XML document with the results.

AxKit has some nice performance boosts built into it. It can cache the full output of a page and serve it as a static file on future requests. It can also compress output to speed up downloads for browsers that understand gzip encoding. These can be done with other systems, but they require you to setup additional software. With AxKit, you just enable them in the configuration file.

If all of these languages, tag libraries and stylesheets sound intimidating to you, AxKit may be overkill for your project. However, AxKit has the advantage of being built on approved W3C standards, and many of the skills used in developing for it carry over to other languages and tools.

Apache::ASP

http://www.apache-asp.org/

Apache::ASP started as a port of Microsoft's Active Server Pages technology, and its basic design still follows that model. It uses in-line Perl with a compilation approach and provides a set of simple objects for accessing the request information and formulating a response. Scripts written for Microsoft's ASP using Perl (via ActiveState's PerlScript) can usually be run on this system without changes. (Pages written in VBScript are not supported.)

Like the original ASP, it has hooks for calling specified code when certain events are triggered, such as the start of a new user session. It also provides the same easy-to-use state and session management. Storing and retrieving state data for a whole application or a specific user is as simple as a single method call. It can even support user sessions without cookies -- a unique feature among these systems.

A significant addition that did not come from Microsoft ASP is the XML and XSLT support. There are two options provided: XMLSubs and XSLT transforms. XMLSubs is a way of adding custom tags to your pages. It maps XML tags to your subroutines, so that you can add something like <site:header page="Page Title" /> to your pages and have it translate into a subroutine call like &site::header({title => "Page Title"}). It can handle processing XML tags with body text as well.

The XSLT support allows the output of ASP scripts to be filtered through XSLT for presentation. This allows your ASP scripts to generate XML data and then format that data with a separate XSL stylesheet. This support is provided through integration with the XML::XSLT module.

Apache::ASP provides sticky widgets for forms through the use of the HTML::FillInForm module. It also has built-in support for removing extra whitespace from generated output, gzip compressing output (for browsers that support it), tracking performance using Time::HiRes, automatically mailing error messages to an administrator and many other conveniences and tuning options. This is a mature package that has evolved to handle real-world problems.

One thing to note about the session and state management in this system is that it currently only supports clusters through the use of network file systems such as NFS or SMB. (Joshua Chamas, the module's author, has reported much better results from Samba file sharing than from NFS.) This may be an issue for large-scale server clusters, which usually rely on a relational database for network storage of sessions. Support for database storage of sessions is planned in a future release. In the meantime, instructions are provided for hooking up to Apache::Session.

Text::Template

http://search.cpan.org/search?dist=Text-Template

This module has become the de facto standard general purpose templating module on CPAN. It has an easy interface and thorough documentation. The examples in the docs show a pipeline execution style, but it's easy to write a mod_perl handler that directly invokes templates, allowing a callback style. The module uses in-line Perl. It has the ability to run the in-line code in a Safe compartment, in case you are concerned about mistakes in the code crashing your server.

The module relies on creative uses of in-line code to provide things that people usually expect from templating tools, like includes. This can be good or bad. For example, to include a file you could just call Text::Template::fill_in_file(filename). However, you'll have to specify the complete file path and nothing will stop you from using /etc/passwd as the file to be included. Most of the fancier templating tools have concepts like include paths, which allow you to specify a list of directories to search for included files. You could write a subroutine that works this way, and make it available in your template's namespace, but it's not built in.

Each template is loaded as a separate object. Templates are compiled to Perl and only parsed the first time they are used. However, to take full advantage of this caching in a persistent environment like mod_perl, your program will have to keep track of which templates have been used, since Text::Template does not have a way of globally tracking this and returning cached templates when possible.

Text::Template is not tied to HTML, and is just a templating module, not a Web application framework. It is perfectly at home generating e-mails, PDFs, etc.

Template Toolkit

http://template-toolkit.org/

One of the more recent additions to the templating scene, Template Toolkit, is a flexible mini-language system. It has a complete set of directives for working with data, including loops and conditionals, and it can be extended in a number of ways. In-line Perl code can be enabled with a configuration option, but is generally discouraged. It uses compilation, caching the compiled bytecode in memory and optionally caching the generated Perl code for templates on disk. Although it is commonly used in a pipeline style, the included Apache::Template module allows templates to be invoked directly from URLs.

Template Toolkit has a large feature set, so we'll only be able cover some of the highlights here. The TT distribution sets a gold standard for documentation thoroughness and quality, so it's easy to learn more if you choose to.

One major difference between TT and other systems is that it provides simple access to complex data structures through the concept of a dot operator. This allows people who don't know Perl to access nested lists and hashes or call object methods. For example, we could pass in this Perl data structure:

  $vars = {
           customer => {
                        name    => 'Bubbles',
                        address => {
                                    city => 'Townsville',
                                   }
                       }
          };

Then we can refer to the nested data in the template:

  Hi there, [% customer.name %]!
  How are things in [% customer.address.city %]?

This is simpler and more uniform than the equivalent syntax in Perl. If we pass in an object as part of the data structure, we can use the same notation to call methods within that object. If you've modeled your system's data as a set of objects, this can be convenient.

Templates can define macros and include other templates, and parameters can be passed to either. Included templates can optionally localize their variables so that changes made while the included template is executing do not affect the values of variables in the larger scope.

There is a filter directive, which can be used for post-processing output. Uses for this range from simple HTML entity conversion to automatic truncation (useful for pulldown menus when you want to limit the size of entries) and printing to STDERR.

TT supports a plugin API, which can be used to add extra capabilities to your templates. The provided plug-ins can be broadly organized into data access and formatting. Standard data access plugins include modules for accessing XML data or a DBI data source and using that data within your template. There's a plugin for access to CGI.pm as well.

Formatting plug-ins allow you to display things like dates and prices in a localized style. There's also a table plugin for use in displaying lists in a multi-column format. These formatting plug-ins do a good job of covering the final 5 percent of data display problems that often cause people who are using an in-house system to embed a little bit of HTML in their Perl modules.

In a similar vein, TT includes some nice convenience features for template writers, including eliminating white space around tags and the ability to change the tag delimiters -- things that may sound a little esoteric, but can sometimes make templates significantly easier to use.

The TT distribution also includes a script called ttree, which allows for processing an entire directory tree of templates. This is useful for sites that pre-publish their templated pages and serve them statically. The script checks modification times and only updates pages that require it, providing a make-like functionality. The distribution also includes a sample set of template-driven HTML widgets that can be used to give a consistent look and feel to a collection of documents.

HTML::Template

http://search.cpan.org/search?dist=HTML-Template

HTML::Template is a popular module among those looking to use a mini-language rather than in-line Perl. It uses a simple set of tags that allow looping (even on nested data structures) and conditionals in addition to basic value insertion. The tags are intentionally styled to look like HTML tags, which may be useful for some situations.

As the documentation says, it ``does just one thing and it does quickly and carefully'' -- there is no attempt to add application features like form-handling or session tracking. The module follows a pipeline execution style. Parsed templates are stored in a Perl data structure that can be cached in any combination of memory, shared memory (using IPC::SharedCache) and disk. The documentation is complete and well-written, with plenty of examples.

You may be wondering how this module is different from Template Toolkit, the other popular mini-language system. Beyond the obvious differences in syntax, HTML::Template is faster and simpler, while Template Toolkit has more advanced features, like plug-ins and dot notation. Here's a simple example comparing the syntax:

HTML::Template:

  <TMPL_LOOP list>
      <a href="<TMPL_VAR url>"><b><TMPL_VAR name></b></A>
  </TMPL_LOOP>

Template Toolkit:

  [% FOREACH list %]
      <a href="[% url %]"><b>[% name %]</a></a>
  [% END %]

And now, a few honorable mentions:

HTML_Tree

http://homepage.mac.com/pauljlucas/software/html_tree/

As mentioned earlier, HTML Tree uses a fairly unique method of templating: it loads in an HTML page, parses it to a DOM and then programmatically modifies the contents of nodes. This allows it to use genuine valid HTML documents as templates, something that none of these other modules can do. The learning curve is a little steeper than average, but this may be just the thing if you are concerned about keeping things simple for your HTML coders. Note that the name is ``HTML_Tree,'' not ``HTML::Tree.''

Apache::XPP

http://opensource.cnation.com/projects/XPP/

XPP is an in-line Perl system that compiles to bytecode. Although it is a perfectly good implementation, it has little to differentiate it except for an easy mechanism to define new HTML-like tags that can be used to replace in-line code in templates.

ePerl

http://search.cpan.org/search?dist=Apache-ePerl

Possibly the first module to embed Perl code in a text or HTML file, ePerl is still a viable option in the form of Apache::ePerl. It caches compiled bytecode in memory to achieve solid performance, and some people find it refreshingly simple to use.

CGI::FastTemplate

http://search.cpan.org/search?dist=CGI-FastTemplate

This module takes a minimalistic approach to templating, which makes it unusually well-suited to use in CGI programs. It parses templates with a single regular expression and does not support anything in templates beyond simple variable interpolation. Loops are handled by including the output of other templates. Unfortunately, this leads to a Perl coding style that is more confusing than most, and a proliferation of template files. However, some people swear by this dirt-simple approach.

Pages: 1, 2, 3, 4

Next Pagearrow