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