Library
Module
Module type
Parameter
Class
Class type
Rewriting XML trees.
Rewrite XML tree
s using callback
rules provided by the env
environment.
A complete description of the templating rules is available in the Templating engine section below.
type attributes = tree list Xml.attributes
Attributes of a XML node in a rewrite tree. Note that the content value of an attribute is a list of XML trees, not just a string.
and tree =
| E of node
XML element
*)| D of Xml.cdata
CDATA
*)| C of Xml.comment
Comment
*)| PI of Xml.proc_inst
Processing instruction
*)val node : ?loc:Xml.loc -> name -> ?atts:attributes -> tree list -> tree
val doc : Xml.prolog -> tree list -> tree Xml.doc
upto_first_element trees
returns the list of trees until the first E
element, included.
val atts_empty : attributes
Empty attributes
structure.
val atts_of_list : ?atts:attributes -> (name * tree list) list -> attributes
atts_of_list list
returns a attributes
structure from the given list of pairs (name, xml tree list) ; (name, xml tree list) ; ...
.
val atts_one : ?atts:attributes -> name -> tree list -> attributes
atts_one ?atts name xmls
is like atts_of_list
but for one attribute.
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.
val get_att : attributes -> name -> tree list option
get_att attributes name
returns the xml tree list bound to name
in attributes
. Return None
if no binding was found for name
.
val get_att_cdata : attributes -> name -> string option
Same as get_att
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_att : attributes -> ?def:tree list -> name -> tree list
opt_att 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_att_cdata : attributes -> ?def:string -> name -> string
Same as opt_att
but looking for CDATA bounded values, as in get_att_cdata
.
An env
is a name
-to-callback
associative map. In addition to basic manipulation functions, the functions env_add_xml
and env_of_list
provide convenient shortcuts for common operations.
The environments are immutable, all mutating operations return new environments.
and 'a callback =
'a ->
'a env ->
?loc:Xml.loc ->
attributes ->
tree list ->
'a * tree list
This exception can be raised by callbacks to indicate that the node to be rewritten remains unchanged.
val env_empty : unit -> 'a env
An environment that contains no binding.
Add a binding to an environment.
env_add_cb "double" (fun acc _ _ xml -> (acc, xml @ xml))
binds the key ("", "double")
to a callback that doubles an XML subtree.
env_add_cb ~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.
Bind a callback that returns some XML.
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_xml "logo" [ E (("","img"), atts_one ("","src") [D "logo.png"], []) ] env
binds the key ("","logo")
to a callback that returns an XHTML image tag.
Get a binding from an environment.
If the binding is not found, returns None
.
val string_of_env : 'a env -> string
String representation of all the keys in the environment.
Add several bindings at once.
This convenience function saves you the effort of calling env_add_cb
several times yourself.
env_of_list ~env:env [ (ns1, k1), f1 ; (ns2, k2), f2 ]
is equivalent to env_add_cb ~prefix: ns1 k1 f1 (env_add_cb ~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.
type rewrite_stack = (name * attributes * tree list * Xml.loc option) list
To catch eventual infinite loops in rewriting, we keep a stack of the rules called.
type error =
| Loop of rewrite_stack
The Loop
error 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.
| Parse_error of Xml.loc * string
| Parse_attribute_error of Xml.loc option * name * string
loc * att name * message
*)| Invalid_attribute_value of string * tree list
| Fixpoint_limit of int
exception Error of error
val loop_error : rewrite_stack -> 'a
val parse_error : Xml.loc -> string -> 'a
val invalid_attribute_value : string -> tree list -> 'a
val string_of_error : error -> string
val string_of_rewrite_stack : rewrite_stack -> string
String representation of the given rewrite stack.
The environment tag, currently "env_"
.
See the template rules in the Templating engine section below for more information about this tag.
The escamp attribute, currently "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>
.
The protect attribute, currently "protect_". See the engine section for details. This attribute is removed when a XML tree is converted to a string, as for att_escamp
.
val from_xml_atts : Xml.str_attributes -> attributes
Convert from a Xml.doc
. Attribute values must be valid XML.
val to_string : ?xml_atts:bool -> tree list -> string
Output an XML string.
val atts_to_string : ?xml_atts:bool -> attributes -> Xml.str_attributes
val from_file : string -> tree list
Same as from_string
but read from a file.
Same as doc_from_string
but read from a file.
Same as merge_cdata
but taking a tree
list.
The apply_*
functions apply a given environment and data to XML tree(s). These trees are given as parameter (apply_to_xmls
) or can be read from a file (apply_to_file
), or a string (apply_to_string
).
The functions return the result of the rewrite as XML trees, or can write it to a file (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.
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 current data and 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 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.
The callback returns a pair composed of (maybe new) data and a new list of elements that is used instead of the old element.
Example: assuming that the environnement was build using env_add_cb "x2" (fun data _ _ xml -> (data, xml @ xml)) env
, then <x2>A</x2>
is rewritten as AA
.
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
.
The env_
element (see tag_env
is a special case: it is automatically replaced with its children (as if its callback was (fun data _ _ xml -> (data, xml))
).
env_
effectively changes the environment used when processing its children by adding the bindings defined by its attributes (using env_add_xml
).
Example: <env_ a="<b>A</b>"><a/></env_>
is replaced by <a/>
, which in turn is replaced by <b>A</b>
.
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
.
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>
.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.
As apply_to_string
, but reads the XML from a file.
As apply_to_string
, but applies to a list of XML trees.
As apply_to_string
, but applies to a doc.
val apply_into_file :
'a ->
?head:string ->
'a env ->
infile:string ->
outfile:string ->
'a
As apply_to_file
, but writes the result back to a file.
For instance, apply_to_file data env ~infile:"source.xml" ~outfile: "dest.xml"
.
val apply_string_into_file :
'a ->
?head:string ->
'a env ->
outfile:string ->
string ->
'a
As apply_into_file
, but read the XML from a string instead of a file.