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