ionflux.org | Impressum

Template Engine

Introduction

The Ionflux Tools template engine is available both as a C++ class (Ionflux::Tools::Template), which you can include in your projects, and a standalone template processor, iftpl (see iftpl), which you can use to process templates. iftpl is designed to work with configuration files. The Ionflux Tools Class Library also provides a class for handling these (see Ionflux::Tools::ConfigTree and Configuration file I/O).

Templates

The purpose of a template is to separate data from presentation, i.e. to be able to change the representation of data without actually touching the data itself and vice versa. A representation of data can then be generated easily by invoking a template processor, such as iftpl or Ionflux::Tools::Template on a template and set of data. A template consists of a combination of arbitrary text and template tags, which may be stored in a file or a buffer in memory. Template tags are used as special instructions to the template processor. For example, a tag may instruct the template processor to substitute the value of a variable in place of the tag, or to execute a part of the template only if a special condition is satisfied. Some tags, like foreach and if, may be nested to achieve special results.

Variables

Template variables are containers for the data to be used for generating the data representation (or output) of a template. The Ionflux Tools Template Engine uses tree nodes (Ionflux::Tools::Node) to represent all data, so you can also use tree nodes in your configuration files. Each tree node can have an arbitrary number of data entries (like an array) or child nodes (or fields, like a struct or class). A specification of a tree node or data entry, as used in a configuration file, is called a tree path expression.

Tree Path Expressions

The simplest form of a tree path expression is just a name specifying a top-level tree node:

myvar

In a configuration file, you can assign values to tree nodes:

myvar = foo

Subscripts are allowed and may either consist of a numeric index or a name:

myvar[1] = foo
myvar['foo'] = 42

You can also use the resolution operator to access child nodes of a node:

myvar.foo = bar

Actually, resolution in this way is handled the same way as a subscript, so it doesn't really matter which variant you use.

Finally, you can use the contents of a node as a name for a subscript or resolution operand:

foo = 1
bar = baz
myvar[.foo] = 2
myvar.(.bar) = 3

is the same as:

myvar[1] = 2
myvar['baz'] = 3

Note that, in this case, a leading resolution operator is needed to distinguish between a node reference and a subscript by name.

Special Variables

The Ionflux Tools Template Engine has some built-in special variables. You should not attempt to overwrite these yourself, but you may use them in your templates. The special variables are:

Note that __template_file and __config_file are available only if you are using iftpl to process a template.

Template Tags

This section provides an overview of the tags recognized by the Ionflux Tools Template Engine.

include

{include <file>}

This tag is replaced by the contents of another file (which may or may not be a template file itself). file can be an absolute path or a path relative to the current working directory of the application using the template processor (for example iftpl). Any template data included in this way will be treated by the template processor as if it had been there in the template being processed in the first place.

Variable Substitution

{$<path>[|<filter> ...]}
{.<path>[|<filter> ...]}
{&lt;path>[|<filter> ...]}

This tag is replaced by the value contained in the variable path. Optionally, a string filter is applied to the value before the substitution actually takes place (see String Filters). (By the way, it doesn't matter which of the various variants specified above you use in your template. All of them are valid variable substitution tags and behave exactly the same.)

Variable Assignment

{$<path> = <expr>}
{.<path> = <expr>}
{&lt;path> = <expr>}

Assign the value resulting from evaluating expr to the variable specified by path.

foreach

{foreach <iterator> in <path>} ... [{empty} ... ] {/foreach}

A foreach block will process the template section enclosed within its tags once for each element in path. The current element is assigned to the variable iterator. foreach will process data entries of path first, child nodes second. If there are no iterations (i.e. there are neither data entries nor child nodes), an optional empty block will be processed instead of the main foreach block. The value of the iteration counter is made available in the special variable __i[<depth>], where depth is the nesting level of the iteration block, starting from 0. The total number of iterations, including all data entries and child nodes, is made available in the special variable __n[<depth>] (see Special Variables).

first

{first} ... {/first}

A first block is processed only on the first iteration of an iteration block (such as foreach). Outside of an iteration block, the first block simply does nothing. The tag also doesn't do anything if there is but a single element in the iteration, i.e. the total number of iterations is 1 (see single). Each iteration block may have an arbitrary amount of first blocks, and it doesn't matter where they are placed within the iteration block.

mid

{mid} ... {/mid}

A mid block is processed on all but the first and last iteration of an iteration block (such as foreach). Outside of an iteration block, the mid block simply does nothing. The tag also doesn't do anything if there is but a single element in the iteration, i.e. the total number of iterations is 1 (see single). Each iteration block may have an arbitrary amount of mid blocks, and it doesn't matter where they are placed within the iteration block.

last

{last} ... {/last}

A last block is processed only on the last iteration of an iteration block (such as foreach). Outside of an iteration block, the last block simply does nothing. The tag also doesn't do anything if there is but a single element in the iteration, i.e. the total number of iterations is 1 (see single). Each iteration block may have an arbitrary amount of last blocks, and it doesn't matter where they are placed within the iteration block.

single

{single} ... {/single}

A single block is processed only if there is but a single iteration in an iteration block (such as foreach). Outside of an iteration block, the single block simply does nothing. Each iteration block may have an arbitrary amount of single blocks, and it doesn't matter where they are placed within the iteration block.

notfirst

{notfirst} ... {/notfirst}

A notfirst block is processed only if the current iteration is not the first iteration in an iteration block (such as foreach). Outside of an iteration block, the notfirst block simply does nothing. Each iteration block may have an arbitrary amount of notfirst blocks, and it doesn't matter where they are placed within the iteration block.

notmid

{notmid} ... {/notmid}

A notmid block is processed only if the current iteration is not one of the inner iterations (i.e. it is either the first or the last iteration) in an iteration block (such as foreach). Outside of an iteration block, the notmid block simply does nothing. Each iteration block may have an arbitrary amount of notmid blocks, and it doesn't matter where they are placed within the iteration block.

notlast

{notlast} ... {/notlast}

A notlast block is processed only if the current iteration is not the last iteration in an iteration block (such as foreach). Outside of an iteration block, the notlast block simply does nothing. Each iteration block may have an arbitrary amount of notlast blocks, and it doesn't matter where they are placed within the iteration block.

notsingle

{notsingle} ... {/notsingle}

A notsingle block is processed only if there is more than one iteration in an iteration block (such as foreach). Outside of an iteration block, the notsingle block simply does nothing. Each iteration block may have an arbitrary amount of notsingle blocks, and it doesn't matter where they are placed within the iteration block.

if

{if <condition>} ... [{else} ... ] {/if}

An if block is processed only if condition evaluates to true, i.e. is not equal to zero. If the optional else tag is also present, the corresponding block will be processed instead of the if block if condition evaluates to false. You can use most operators and data types in the conditional expression. Data type conversion is performed automatically as necessary to evaluate the expression. Operands will be converted to the data type that most accurately represents the result of an operation. If an operator cannot reasonably be applied to a pair of operands, and they cannot be converted to suitable types either, the template processor will issue a warning.

swrap

{swrap <lineWidth> ['<prefix>'] ['<lineTerm>']}

Soft word wrapping is applied to the data resulting from processing the block enclosed in the swrap tag. Wrapping takes place at whitespace boundaries in the input, with each resulting line no longer than lineWidth, if at all possible. An optional prefix is prepended to each line. The line terminator may be specified explicitly by supplying the optional lineTerm argument.

section

{section <sectionName>}

A section is a part of the template that is not processed until it is referenced with the ref tag. A section may be referenced an arbitrary number of times from within a template. It is also possible to reference a section from within itself, thus allowing for recursive template processing. Note that a section must be defined before it may be referenced.

Warning:
Don't try recursive processing with data entries without adding some break condition. It will likely cause an infinite loop, since each node with a single data element is considered a list with one element which should be iterated over. Thus any iterator variable which is not empty will be iterated over in a recursive section. Child node iterations should work fine.

ref

{ref <referenceName> [restore]}

The ref tag is used to reference a section within a template. The section will be processed in place of the ref tag. If the optional resore switch is specified, the environment will be restored after the section has been processed.


Generated on Tue Mar 14 21:07:13 2006 for Ionflux Tools Class Library (iftools) by  doxygen 1.4.6