Report generation using templates

Templates are a technique for inserting data into pre-defined text. They are a more powerful version of the format codes available in the STRING and PRINT routines. Whenever a few pieces of data need to be inserted into a lot of text, consider using templates.

For example, when creating a web page as part of an IDL script, it might be necessary to create something like below:

<p>The temperature in Boulder is [% temp %] C.</p>

The value for the temp variable could then be inserted into the HTML when the template is filled out. To do this, place the above text into a file, say temperature.tt, and create a template object in the following manner:

IDL> template = obj_new('MGffTemplate', 'temperature.tt')

Now, the template can be passed some data to fill in the variables using its process method. The simplest way is to pass a structure the variable names as its field names:

IDL> template->process, { temp: 77.0 }, 'temperature.html'

This should create an output file temperature.html containing:

<p>The temperature in Boulder is 77.0000 C.</p>

There are many directives that can be used in templates besides the simple variable insertion. The FOREACH directive can be used to loop over the elements of an array in the variables structure. For example, the following template creates an HTML ordered list from items in an array:

<p>The temperatures over the last [% n_elements(temps) %] days were: 
  <ol>[% FOREACH t IN temps %]
    <li>[% t %]</li>
  [% END %]</ol>
</p>

This template also demonstrates that an expression can be used instead of just a simple variable. A temps array is passed to this template like the following:

IDL> template->process, { temps: [77., 78., 77.] }, 'temperature.html'

The available directives are:

  • [% expression %]
  • [% FOREACH a IN arr %][% END %]
  • [% IF expr THEN %][% ELSE %][% END %]
  • [% INCLUDE filename_variable %]
  • [% INCLUDE_TEMPLATE template_filename %]
  • [% INSERT filename %]
  • [% SCOPE var %]

We’ve already seen the first two directives. The [% IF %] directive allows text to be inserted conditionally, with an optional [% ELSE %] clause. The [% INCLUDE %], [% INCLUDE_TEMPLATE %], and [% INSERT %] directives allow text, or another template, from another file to be inserted. The last directive, [% SCOPE %], is useful when passing data via the alternative method: using objects instead of structures.

Passing objects with a getVariable method allows templates to be used in much more complex situations. This technique is how IDLdoc produces all of its output. To create an object that can be passed to the template’s process method, simply define a getVariable method conforming to the following interface:

function classname::getVariable, name, found=found

The name of the variable desired is passed as a string in the name parameter and the value of the variable should be returned from the function. The FOUND keyword should return whether the name variable was found.