Templating System Appendix D: Parsing templates in memory

## Parsing Templates in Memory

Templating System

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

- Templates are stored in the database.
- Templates are generated dynamically, possibly based in turn on a "style" template. This is how ATS auto-generates forms.

### 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 `multiple`loop 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.

templating@arsdigita.com
Last modified: $Id: memory.html,v 1.1.1.1 2001/03/13 22:59:27 ben Exp $