source: trunk/third/libxslt/doc/extensions.html @ 19102

Revision 19102, 21.5 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19101, which included commits to RCS files with non-trunk default branches.
Line 
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
2<html>
3<head>
4<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
5<style type="text/css"><!--
6TD {font-family: Verdana,Arial,Helvetica}
7BODY {font-family: Verdana,Arial,Helvetica; margin-top: 2em; margin-left: 0em; margin-right: 0em}
8H1 {font-family: Verdana,Arial,Helvetica}
9H2 {font-family: Verdana,Arial,Helvetica}
10H3 {font-family: Verdana,Arial,Helvetica}
11A:link, A:visited, A:active { text-decoration: underline }
12--></style>
13<title>Writing extensions</title>
14</head>
15<body bgcolor="#8b7765" text="#000000" link="#000000" vlink="#000000">
16<table border="0" width="100%" cellpadding="5" cellspacing="0" align="center"><tr>
17<td width="100">
18<a href="http://www.gnome.org/"><img src="gnome2.png" alt="Gnome2 Logo"></a><a href="http://www.redhat.com"><img src="redhat.gif" alt="Red Hat Logo"></a><div align="left"><a href="http://xmlsoft.org/XSLT/"><img src="Libxslt-Logo-180x168.gif" alt="Made with Libxslt Logo"></a></div>
19</td>
20<td><table border="0" width="90%" cellpadding="2" cellspacing="0" align="center" bgcolor="#000000"><tr><td><table width="100%" border="0" cellspacing="1" cellpadding="3" bgcolor="#fffacd"><tr><td align="center">
21<h1>The XSLT C library for Gnome</h1>
22<h2>Writing extensions</h2>
23</td></tr></table></td></tr></table></td>
24</tr></table>
25<table border="0" cellpadding="4" cellspacing="0" width="100%" align="center"><tr><td bgcolor="#8b7765"><table border="0" cellspacing="0" cellpadding="2" width="100%"><tr>
26<td valign="top" width="200" bgcolor="#8b7765"><table border="0" cellspacing="0" cellpadding="1" width="100%" bgcolor="#000000"><tr><td>
27<table width="100%" border="0" cellspacing="1" cellpadding="3">
28<tr><td colspan="1" bgcolor="#eecfa1" align="center"><center><b>Main Menu</b></center></td></tr>
29<tr><td bgcolor="#fffacd">
30<form action="search.php" enctype="application/x-www-form-urlencoded" method="GET">
31<input name="query" type="TEXT" size="20" value=""><input name="submit" type="submit" value="Search ...">
32</form>
33<ul>
34<li><a href="index.html">Home</a></li>
35<li><a href="intro.html">Introduction</a></li>
36<li><a href="docs.html">Documentation</a></li>
37<li><a href="bugs.html">Reporting bugs and getting help</a></li>
38<li><a href="help.html">How to help</a></li>
39<li><a href="downloads.html">Downloads</a></li>
40<li><a href="FAQ.html">FAQ</a></li>
41<li><a href="news.html">News</a></li>
42<li><a href="xsltproc2.html">The xsltproc tool</a></li>
43<li><a href="docbook.html">DocBook</a></li>
44<li><a href="API.html">The programming API</a></li>
45<li><a href="python.html">Python and bindings</a></li>
46<li><a href="internals.html">Library internals</a></li>
47<li><a href="extensions.html">Writing extensions</a></li>
48<li><a href="contribs.html">Contributions</a></li>
49<li>
50<a href="xslt.html">flat page</a>, <a href="site.xsl">stylesheet</a>
51</li>
52</ul>
53</td></tr>
54</table>
55<table width="100%" border="0" cellspacing="1" cellpadding="3">
56<tr><td colspan="1" bgcolor="#eecfa1" align="center"><center><b>Related links</b></center></td></tr>
57<tr><td bgcolor="#fffacd"><ul>
58<li><a href="tutorial/libxslttutorial.html">Tutorial</a></li>
59<li><a href="xsltproc.html">Man page for xsltproc</a></li>
60<li><a href="http://mail.gnome.org/archives/xslt/">Mail archive</a></li>
61<li><a href="http://xmlsoft.org/">XML libxml</a></li>
62<li><a href="http://phd.cs.unibo.it/gdome2/">DOM gdome2</a></li>
63<li><a href="ftp://xmlsoft.org/">FTP</a></li>
64<li><a href="http://www.zlatkovic.com/projects/libxml/">Windows binaries</a></li>
65<li><a href="http://garypennington.net/libxml2/">Solaris binaries</a></li>
66<li><a href="http://www.zveno.com/open_source/libxml2xslt.html">MacOsX binaries</a></li>
67<li><a href="http://sourceforge.net/projects/libxml2-pas/">Pascal bindings</a></li>
68<li><a href="http://bugzilla.gnome.org/buglist.cgi?product=libxslt">Bug Tracker</a></li>
69<li><a href="http://xsldbg.sourceforge.net/">Xsldbg Debugger</a></li>
70<li><a href="http://www.mod-xslt.com/mod-xslt/">Apache module</a></li>
71</ul></td></tr>
72</table>
73<table width="100%" border="0" cellspacing="1" cellpadding="3">
74<tr><td colspan="1" bgcolor="#eecfa1" align="center"><center><b>API Indexes</b></center></td></tr>
75<tr><td bgcolor="#fffacd"><ul>
76<li><a href="APIchunk0.html">Alphabetic</a></li>
77<li><a href="APIconstructors.html">Constructors</a></li>
78<li><a href="APIfunctions.html">Functions/Types</a></li>
79<li><a href="APIfiles.html">Modules</a></li>
80<li><a href="APIsymbols.html">Symbols</a></li>
81</ul></td></tr>
82</table>
83</td></tr></table></td>
84<td valign="top" bgcolor="#8b7765"><table border="0" cellspacing="0" cellpadding="1" width="100%"><tr><td><table border="0" cellspacing="0" cellpadding="1" width="100%" bgcolor="#000000"><tr><td><table border="0" cellpadding="3" cellspacing="1" width="100%"><tr><td bgcolor="#fffacd">
85<h3>Table  of content</h3>
86<ul>
87<li><a href="extensions.html#Introducti">Introduction</a></li>
88  <li><a href="extensions.html#Basics">Basics</a></li>
89  <li><a href="extensions.html#Keep">Extension modules</a></li>
90  <li><a href="extensions.html#Registerin">Registering a module</a></li>
91  <li><a href="extensions.html#module">Loading a module</a></li>
92  <li><a href="extensions.html#Registerin1">Registering an extension
93    function</a></li>
94  <li><a href="extensions.html#Implementi">Implementing an extension
95    function</a></li>
96  <li><a href="extensions.html#Examples">Examples for extension
97  functions</a></li>
98  <li><a href="extensions.html#Registerin2">Registering an extension
99    element</a></li>
100  <li><a href="extensions.html#Implementi1">Implementing an extension
101    element</a></li>
102  <li><a href="extensions.html#Example">Example for extension
103  elements</a></li>
104  <li><a href="extensions.html#shutdown">The shutdown of a module</a></li>
105  <li><a href="extensions.html#Future">Future work</a></li>
106</ul>
107<h3><a name="Introducti1">Introduction</a></h3>
108<p>This document describes the work needed to write extensions to the
109standard XSLT library for use with <a href="http://xmlsoft.org/XSLT/">libxslt</a>, the <a href="http://www.w3.org/TR/xslt">XSLT</a> C library developed for the <a href="http://www.gnome.org/">Gnome</a> project.</p>
110<p>Before starting reading this document it is highly recommended to get
111familiar with <a href="internals.html">the libxslt internals</a>.</p>
112<p>Note: this documentation is by definition incomplete and I am not good at
113spelling, grammar, so patches and suggestions are <a href="mailto:veillard@redhat.com">really welcome</a>.</p>
114<h3><a name="Basics">Basics</a></h3>
115<p>The <a href="http://www.w3.org/TR/xslt">XSLT specification</a> provides
116two <a href="http://www.w3.org/TR/xslt">ways to extend an XSLT engine</a>:</p>
117<ul>
118<li>providing <a href="http://www.w3.org/TR/xslt">new extension
119    functions</a> which can be called from XPath expressions</li>
120  <li>providing <a href="http://www.w3.org/TR/xslt">new extension
121    elements</a> which can be inserted in stylesheets</li>
122</ul>
123<p>In both cases the extensions need to be associated to a new namespace,
124i.e. an URI used as the name for the extension's namespace (there is no need
125to have a resource there for this to work).</p>
126<p>libxslt provides a few extensions itself, either in libxslt namespace
127&quot;http://xmlsoft.org/XSLT/&quot; or in other namespace for well known extensions
128provided by other XSLT processors like Saxon, Xalan or XT.</p>
129<h3><a name="Keep">Extension modules</a></h3>
130<p>Since extensions are bound to a namespace name, usually sets of extensions
131coming from a given source are using the same namespace name defining in
132practice a group of extensions providing elements, functions or both. From
133libxslt point of view those are considered as an &quot;extension module&quot;, and most
134of the APIs work at a module point of view.</p>
135<p>Registration of new functions or elements are bound to the activation of
136the module, this is currently done by declaring the namespace as an extension
137by using the attribute  <code>extension-element-prefixes</code> on the
138<code><a href="http://www.w3.org/TR/xslt">xsl:stylesheet</a></code>
139element.</p>
140<p>And extension module is defined by 3 objects:</p>
141<ul>
142<li>the namespace name associated</li>
143  <li>an initialization function</li>
144  <li>a shutdown function</li>
145</ul>
146<h3><a name="Registerin">Registering a module</a></h3>
147<p>Currently a libxslt module has to be compiled within the application using
148libxslt, there is no code to load dynamically shared libraries associated to
149namespace (this may be added but is likely to become a portability
150nightmare).</p>
151<p>So the current way to register a module is to link the code implementing
152it with the application and to call a registration function:</p>
153<pre>int xsltRegisterExtModule(const xmlChar *URI,
154                          xsltExtInitFunction initFunc,
155                          xsltExtShutdownFunction shutdownFunc);</pre>
156<p>The associated header is read by:</p>
157<pre>#include&lt;libxslt/extensions.h&gt;</pre>
158<p>which also defines the type for the initialization and shutdown
159functions</p>
160<h3><a name="module">Loading a module</a></h3>
161<p>Once the module URI has been registered and if the XSLT processor detects
162that a given stylesheet needs the functionalities of an extended module, this
163one is initialized.</p>
164<p>The xsltExtInitFunction type defines the interface for an initialization
165function:</p>
166<pre>/**
167 * xsltExtInitFunction:
168 * @ctxt:  an XSLT transformation context
169 * @URI:  the namespace URI for the extension
170 *
171 * A function called at initialization time of an XSLT
172 * extension module
173 *
174 * Returns a pointer to the module specific data for this
175 * transformation
176 */
177typedef void *(*xsltExtInitFunction)(xsltTransformContextPtr ctxt,
178                                     const xmlChar *URI);</pre>
179<p>There are 3 things to notice:</p>
180<ul>
181<li>the function gets passed the namespace name URI as an argument, this
182    allow a single function to provide the initialization for multiple
183    logical modules</li>
184  <li>it also gets passed a transformation context, the initialization is
185    done at run time before any processing occurs on the stylesheet but it
186    will be invoked separately each time for each transformation</li>
187  <li>it returns a pointer, this can be used to store module specific
188    informations which can be retrieved later when a function or an element
189    from the extension are used, an obvious example is a connection to a
190    database which should be kept and reused along the transformation. NULL
191    is a perfectly valid return, there is no way to indicate a failure at
192    this level</li>
193</ul>
194<p>What this function is expected to do is:</p>
195<ul>
196<li>prepare the context for this module (like opening the database
197    connection)</li>
198  <li>register the extensions specific to this module</li>
199</ul>
200<h3><a name="Registerin1">Registering an extension function</a></h3>
201<p>There is a single call to do this registration:</p>
202<pre>int xsltRegisterExtFunction(xsltTransformContextPtr ctxt,
203                            const xmlChar *name,
204                            const xmlChar *URI,
205                            xmlXPathEvalFunc function);</pre>
206<p>The registration is bound to a single transformation instance referred by
207ctxt, name is the UTF8 encoded name for the NCName of the function, and URI
208is the namespace name for the extension (no checking is done, a module could
209register functions or elements from a different namespace, but it is not
210recommended).</p>
211<h3><a name="Implementi">Implementing an extension function</a></h3>
212<p>The implementation of the function must have the signature of a libxml
213XPath function:</p>
214<pre>/**
215 * xmlXPathEvalFunc:
216 * @ctxt: an XPath parser context
217 * @nargs: the number of arguments passed to the function
218 *
219 * an XPath evaluation function, the parameters are on the
220 * XPath context stack
221 */
222
223typedef void (*xmlXPathEvalFunc)(xmlXPathParserContextPtr ctxt,
224                                 int nargs);</pre>
225<p>The context passed to an XPath function is not an XSLT context but an <a href="internals.html#XPath1">XPath context</a>. However it is possible to
226find one from the other:</p>
227<ul>
228<li>The function xsltXPathGetTransformContext provide this lookup facility:
229    <pre>xsltTransformContextPtr
230         xsltXPathGetTransformContext
231                          (xmlXPathParserContextPtr ctxt);</pre>
232  </li>
233  <li>The <code>xmlXPathContextPtr</code> associated to an
234    <code>xsltTransformContext</code> is stored in the <code>xpathCtxt</code>
235    field.</li>
236</ul>
237<p>The first thing an extension function may want to do is to check the
238arguments passed on the stack, the <code>nargs</code> will precise how many
239of them were provided on the XPath expression. The macros valuePop will
240extract them from the XPath stack:</p>
241<pre>#include &lt;libxml/xpath.h&gt;
242#include &lt;libxml/xpathInternals.h&gt;
243
244xmlXPathObjectPtr obj = valuePop(ctxt); </pre>
245<p>Note that <code>ctxt</code> is the XPath context not the XSLT one. It is
246then possible to examine the content of the value. Check <a href="internals.html#Descriptio">the description of XPath objects</a> if
247necessary. The following is a common sequcnce checking whether the argument
248passed is a string and converting it using the built-in XPath
249<code>string()</code> function if this is not the case:</p>
250<pre>if (obj-&gt;type != XPATH_STRING) {
251    valuePush(ctxt, obj);
252    xmlXPathStringFunction(ctxt, 1);
253    obj = valuePop(ctxt);
254}</pre>
255<p>Most common XPath functions are available directly at the C level and are
256exported either in <code>&lt;libxml/xpath.h&gt;</code> or in
257<code>&lt;libxml/xpathInternals.h&gt;</code>.</p>
258<p>The extension function may also need to retrieve the data associated to
259this module instance (the database connection in the previous example) this
260can be done using the xsltGetExtData:</p>
261<pre>void * xsltGetExtData(xsltTransformContextPtr ctxt,
262                      const xmlChar *URI);</pre>
263<p>again the URI to be provided is the one used which was used when
264registering the module.</p>
265<p>Once the function finishes, don't forget to:</p>
266<ul>
267<li>push the return value on the stack using <code>valuePush(ctxt,
268    obj)</code>
269</li>
270  <li>deallocate the parameters passed to the function using
271    <code>xmlXPathFreeObject(obj)</code>
272</li>
273</ul>
274<h3><a name="Examples">Examples for extension functions</a></h3>
275<p>The module libxslt/functions.c containsthe sources of the XSLT built-in
276functions, including document(), key(), generate-id(), etc. as well as a full
277example module at the end. Here is the test function implementation for the
278libxslt:test function:</p>
279<pre>/**
280 * xsltExtFunctionTest:
281 * @ctxt:  the XPath Parser context
282 * @nargs:  the number of arguments
283 *
284 * function libxslt:test() for testing the extensions support.
285 */
286static void
287xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, int nargs)
288{
289    xsltTransformContextPtr tctxt;
290    void *data;
291
292    tctxt = xsltXPathGetTransformContext(ctxt);
293    if (tctxt == NULL) {
294        xsltGenericError(xsltGenericErrorContext,
295            &quot;xsltExtFunctionTest: failed to get the transformation context\n&quot;);
296        return;
297    }
298    data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
299    if (data == NULL) {
300        xsltGenericError(xsltGenericErrorContext,
301            &quot;xsltExtFunctionTest: failed to get module data\n&quot;);
302        return;
303    }
304#ifdef WITH_XSLT_DEBUG_FUNCTION
305    xsltGenericDebug(xsltGenericDebugContext,
306                     &quot;libxslt:test() called with %d args\n&quot;, nargs);
307#endif
308}</pre>
309<h3><a name="Registerin2">Registering an extension element</a></h3>
310<p>There is a single call to do this registration:</p>
311<pre>int xsltRegisterExtElement(xsltTransformContextPtr ctxt,
312                           const xmlChar *name,
313                           const xmlChar *URI,
314                           xsltTransformFunction function);</pre>
315<p>It is similar to the mechanism used to register an extension function,
316except that the signature of an extension element implementation is
317different.</p>
318<p>The registration is bound to a single transformation instance referred by
319ctxt, name is the UTF8 encoded name for the NCName of the element, and URI is
320the namespace name for the extension (no checking is done, a module could
321register elements for a different namespace, but it is not recommended).</p>
322<h3><a name="Implementi1">Implementing an extension element</a></h3>
323<p>The implementation of the element must have the signature of an XSLT
324transformation function:</p>
325<pre>/**
326 * xsltTransformFunction:
327 * @ctxt: the XSLT transformation context
328 * @node: the input node
329 * @inst: the stylesheet node
330 * @comp: the compiled information from the stylesheet
331 *
332 * signature of the function associated to elements part of the
333 * stylesheet language like xsl:if or xsl:apply-templates.
334 */
335typedef void (*xsltTransformFunction)
336                          (xsltTransformContextPtr ctxt,
337                           xmlNodePtr node,
338                           xmlNodePtr inst,
339                           xsltStylePreCompPtr comp);</pre>
340<p>The first argument is the XSLT transformation context. The second and
341third arguments are xmlNodePtr i.e. internal memory <a href="internals.html#libxml">representation of  XML nodes</a>. They are
342respectively <code>node</code> from the the input document being transformed
343by the stylesheet and <code>inst</code> the extension element in the
344stylesheet. The last argument is <code>comp</code> a pointer to a precompiled
345representation of <code>inst</code> but usually for extension function this
346value is <code>NULL</code> by default (it could be added and associated to
347the instruction in <code>inst-&gt;_private</code>).</p>
348<p>The same functions are available from a function implementing an extension
349element as in an extension function, including
350<code>xsltGetExtData()</code>.</p>
351<p>The goal of extension element being usually to enrich the generated
352output, it is expected that they will grow the currently generated output
353tree, this can be done by grabbing ctxt-&gt;insert which is the current
354libxml node being generated (Note this can also be the intermediate value
355tree being built for example to initialize a variable, the processing should
356be similar). The functions for libxml tree manipulation from <a href="http://xmlsoft.org/html/libxml-tree.html">&lt;libxml/tree.h&gt;</a> can
357be employed to extend or modify the tree, but it is required to preserve the
358insertion node and its ancestors since there is existing pointers to those
359elements still in use in the XSLT template execution stack.</p>
360<h3><a name="Example">Example for extension elements</a></h3>
361<p>The module libxslt/transform.c containsthe sources of the XSLT built-in
362elements, including xsl:element, xsl:attribute, xsl:if, etc. There is a small
363but full example in functions.c providing the implementation for the
364libxslt:test element, it will output a comment in the result tree:</p>
365<pre>/**
366 * xsltExtElementTest:
367 * @ctxt:  an XSLT processing context
368 * @node:  The current node
369 * @inst:  the instruction in the stylesheet
370 * @comp:  precomputed informations
371 *
372 * Process a libxslt:test node
373 */
374static void
375xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node,
376                   xmlNodePtr inst,
377                   xsltStylePreCompPtr comp)
378{
379    xmlNodePtr comment;
380
381    if (ctxt == NULL) {
382        xsltGenericError(xsltGenericErrorContext,
383                         &quot;xsltExtElementTest: no transformation context\n&quot;);
384        return;
385    }
386    if (node == NULL) {
387        xsltGenericError(xsltGenericErrorContext,
388                         &quot;xsltExtElementTest: no current node\n&quot;);
389        return;
390    }
391    if (inst == NULL) {
392        xsltGenericError(xsltGenericErrorContext,
393                         &quot;xsltExtElementTest: no instruction\n&quot;);
394        return;
395    }
396    if (ctxt-&gt;insert == NULL) {
397        xsltGenericError(xsltGenericErrorContext,
398                         &quot;xsltExtElementTest: no insertion point\n&quot;);
399        return;
400    }
401    comment =
402        xmlNewComment((const xmlChar *)
403                      &quot;libxslt:test element test worked&quot;);
404    xmlAddChild(ctxt-&gt;insert, comment);
405}</pre>
406<h3><a name="shutdown">The shutdown of a module</a></h3>
407<p>When the XSLT processor ends a transformation, the shutdown function (if
408it exists) of all the modules initialized are called.The
409xsltExtShutdownFunction type defines the interface for a shutdown
410function:</p>
411<pre>/**
412 * xsltExtShutdownFunction:
413 * @ctxt:  an XSLT transformation context
414 * @URI:  the namespace URI for the extension
415 * @data:  the data associated to this module
416 *
417 * A function called at shutdown time of an XSLT extension module
418 */
419typedef void (*xsltExtShutdownFunction) (xsltTransformContextPtr ctxt,
420                                         const xmlChar *URI,
421                                         void *data);</pre>
422<p>this is really similar to a module initialization function except a third
423argument is passed, it's the value that was returned by the initialization
424function. This allow to deallocate resources from the module for example
425close the connection to the database to keep the same example.</p>
426<h3><a name="Future">Future work</a></h3>
427<p>Well some of the pieces missing:</p>
428<ul>
429<li>a way to load shared libraries to instanciate new modules</li>
430  <li>a better detection of extension function usage and their registration
431    without having to use the extension prefix which ought to be reserved to
432    element extensions.</li>
433  <li>more examples</li>
434  <li>implementations of the <a href="http://www.exslt.org/">EXSLT</a> common
435    extension libraries, Thomas Broyer nearly finished implementing them.</li>
436</ul>
437<p></p>
438<p><a href="bugs.html">Daniel Veillard</a></p>
439</td></tr></table></td></tr></table></td></tr></table></td>
440</tr></table></td></tr></table>
441</body>
442</html>
Note: See TracBrowser for help on using the repository browser.