module Xtmpl:sig
..end
Rewrite XML Xtmpl.tree
s 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
typename =
string * string
(prefix, s)
, where prefix can be the empty string.
When the prefix is not empty, it corresponds to the notation prefix:foo
for XML tags and attribute names.module Name_ord:Map.OrderedType
with type t = name
module Name_map:Map.S
with type key = name
module Name_set:Set.S
with type elt = name
type 'a
env
type'a
callback ='a ->
'a env -> attributes -> tree list -> 'a * tree list
'a callback
takes data of type 'a
, a 'a env
, attributes and XML nodes.
It returns a potentially new data of type 'a
and XML nodes. The attributes are
the attributes of the node being rewritten, and the XML trees in parameter are the
XML children of this node. The environment must be a 'a env
so that
if can be used in the callback to perform rewriting, returning a
new data of type 'a
.type
tree =
| |
E of |
| |
D of |
typeattributes =
tree list Name_map.t
val merge_cdata : tree -> tree
D
nodes into one D
node.val merge_cdata_list : tree list -> tree list
typerewrite_stack =
(name * attributes * tree list) list
exception Loop of rewrite_stack
Loop
exception is raised when the rewrite stack
is higher than a default value of 100. This value can be changed
by setting the XTMPL_REWRITE_DEPTH_LIMIT
environment variable.
Default value is 100
.val string_of_stack : rewrite_stack -> string
Here are some convenient functions to work with attributes: building, querying.
val atts_empty : attributes
Xtmpl.attributes
structure.val atts_of_list : ?atts:attributes ->
(name * tree list) list -> attributes
atts_of_list list
returns an Xtmpl.attributes
structure from the given
list of pairs (name, xml tree list) ; (name, xml tree list) ; ...
.
The last pair of the list is added first (using List.fold_right
).atts
: can be used to specify an existing Xtmpl.attributes
structure to
add bindings to, instead of starting from an empty one.val atts_one : ?atts:attributes -> name -> tree list -> attributes
val atts_remove : name -> attributes -> attributes
atts_remove name attributes
removes the binding to name
from the
attributes
.val atts_replace : name -> tree list -> attributes -> attributes
atts_replace name xmls attributes
adds a new bindings from name
to
xmls
in attributes
. If name
was previously bound, the previous
binding is removed.
atts_replace ~atts name xmls
is equivalent to atts_replace name xmls atts
.val get_arg : attributes -> name -> tree list option
get_arg attributes name
returns the xml tree list bound to name
in
attributes
. Return None
if no binding was found for name
.val get_arg_cdata : attributes -> name -> string option
Xtmpl.get_arg
but return a string s
only if name
is bound to
a single CDATA XML node ([D s]
).
In particular, if name
is bound to a list of XML tree, or to
a single tree which is not a CDATA, the function returns None
.val opt_arg : attributes -> ?def:tree list -> name -> tree list
opt_arg attributes ?def name
returns the tree list associated to name
in the attributes
or a default value. This default value can be
specified with the def
parameter. If no default value is specified, then
the empty list is used.val opt_arg_cdata : attributes -> ?def:string -> name -> string
val string_of_args : attributes -> string
a="foo" b="bar" ...
.
Note that the argument names are output verbatim, but the
argument values are escaped with the %S
format.
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 : unit -> 'a env
Xtmpl.tag_main
to a function such as (fun data _env _atts subs -> (data, subs))
,
i.e. only returning the given data and subnodes.val env_add : ?prefix:string -> string -> 'a callback -> 'a env -> 'a env
env_add "double" (fun acc _ _ xml -> (acc, xml @ xml))
binds the key
("", "double")
to a callback that doubles an XML subtree.
env_add ~prefix: "foo" "double" (fun acc _ _ xml -> (acc, 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 -> 'a env -> 'a callback option
If the binding is not found, returns None
.
val string_of_env : 'a env -> string
val env_add_att : ?prefix:string -> string -> tree list -> 'a env -> 'a env
The most frequent operation performed by a callback is to return constant XML subtrees. This convenience function lets you provide the XML subtrees.
env_add_att "logo" [ E (("","img"), atts_one ("","src") [C "logo.png"], [] ] env
binds the key ("","logo")
to a callback that returns an XHTML image tag.
val env_of_list : ?env:'a env -> (name * 'a callback) list -> 'a env
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.
val tag_main : string
"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.xml_of_string
and, most importantly, by the
Xtmpl.apply_to_string
, Xtmpl.apply_to_file
, Xtmpl.apply_into_file
and
Xtmpl.apply_string_into_file
functions.
val tag_env : string
"env_"
.
See the template rules in the Templating engine section below for more
information about this tag.
val att_defer : string
"defer_"
. See the engine section
for details.val att_escamp : string
"escamp_"
. This attribute
is used when converting XML to string or reading XML from a string.
The CDATA associated to this attribute indicates the other attributes
in which the ampersands must be escaped (when parsing XML from an
attribute string) or unescaped (when printing XML to an attribute string).
This is useful for urls with &, for example in <a href="...">
nodes.
Example: In <a escamp_="href", href="http://foo.fr?v1=3amp;v2=4">...</a>
.
As attributes are parsed as XML, setting the escamp_
attribute to "href"
will make the ampersand escaped. The attribute is kept during rewriting.
When the XML tree will be converted to a string, the escamp_
attribute
will be removed. Several attribute names can be indicated, using ','
or ';'
as separator, as in
<a escamp_="href, foo, gee:buz" href="..." ...>...</a>
.
This treatment is done in Xtmpl.xmls_of_atts
(escaping) and Xtmpl.string_of_xml_atts
(unescaping).
val att_protect : string
Xtmpl.att_escamp
.val string_of_xml : tree -> string
The returned string does not include the initial <?xml ... ?>
.
val string_of_xmls : tree list -> string
Xtmpl.string_of_xml
to concatenate a list of xml trees into one string,
with no separator.val string_of_xml_atts : attributes -> (name * string) list
val xml_of_string : ?add_main:bool -> string -> tree
Failure
when a parsing error occurs, including the source string.val xmls_of_atts : (name * string) list -> attributes
Xtmpl.attributes
structure. The value
associated to each name must be valid XML. See also Xtmpl.att_escamp
.val xml_of_file : string -> tree
Xtmpl.xml_of_string
but read from a file.
The apply_*
functions apply a given environment and data 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
). They also return data
as the result of the callbacks called, as in a classic fold function (callbacks
take the data in parameter, as the environment, the attributes and subnodes
of the rewritten node).
The rewrite rules are applied until a fix-point is reached.
If the XTMPL_FIXPOINT_LIMIT
environment variable contains a valid integer n
,
it is used as a fix-point limit: if no fix-point is reached in n
iterations,
then a Failure
exception is raised.
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 data env {("","author")->[ D "Rammstein"]|("","name")->[D "Reise, Reise"]} xml
where env
is the current environment and xml
represents the
two children <track>..</track>
elements.
Example: assuming that the environnement was build using
env_add "x2" (fun data _ _ xml -> (data, xml @ xml)) env
,
then <x2>A</x2>
is rewritten as AA
.
Example: <x2><x2>A</x2></x2>
is first rewritten as
<x2>A</x2><x2>A</x2>
, and then as AAAA
.
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 data _ _ xml -> (data, 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="<b>A</b>"><a/></env_>
is
replaced by <a/>
, which in turn is replaced by
<b>A</b>
.
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
.
protect_
attribute, then the value
must be CDATA and contains a list of names to remove from the environment
when descending in the children. The names are separated by ','
or ';'
,
for example: <foo protect_="title,id,foo:bar" ..>...</foo>
.
val apply_to_string : 'a -> 'a env -> string -> 'a * tree list
See above for how an iteration is applied.
val apply_to_file : 'a -> 'a env -> string -> 'a * tree list
Xtmpl.apply_to_string
, but reads the XML from a file.val apply_to_xmls : 'a -> 'a env -> tree list -> 'a * tree list
Xtmpl.apply_to_string
, but applies to a list of XML trees.val apply_into_file : 'a -> ?head:string -> 'a env -> infile:string -> outfile:string -> 'a
Xtmpl.apply_to_file
, but writes the result back to a file.
For instance, apply_to_file data 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 : 'a -> ?head:string -> 'a env -> outfile:string -> string -> 'a
Xtmpl.apply_into_file
, but read the XML from a string instead of a file.