Module Xtmpl

module Xtmpl: sig .. end
Xml templating library.

Rewrite XML Xtmpl.trees using Xtmpl.callback rules provided by the Xtmpl.env environment.

A complete description of the templating rules is available in the Templating engine section below.


exception No_change
This exception can be raised by callbacks to indicate that the node to be rewritten remains unchanged.
type name = string * string 
type attribute = name * string 
type env 
type callback = env -> attribute list -> tree list -> tree list 
type tree = 
| E of name * attribute list * tree list
| D of string

Environment

An Xtmpl.env is a Xtmpl.name-to-Xtmpl.callback associative map. In addition to basic manipulation functions, the functions Xtmpl.env_add_att and Xtmpl.env_of_list provide convenient shortcuts for common operations.

The environments are immutable, all mutating operations return new environments.

val env_empty : env
An environment that contains only one binding, associating Xtmpl.tag_main to a function returning its subnodes.
val env_add : ?prefix:string -> string -> callback -> env -> env
Add a binding to an environment.

env_add "double" (fun _ _ xml -> xml @ xml) binds the key ("", "double") to a callback that doubles an XML subtree.

env_add ~prefix: "foo" "double" (fun _ _ xml -> xml @ xml) does the same but for the key ("foo", "double").

If the same key was already bound, the previous binding is replaced.

prefix : is "" by default.
val env_get : name -> env -> callback option
Get a binding from an environment.

If the binding is not found, returns None.

val string_of_env : env -> string
String representation of all the keys in the environment.
val env_add_att : ?prefix:string -> string -> string -> env -> env
Bind a callback that returns some XML.

The most frequent operation performed by a callback is to return a constant XML subtree. This convenience function lets you provide the XML subtree as a string.

env_add_att "logo" "<img src=\"logo.png\"/>" env binds the key ("","logo") to a callback that returns an XHTML image tag.

Note that the provided XML is automatically wrapped in the Xtmpl.tag_main tag, which will cause the corresponding templating rules to be applied to it

val env_of_list : ?env:env -> (name * callback) list -> env
Add several bindings at once.

This convenience function saves you the effort of calling Xtmpl.env_add several times yourself.

env_of_list ~env:env [ (ns1, k1), f1 ; (ns2, k2), f2 ] is equivalent to env_add ~prefix: ns1 k1 f1 (env_add ~prefix: ns2 k2 f2 env). This means that one key is present twice in the list, the first association in the list will hide the second one in the resulting environment.

env : The environment to which bindings are added. If not provided, Xtmpl.env_empty is used.

XML Manipulation


val tag_main : string
A dummy tag, currently "main_". It is used when parsing a string as an XML tree, to ensure that we will parse a tree and not a list of trees. For this purpose, the tag is used to enclosed a string before parsing it.

Used by Xtmpl.env_add_att, Xtmpl.xml_of_string and, most importantly, by the apply_* functions.

val tag_env : string
The environment tag, currently "env_".

See the template rules in the templating engine section below for more information about this tag.

val string_of_xml : tree -> string
Output an XML string.

The returned string does not include the initial <?xml ... ?>.

val string_of_xmls : tree list -> string
Use Xtmpl.string_of_xml to concatenate a list of xml trees into one string, with no separator.
val xml_of_string : ?add_main:bool -> string -> tree
Parses a string as XML.
Raises Failure when a parsing error occurs, includes the source string.
add_main : if true, adds <main_>..</main_> around the string (see Xtmpl.tag_main).
val xml_of_file : string -> tree
Same as Xtmpl.xml_of_string but read from a file.

Templating engine

The apply_* functions apply a given environment to XML tree(s). These trees are given as parameter (Xtmpl.apply_to_xmls) or can be read from a file (Xtmpl.apply_to_file), or a string (Xtmpl.apply_to_string).

The functions return the result of the rewrite as XML trees, or can write it to a file (Xtmpl.apply_into_file).

The rewrite rules are applied until a fix-point is reached.

I. A single iteration descends recursively into the XML tree. If an element has a callback associated in the environment, then the callback is applied to the node's attributes and children.

Example: consider the following XML:

<album author="Rammstein" name="Reise, Reise">
  <track>Los</track>
  <track>Mein Teil</track>
</album>

This would look for a callback bound to ("","album") in the environment and call it using callback env [("","author"),"Rammstein"; ("","name"),"Reise, Reise"] xml where env is the current environment and xml represents the two children <track>..</track> elements.

II. The callback returns a new list of elements that is used instead of the old element.

Example: assuming that env_add "x2" (fun _ _ xml -> xml @ xml), then <x2>A</x2> is rewritten as AA.

III. The engine then recursively descends into those replaced elements (this means that a poorly conceived rule set may well never terminate).

Example: <x2><x2>A</x2></x2> is first rewritten as <x2>A</x2><x2>A</x2>, and then as AAAA.

IV. The env_ and main_ elements (see Xtmpl.tag_env and Xtmpl.tag_main) are a special case: both are automatically replaced with their children (as if their callback was (fun _ _ xml -> xml)).

env_ effectively changes the environment used when processing its children by adding the bindings defined by its arguments (using Xtmpl.env_add_att, hence the name).

Example: <env_ a="&lt;b&gt;A&lt;/b&gt;"><a/></env_> is replaced by <a/>, which in turn is replaced by <b>A</b>.

V. If an element has a defer_ attribute (that is greater than zero), then it is not processed and the attribute is decremented by one, and the process recursively applies to its children.

Example: <x2 defer_="1"><x2>A</x2></x2> is rewritten as <x2 defer_="0">AA</x2>. The next iteration will effectively apply the rule to the node and return AAAA.

val apply_to_string : env -> string -> tree list
Applies as many iterations as necessary to a piece of XML (represented as an unparsed string) to reach a fix-point.

See above for how an iteration is applied.

val apply_to_file : env -> string -> tree list
As Xtmpl.apply_to_string, but reads the XML from a file.
val apply_to_xmls : env -> tree list -> tree list
As Xtmpl.apply_to_string, but applies to a list of XML trees.
val apply_into_file : ?head:string -> env -> infile:string -> outfile:string -> unit
As Xtmpl.apply_to_file, but writes the result back to a file.

For instance, apply_to_file env ~infile:"source.xml" ~outfile: "dest.xml".

head : Prepend this string to the XML that is output to the file. By default, nothing is prepended.
val apply_string_into_file : ?head:string -> env -> outfile:string -> string -> unit
As Xtmpl.apply_into_file, but read the XML from a string instead of a file.

Utilities

Several useful functions when workin with XML.

val get_arg : attribute list -> name -> string option
Finds a binding in an attribute list.

This performs the same as List.assoc, but returns an optional string instead of raising Not_found.

val string_of_args : attribute list -> string
A string representation of an argument list.

string_of_args ["a","x";"b","y"] returns a="x" b="y". Note that the argument names are output verbatim, but the argument values are escaped with the %S format.

val opt_arg : attribute list -> ?def:string -> name -> string
Finds a binding in an associative list, or returns a default.

This performs the same as List.assoc, but returns the provided default value instead of raising Not_found.

def : Default value, returned for missing bindings. If not provided, an empty string is used.