4 Programming with the CamlTemplate Library
When reading this section, you will probably find it helpful to refer to the CamlTemplate
API documentation, which is generated by ocamldoc and provided in the doc/api
directory of the CamlTemplate distribution.
4.1 The General Procedure
The general procedure is as follows:
-
Create a template cache using Cache.create.
- Create a data model consisting of values of type Model.tvalue.
- Load a template using Cache.get_template.
- Pass the template to the merge function to generate output.
Here is `Hello, world!' with a template. The template is as follows:
Here is the message: ${message}
And here is a program that uses it:
open Printf ;;
open CamlTemplate.Model ;;
let _ =
(* Make a template cache. *)
let cache = CamlTemplate.Cache.create () in
(* Create a model. *)
let model = Hashtbl.create 4 in
Hashtbl.add model "message"
(Tstr "Hello, world!");
try
(* Get the template. *)
let tmpl =
CamlTemplate.Cache.get_template
cache "hello.tmpl"
(* Make a buffer for the output. *)
and buf = Buffer.create 256 in
(* Generate output. *)
CamlTemplate.merge tmpl model buf;
print_string (Buffer.contents buf)
with
CamlTemplate.Syntax_error msg ->
eprintf "\n%s\n" msg
| CamlTemplate.Template_error msg ->
eprintf "\n%s\n" msg ;;
There are other examples in the examples directory of the distribution.
4.2 Template Data Models
A template data model is a tree of values; these values can be scalars (strings, integers
or booleans), lists, hashtables or functions. The root of the tree must be a hashtable.
In a template, an identifier by itself is the name of an entry in that root hashtable.
Tabular data can be represented as a list of hashes of scalars. Each element in the list
represents a row in the table, and consists of a hash in which the names are column names
and the values are cell values. Such a model can be handled as shown in
Section 2.3.
4.3 Loading and Caching Templates
Once loaded and parsed, templates are cached; the Cache module provides functions
for creating template caches, getting templates from them and configuring the behaviour of
a cache (e.g. how often it is refreshed). By default, templates are loaded from files,
but you can provide a class of type source_loader to load them from another
source.
The #include and #open statements fetch the included or opened template from
the cache when the enclosing template is merged. Therefore, if an #include or #open refers to a template that doesn't exist, this won't be detected until the outer
template is merged.
Macros are stored in the templates in which they are defined. When a template containing
a macro definition changes, the macro definition is updated as well.
4.4 Threads
If CamlTemplate has been compiled with thread support, multiple threads can safely pass
the same template (or different templates) to the merge function, and multiple
templates running in different threads can safely use the same model, as long as no
template function changes the model. (Note that none of the template statements,
including #set and #var, can change the model.) Values set using #set and #var are visible only to the thread that set them.
4.5 Error Handling
The get_template function raises Syntax_error if it cannot parse a template.
It may also raise other exceptions if it fails to read template source code because of an
I/O error.
If a template cannot be merged because of a run-time error (e.g. a wrong data type), the
merge function raises Template_error.
If a Caml function called from a template is unable to complete successfully, it can raise
Template_function_error; this causes merge to raise Template_error.