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