Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > d9c1887ff364dc87e282490223567c41 > files > 123

ocaml-pxp-1.2.1-1mdv2010.0.i586.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel="stylesheet" href="style.css" type="text/css">
<meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type">
<link rel="Start" href="index.html">
<link rel="previous" href="Intro_trees.html">
<link rel="next" href="Intro_namespaces.html">
<link rel="Up" href="index.html">
<link title="Index of types" rel=Appendix href="index_types.html">
<link title="Index of exceptions" rel=Appendix href="index_exceptions.html">
<link title="Index of values" rel=Appendix href="index_values.html">
<link title="Index of class methods" rel=Appendix href="index_methods.html">
<link title="Index of classes" rel=Appendix href="index_classes.html">
<link title="Index of class types" rel=Appendix href="index_class_types.html">
<link title="Index of modules" rel=Appendix href="index_modules.html">
<link title="Index of module types" rel=Appendix href="index_module_types.html">
<link title="Pxp_types" rel="Chapter" href="Pxp_types.html">
<link title="Pxp_document" rel="Chapter" href="Pxp_document.html">
<link title="Pxp_dtd" rel="Chapter" href="Pxp_dtd.html">
<link title="Pxp_tree_parser" rel="Chapter" href="Pxp_tree_parser.html">
<link title="Pxp_core_types" rel="Chapter" href="Pxp_core_types.html">
<link title="Pxp_ev_parser" rel="Chapter" href="Pxp_ev_parser.html">
<link title="Pxp_event" rel="Chapter" href="Pxp_event.html">
<link title="Pxp_dtd_parser" rel="Chapter" href="Pxp_dtd_parser.html">
<link title="Pxp_codewriter" rel="Chapter" href="Pxp_codewriter.html">
<link title="Pxp_marshal" rel="Chapter" href="Pxp_marshal.html">
<link title="Pxp_yacc" rel="Chapter" href="Pxp_yacc.html">
<link title="Pxp_reader" rel="Chapter" href="Pxp_reader.html">
<link title="Intro_trees" rel="Chapter" href="Intro_trees.html">
<link title="Intro_extensions" rel="Chapter" href="Intro_extensions.html">
<link title="Intro_namespaces" rel="Chapter" href="Intro_namespaces.html">
<link title="Intro_events" rel="Chapter" href="Intro_events.html">
<link title="Intro_resolution" rel="Chapter" href="Intro_resolution.html">
<link title="Intro_getting_started" rel="Chapter" href="Intro_getting_started.html">
<link title="Intro_advanced" rel="Chapter" href="Intro_advanced.html">
<link title="Intro_preprocessor" rel="Chapter" href="Intro_preprocessor.html">
<link title="Example_readme" rel="Chapter" href="Example_readme.html"><link title="Node extensions" rel="Section" href="#1_Nodeextensions">
<link title="How to define an extension class" rel="Subsection" href="#defext">
<link title="How to bind extension classes to element types" rel="Subsection" href="#bindext">
<link title="An example" rel="Subsection" href="#example">
<title>PXP Reference : Intro_extensions</title>
</head>
<body>
<div class="navbar"><a href="Intro_trees.html">Previous</a>
&nbsp;<a href="index.html">Up</a>
&nbsp;<a href="Intro_namespaces.html">Next</a>
</div>
<center><h1>Intro_extensions</h1></center>
<br>
<br>
This text explains the custom node extensions that can be attached
to XML trees. This feature can be ignored by users that do not need
it. We effectively comment the class type <a href="Pxp_document.extension.html"><code class="code"><span class="constructor">Pxp_document</span>.extension</code></a>
here.
<p>

<a name="1_Nodeextensions"></a>
<h1>Node extensions</h1>
<p>

Every node in a tree has a so-called extension. By default, the
extension is practically empty and only present for formal uniformity.
However, one can also define custom extension classes, and effectively
make new methods available to nodes.
<p>

The type <a href="Pxp_document.extension.html"><code class="code"><span class="constructor">Pxp_document</span>.extension</code></a> is:
<p>

<pre></pre><code class="code"><span class="keyword">class</span>&nbsp;<span class="keyword">type</span>&nbsp;[&nbsp;<span class="keywordsign">'</span>node&nbsp;]&nbsp;extension&nbsp;=<br>
&nbsp;&nbsp;<span class="keyword">object</span>&nbsp;(<span class="keywordsign">'</span>self)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;clone&nbsp;:&nbsp;<span class="keywordsign">'</span>self<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;node&nbsp;:&nbsp;<span class="keywordsign">'</span>node<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;set_node&nbsp;:&nbsp;<span class="keywordsign">'</span>node&nbsp;<span class="keywordsign">-&gt;</span>&nbsp;unit<br>
&nbsp;&nbsp;<span class="keyword">end</span><br>
</code><pre></pre>
<p>

Every node has such an extension object, as the following picture shows.
Of course, the idea is to equip the extension object with additional
methods and not only <code class="code">clone</code>, <code class="code">node</code>, and <code class="code">set_node</code> - which are simply
the bare minimum.
<p>

<div class="picture"><div class="picture-caption">Node objects and extension objects</div><img src="../pic/extension_general.gif"></div>
<p>

The picture shows how the nodes and extensions are linked
together. Every node has a reference to its extension, and every extension has
a reference to its node. The methods <code class="code">extension</code> and
<code class="code">node</code> follow these references; a typical phrase is 
<p>

<pre></pre><code class="code">&nbsp;self&nbsp;<span class="keywordsign">#</span>&nbsp;node&nbsp;<span class="keywordsign">#</span>&nbsp;attribute&nbsp;<span class="string">"xy"</span>&nbsp;</code><pre></pre>
<p>

to get the value of an attribute from a method defined in the extension object;
or 
<p>

<pre></pre><code class="code">self&nbsp;<span class="keywordsign">#</span>&nbsp;node&nbsp;<span class="keywordsign">#</span>&nbsp;iter<br>
&nbsp;&nbsp;(<span class="keyword">fun</span>&nbsp;n&nbsp;<span class="keywordsign">-&gt;</span>&nbsp;n&nbsp;<span class="keywordsign">#</span>&nbsp;extension&nbsp;<span class="keywordsign">#</span>&nbsp;my_method&nbsp;...)<br>
</code><pre></pre>
<p>

to iterate over the subnodes and to call <code class="code">my_method</code> of the
corresponding extension objects.
<p>

Note that extension objects do not have references to subnodes
(or "subextensions") themselves; in order to get one of the children of an
extension you must first go to the node object, then get the child node, and
finally reach the extension that is logically the child of the extension you
started with.
<p>

In other programming languages, it is possible to extend the node
objects directly. Ocaml's subtyping rules make this practically
impossible. The type of the extension object appears as type parameter
in the class type of the nodes. Note that this means that the type
of the extension objects has to be the same for all nodes in a tree.
It is not possible to e.g. use a different type for elements than for
data nodes.
<p>

<a name="defext"></a>
<h2>How to define an extension class</h2>
<p>

At minimum, you must define the methods <code class="code">clone</code>, <code class="code">node</code>, and
<code class="code">set_node</code> such that your class is compatible with the type
<a href="Pxp_document.extension.html"><code class="code"><span class="constructor">Pxp_document</span>.extension</code></a>. The method <code class="code">set_node</code> is called during the
initialization of the node, or after a node has been cloned; the node
object invokes <code class="code">set_node</code> on the extension object to tell it that this
node is now the object the extension is linked to. The extension must
return the node object passed as argument of <code class="code">set_node</code> when the
<code class="code">node</code> method is called.
<p>

The <code class="code">clone</code> method must return a copy of the extension object; at
least the object itself must be duplicated, but if required, the copy
should deeply duplicate all objects and values that are referred by
the extension, too. Whether this is required, depends on the
application; <code class="code">clone</code> is invoked by the node object when one of its
cloning methods is called.
<p>

A good starting point for an extension class:
<p>

<pre></pre><code class="code"><span class="keyword">class</span>&nbsp;custom_extension&nbsp;=<br>
&nbsp;&nbsp;<span class="keyword">object</span>&nbsp;(self)<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">val</span>&nbsp;<span class="keyword">mutable</span>&nbsp;node&nbsp;=&nbsp;(<span class="constructor">None</span>&nbsp;:&nbsp;custom_extension&nbsp;node&nbsp;option)<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;clone&nbsp;=&nbsp;{&lt;&nbsp;&gt;}&nbsp;<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;node&nbsp;=<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">match</span>&nbsp;node&nbsp;<span class="keyword">with</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="constructor">None</span>&nbsp;<span class="keywordsign">-&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">assert</span>&nbsp;<span class="keyword">false</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keywordsign">|</span>&nbsp;<span class="constructor">Some</span>&nbsp;n&nbsp;<span class="keywordsign">-&gt;</span>&nbsp;n<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;set_node&nbsp;n&nbsp;=<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node&nbsp;&lt;-&nbsp;<span class="constructor">Some</span>&nbsp;n<br>
<br>
&nbsp;&nbsp;<span class="keyword">end</span><br>
</code><pre></pre>
<p>

This class is compatible with <a href="Pxp_document.extension.html"><code class="code"><span class="constructor">Pxp_document</span>.extension</code></a>. The purpose
of defining such a class is, of course, adding further methods; and
you can do it without restriction.
<p>

Often, you want more than only a single extension class. In this case,
it is strictly required that all your classes (that will be used in
the same tree) have the same type of extensions (with respect to the
interface; i.e. it does not matter if your classes differ in the
defined private methods and instance variables, but public methods
count). It is simple to implement:
<p>

<pre></pre><code class="code"><span class="keyword">class</span>&nbsp;custom_extension&nbsp;=<br>
&nbsp;&nbsp;<span class="keyword">object</span>&nbsp;(self)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">val</span>&nbsp;<span class="keyword">mutable</span>&nbsp;node&nbsp;=&nbsp;(<span class="constructor">None</span>&nbsp;:&nbsp;custom_extension&nbsp;node&nbsp;option)<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;clone&nbsp;=&nbsp;...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;see&nbsp;above&nbsp;*)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;node&nbsp;=&nbsp;...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;see&nbsp;above&nbsp;*)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;set_node&nbsp;n&nbsp;=&nbsp;...&nbsp;<span class="comment">(*&nbsp;see&nbsp;above&nbsp;*)</span><br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;<span class="keyword">virtual</span>&nbsp;my_method1&nbsp;:&nbsp;...<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;<span class="keyword">virtual</span>&nbsp;my_method2&nbsp;:&nbsp;...<br>
&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;<span class="comment">(*&nbsp;etc.&nbsp;*)</span><br>
&nbsp;&nbsp;<span class="keyword">end</span><br>
<br>
<span class="keyword">class</span>&nbsp;custom_extension_kind_A&nbsp;=<br>
&nbsp;&nbsp;<span class="keyword">object</span>&nbsp;(self)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">inherit</span>&nbsp;custom_extension<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;my_method1&nbsp;=&nbsp;...<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;my_method2&nbsp;=&nbsp;...<br>
&nbsp;&nbsp;<span class="keyword">end</span><br>
<br>
<span class="keyword">class</span>&nbsp;custom_extension_kind_B&nbsp;=<br>
&nbsp;&nbsp;<span class="keyword">object</span>&nbsp;(self)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">inherit</span>&nbsp;custom_extension<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;my_method1&nbsp;=&nbsp;...<br>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">method</span>&nbsp;my_method2&nbsp;=&nbsp;...<br>
&nbsp;&nbsp;<span class="keyword">end</span><br>
</code><pre></pre>
<p>

If a class does not need a method (e.g. because it does not make
sense, or it would violate some important condition), it is possible
to define the method and to always raise an exception when the method
is invoked (e.g. <code class="code"><span class="keyword">assert</span> <span class="keyword">false</span></code>).
<p>

<a name="bindext"></a>
<h2>How to bind extension classes to element types</h2>
<p>

Once you have defined your extension classes, you can bind them to
element types. The simplest case is that you have only one class and
that this class is always to be used. The parsing functions in the
module <a href="Pxp_tree_parser.html"><code class="code"><span class="constructor">Pxp_tree_parser</span></code></a> take a <code class="code">spec</code> argument for the document
model specification which can be customized (of type
<a href="Pxp_document.html#TYPEspec"><code class="code"><span class="constructor">Pxp_document</span>.spec</code></a>). If your single class has the name <code class="code">c</code>, this
argument should be
<p>

<pre></pre><code class="code"><span class="keyword">let</span>&nbsp;spec&nbsp;=<br>
&nbsp;&nbsp;<span class="constructor">Pxp_document</span>.make_spec_from_alist<br>
&nbsp;&nbsp;&nbsp;&nbsp;~data_exemplar:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="keyword">new</span>&nbsp;<span class="constructor">Pxp_document</span>.data_impl&nbsp;c)<br>
&nbsp;&nbsp;&nbsp;&nbsp;~default_element_exemplar:&nbsp;(<span class="keyword">new</span>&nbsp;<span class="constructor">Pxp_document</span>.element_impl&nbsp;c)<br>
&nbsp;&nbsp;&nbsp;&nbsp;~element_alist:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[]<br>
&nbsp;&nbsp;&nbsp;&nbsp;()<br>
</code><pre></pre>
<p>

This means that data nodes will be created from the exemplar passed by
<code class="code">~data_exemplar</code> and that all element nodes will be made from the
exemplar specified by <code class="code">~default_element_exemplar</code>. In
<code class="code">~element_alist</code>, you can pass that different exemplars are to be used
for different element types; but this is an optional feature. If you
do not need it, pass the empty list.
<p>

Remember that an exemplar is a (node, extension) pair that serves as
pattern when new nodes (and the corresponding extension objects) are
added to the document tree. In this case, the exemplar contains <code class="code">c</code> as
extension, and when nodes are created, the exemplar is cloned, and
cloning makes also a copy of <code class="code">c</code> such that all nodes of the document
tree will have a copy of <code class="code">c</code> as extension.
<p>

The <code class="code">~element_alist</code> argument can bind specific element types to
specific exemplars; as exemplars may be instances of different classes
it is effectively possible to bind element types to classes. For
example, if the element type "p" is implemented by class <code class="code">c_p</code>, and
"q" is realized by <code class="code">c_q</code>, you can pass the following value:
<p>

<pre></pre><code class="code"><span class="keyword">let</span>&nbsp;spec&nbsp;=<br>
&nbsp;&nbsp;<span class="constructor">Pxp_document</span>.make_spec_from_alist<br>
&nbsp;&nbsp;&nbsp;&nbsp;~data_exemplar:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="constructor">Pxp_document</span>.<span class="keyword">new</span>&nbsp;data_impl&nbsp;c)<br>
&nbsp;&nbsp;&nbsp;&nbsp;~default_element_exemplar:&nbsp;(<span class="constructor">Pxp_document</span>.<span class="keyword">new</span>&nbsp;element_impl&nbsp;c)<br>
&nbsp;&nbsp;&nbsp;&nbsp;~element_alist:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[&nbsp;<span class="string">"p"</span>,&nbsp;<span class="keyword">new</span>&nbsp;<span class="constructor">Pxp_document</span>.element_impl&nbsp;c_p;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="string">"q"</span>,&nbsp;<span class="keyword">new</span>&nbsp;<span class="constructor">Pxp_document</span>.element_impl&nbsp;c_q;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]<br>
&nbsp;&nbsp;&nbsp;&nbsp;()<br>
</code><pre></pre>
<p>

The extension object <code class="code">c</code> is still used for all data nodes and
for all other element types.
<p>

<a name="example"></a>
<h2>An example</h2>
<p>

A complete example using extension objects is the <code class="code">readme</code>
processor. The full source code is included in the PXP source tarball.
A commented version is available here: <a href="Example_readme.html"><code class="code"><span class="constructor">Example_readme</span></code></a>.
<p>

<br>
</body></html>