Parsing Templates in Memory

Templating System

The templating system code is oriented towards parsing templates stored in the filesystem, in conjunction with a Tcl script that is also stored as a file. However, when the template is not actually stored in the filesystem, you will need to parse it as a string in memory. Two common situations in which this occurs are:

The Parsing Process

Whether the template is ultimately stored in a file or not, the templating system follows the same basic process during the parsing process:

  1. Prepare data sources. Some Tcl code is evaluated to prepare data sources (scalars, lists, multirow data structures) for merging with the template. (For file-based templates the interpreted code is cached in a procedure after the first time).
  2. Compile the template.. The template markup is compiled into a chunk of Tcl code that builds the page into a single output string. (For file-based templates the resulting code is cached in a procedure after the first time).
  3. Evaluate the compiled template. The template code is evaluated in the same stack frame as the data source code, so that all variables declared as data sources are directly available to the template. The result of the evaluation step is a single string, which normally is written to the connection.

How to Parse Templates in Memory

The templating system provides a low-level API that allows you to perform the three steps described above in the context of your own code:

# set up any number of data sources:

set first_name George

query cars multirow "
  select make, model from cars where first_name = :first_name"

# get the template.  This may be a static string, be queried from the
# database, generated dynamically, etc.

set template "
Hello @first_name@!

<multiple name=cars>
  @cars.rownum@. @cars.make@ @cars.model@<br>
</multiple>
"

# compile the template.  The templating system takes the
# result of this step and wraps it in a proc so that it is 
# bytecode-cached in the interpreter.  You may wish to implement
# some sort of simple caching here as well.

set code [template::adp_compile -string $template]

# evaluate the template code.  Note that you pass a reference
# to the variable containing the code, not the value itself.  The code
# is evaluated in the calling stack frame (by uplevel) so that
# the above data sources are directly accessible.

set output [template::adp_eval code]

# now use the output however you wish
      
Also see the "string" demo.

Generating Templates from Other Templates

In some cases, the template itself may be based on yet another base template. For example, the templating system itself generates form templates based on a generic "style" template. The generic template primarily depends on a single data source, elements, which references the element list for a particular form object. A single multipleloop is used to lay out the specific formwidget and formgroup tags, along with labels and validation text, for the form. The output of this first step is then rendered into HTML and returned to the user.

Note that the generic "style" template contains templating tags (formwidget, formgroup, if etc.) that must be "protected" during the first step. The templating system provides the noparse tag to do this.



Last modified: $Id: memory.html,v 1.4 2024/09/11 06:15:48 gustafn Exp $