Templates are tools for creating text output reports. The beauty of templates is that they allow a separation of the code that generates/calculates information from the code that produces the output. The template code produces the output and is done in plain text in the type of output desired with a few directives that are used to insert the real information, check conditions, do loops, include other files, etc. This article will demonstrate more features than my original post about templates. The demo program mg_report_demo.pro (docs uses three templates to create its output: the main template, the header, and the footer.

Demo output

The files needed to use the template are the MGffTemplate class (docs) and the MGffTokenizer class (docs).

Using the template object is simply a matter of instantiating an MGffTemplate object that uses a template file, in this case report.tt; create a a structure of variables; and call the process method with the structure of variables. In MG_REPORT_DEMO this is done with:

template = obj_new('MGffTemplate', 'report.tt')
variables = { dir: myDir, $
              files: infoArray, $
              header: 'header.tt', $
              footer: 'footer.tt' $
            }
template->process, variables, 'report.html'
obj_destroy, template

The fields of the structure variables will be variables accessible in the template via directives. Directives are enclosed between squares brackets and the percent sign. For example, the myDir field can be included in the output by:

<h1>Results for [% dir %]</h1>

Also, arbitrary IDL expressions can put their results into the output as well:

Reported on [% systime() %]

There are also directives to include output from other files. The include directive simply copies the contents of the file into the output, no processing is done. So the following snippet in report.tt,

[% INCLUDE footer %]

puts the contents of footer.tt (since that is stored in the footer variable), into the output. So Output produced by MGffTemplate is copied directly and any directives in it would be ignored (just copied verbatim). To process the file as another template, passing the variables structure to it and processing its directives, use the include_template directive. Here,

<p>[% INCLUDE_TEMPLATE header %]</p>
<p>The header variable is set to header.tt which is:</p>
<h1>Results for [% dir %]</h1>
<p class="date">Reported on [% systime() %]</p>

The last directive demonstrated is the “foreach” directive which loops through an array. Any array can be used, but an array of structures is particularly useful. The files field of the variables structure is an array of structures of the form:

imageInfo = { filename: '', $
              channels: 0L, $
              dimensions: lonarr(2), $
              has_palette: 0L, $
              num_images: 0L, $
              image_index: 0L, $
              pixel_type: 0L, $
              type: '' $
            }

The following (partial snippet) code accesses the various fields of each element of the files array in turn:

<p>[% FOREACH f IN files %]</p>
<h2>[% f.filename %]</h2>
<table class="[% f.type %]">
  <tbody>
    <tr>
      <td>Number of bands</td>
      <td>[% f.channels %]</td>
    </tr>
    <tr>
      <td>Type</td>
      <td>[% strlowcase(f.type) %]</td>
    </tr>
  </tbody>
</table>
[% END %]

See report.tt for the full loop.

This example used HTML output, but that is not required. Any text can be output, i.e. XML, TeX, etc.