1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2 "http://www.w3.org/TR/html4/loose.dtd">
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">
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>
15 <h1 align="center">Writing extensions for XSLT C library for Gnome</h1>
20 href="http://xmlsoft.org/XSLT/extensions.html">http://xmlsoft.org/XSLT/extensions.html</a></p>
22 <p>Libxslt home page: <a
23 href="http://xmlsoft.org/XSLT/">http://xmlsoft.org/XSLT/</a></p>
25 <p>mailing-list archives: <a
26 href="http://mail.gnome.org/archives/xslt/">http://mail.gnome.org/archives/xslt/</a></p>
28 <p>Version: $Revision$</p>
30 <h2>Table of content</h2>
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>
47 <h2><a name="Introducti">Introduction</a></h2>
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>
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>
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>
61 <h2><a name="Basics">Basics</a></h2>
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>
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>
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>
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>
80 <h2><a name="Keep">Extension modules</a></h2>
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>
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>
94 <p>And extension module is defined by 3 objects:</p>
96 <li>the namespace name associated</li>
97 <li>an initialization function</li>
98 <li>a shutdown function</li>
101 <h2><a name="Registerin">Registering a module</a></h2>
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
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>
114 <p>The associated header is read by:</p>
115 <pre>#include<libxslt/extensions.h></pre>
117 <p>which also defines the type for the initialization and shutdown
120 <h2><a name="libxml">Loading a module</a></h2>
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>
126 <p>The xsltExtInitFunction type defines the interface for an initialization
129 * xsltExtInitFunction:
130 * @ctxt: an XSLT transformation context
131 * @URI: the namespace URI for the extension
133 * A function called at initialization time of an XSLT
136 * Returns a pointer to the module specific data for this
139 typedef void *(*xsltExtInitFunction)(xsltTransformContextPtr ctxt,
140 const xmlChar *URI);</pre>
142 <p>There is 3 things to notice:</p>
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
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
158 <p>What this function is expected to do is:</p>
160 <li>prepare the context for this module (like opening the database
162 <li>registers the extensions specific to this module</li>
165 <h2><a name="Registerin1">Registering an extension function</a></h2>
167 <p>There is a single call to do this registration:</p>
168 <pre>int xsltRegisterExtFunction(xsltTransformContextPtr ctxt,
171 xmlXPathEvalFunc function);</pre>
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
179 <h2><a name="Implementi">Implementing an extension function</a></h2>
181 <p>The implementation of the function must have the signature of a libxml
185 * @ctxt: an XPath parser context
186 * @nargs: the number of arguments passed to the function
188 * an XPath evaluation function, the parameters are on the
189 * XPath context stack
192 typedef void (*xmlXPathEvalFunc)(xmlXPathParserContextPtr ctxt,
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>
199 <li>The function xsltXPathGetTransformContext provide this lookup facility:
200 <pre>xsltTransformContextPtr
201 xsltXPathGetTransformContext
202 (xmlXPathParserContextPtr ctxt);</pre>
204 <li>The <code>xmlXPathContextPtr</code> associated to an
205 <code>xsltTransformContext</code> is stored in the <code>xpathCtxt</code>
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 <libxml/xpath.h>
214 #include <libxml/xpathInternals.h>
216 xmlXPathObjectPtr obj = valuePop(ctxt); </pre>
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->type != XPATH_STRING) {
225 valuePush(ctxt, obj);
226 xmlXPathStringFunction(ctxt, 1);
227 obj = valuePop(ctxt);
230 <p>Most common XPath function are availbale directly at the C level and are
231 exported either in <code><libxml/xpath.h></code> or in
232 <code><libxml/xpathInternals.h></code>.</p>
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>
240 <p>again the URI to be provided is the one used which was used when
241 registering the module.</p>
243 <p>Once the function finishes, don't forget to:</p>
245 <li>push the return value on the stack using <code>valuePush(ctxt,
247 <li>deallocate the parameters passed to the function using
248 <code>xmlXPathFreeObject(obj)</code></li>
251 <h2><a name="Examples">Examples for extension functions</a></h2>
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>
258 * xsltExtFunctionTest:
259 * @ctxt: the XPath Parser context
260 * @nargs: the number of arguments
262 * function libxslt:test() for testing the extensions support.
265 xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, int nargs)
267 xsltTransformContextPtr tctxt;
270 tctxt = xsltXPathGetTransformContext(ctxt);
272 xsltGenericError(xsltGenericErrorContext,
273 "xsltExtFunctionTest: failed to get the transformation context\n");
276 data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
278 xsltGenericError(xsltGenericErrorContext,
279 "xsltExtFunctionTest: failed to get module data\n");
282 #ifdef WITH_XSLT_DEBUG_FUNCTION
283 xsltGenericDebug(xsltGenericDebugContext,
284 "libxslt:test() called with %d args\n", nargs);
288 <h2><a name="Registerin2">Registering an extension function</a></h2>
290 <p>There is a single call to do this registration:</p>
291 <pre>int xsltRegisterExtElement(xsltTransformContextPtr ctxt,
294 xsltTransformFunction function);</pre>
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
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>
305 <h2><a name="Implementi1">Implementing an extension element</a></h2>
307 <p>The implementation of the element must have the signature of an XSLT
308 transformation function:</p>
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
316 * signature of the function associated to elements part of the
317 * stylesheet language like xsl:if or xsl:apply-templates.
319 typedef void (*xsltTransformFunction)
320 (xsltTransformContextPtr ctxt,
323 xsltStylePreCompPtr comp);</pre>
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->_private</code>).</p>
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>
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->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"><libxml/tree.h></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>
350 <h2><a name="Example">Example for extension elements</a></h2>
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>
357 * xsltExtElementTest:
358 * @ctxt: an XSLT processing context
359 * @node: The current node
360 * @inst: the instruction in the stylesheet
361 * @comp: precomputed informations
363 * Process a libxslt:test node
366 xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node,
368 xsltStylePreCompPtr comp)
373 xsltGenericError(xsltGenericErrorContext,
374 "xsltExtElementTest: no transformation context\n");
378 xsltGenericError(xsltGenericErrorContext,
379 "xsltExtElementTest: no current node\n");
383 xsltGenericError(xsltGenericErrorContext,
384 "xsltExtElementTest: no instruction\n");
387 if (ctxt->insert == NULL) {
388 xsltGenericError(xsltGenericErrorContext,
389 "xsltExtElementTest: no insertion point\n");
393 xmlNewComment((const xmlChar *)
394 "libxslt:test element test worked");
395 xmlAddChild(ctxt->insert, comment);
398 <h2><a name="shutdown">The shutdown of a module</a></h2>
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>
404 * xsltExtShutdownFunction:
405 * @ctxt: an XSLT transformation context
406 * @URI: the namespace URI for the extension
407 * @data: the data associated to this module
409 * A function called at shutdown time of an XSLT extension module
411 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 close
418 the connection to the database to keep the same example.</p>
420 <h2><a name="Future">Future work</a></h2>
422 <p>Well some of the pieces missing:</p>
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.
436 <p><a href="mailto:daniel@veillard.com">Daniel Veillard</a></p>