enhanced documentation to include exslt; rebuilt docs
[platform/upstream/libxslt.git] / doc / extensions.html
1 <?xml version="1.0" encoding="ISO-8859-1"?>
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /><style type="text/css">
4 TD {font-family: Verdana,Arial,Helvetica}
5 BODY {font-family: Verdana,Arial,Helvetica; margin-top: 2em; margin-left: 0em; margin-right: 0em}
6 H1 {font-family: Verdana,Arial,Helvetica}
7 H2 {font-family: Verdana,Arial,Helvetica}
8 H3 {font-family: Verdana,Arial,Helvetica}
9 A:link, A:visited, A:active { text-decoration: underline }
10 </style><title>Writing extensions</title></head><body bgcolor="#8b7765" text="#000000" link="#000000" vlink="#000000"><table border="0" width="100%" cellpadding="5" cellspacing="0" align="center"><tr><td width="120"><a href="http://swpat.ffii.org/"><img src="epatents.png" alt="Action against software patents" /></a></td><td width="100"><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></td><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"><h1>The XSLT C library for Gnome</h1><h2>Writing extensions</h2></td></tr></table></td></tr></table></td></tr></table><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><td valign="top" width="200" bgcolor="#8b7765"><table border="0" cellspacing="0" cellpadding="1" width="100%" bgcolor="#000000"><tr><td><table width="100%" border="0" cellspacing="1" cellpadding="3"><tr><td colspan="1" bgcolor="#eecfa1" align="center"><center><b>Main Menu</b></center></td></tr><tr><td bgcolor="#fffacd"><form action="search.php" enctype="application/x-www-form-urlencoded" method="get"><input name="query" type="text" size="20" value="" /><input name="submit" type="submit" value="Search ..." /></form><ul><li><a href="index.html">Home</a></li><li><a href="intro.html">Introduction</a></li><li><a href="docs.html">Documentation</a></li><li><a href="bugs.html">Reporting bugs and getting help</a></li><li><a href="help.html">How to help</a></li><li><a href="downloads.html">Downloads</a></li><li><a href="FAQ.html">FAQ</a></li><li><a href="news.html">News</a></li><li><a href="xsltproc2.html">The xsltproc tool</a></li><li><a href="docbook.html">DocBook</a></li><li><a href="API.html">The programming API</a></li><li><a href="python.html">Python and bindings</a></li><li><a href="internals.html">Library internals</a></li><li><a href="extensions.html">Writing extensions</a></li><li><a href="contribs.html">Contributions</a></li><li><a href="EXSLT/index.html" style="font-weight:bold">libexslt</a></li><li><a href="xslt.html">flat page</a>, <a href="site.xsl">stylesheet</a></li><li><a href="html/index.html" style="font-weight:bold">API Menu</a></li></ul></td></tr></table><table width="100%" border="0" cellspacing="1" cellpadding="3"><tr><td colspan="1" bgcolor="#eecfa1" align="center"><center><b>Related links</b></center></td></tr><tr><td bgcolor="#fffacd"><ul><li><a href="tutorial/libxslttutorial.html">Tutorial</a></li><li><a href="xsltproc.html">Man page for xsltproc</a></li><li><a href="http://mail.gnome.org/archives/xslt/">Mail archive</a></li><li><a href="http://xmlsoft.org/">XML libxml</a></li><li><a href="http://phd.cs.unibo.it/gdome2/">DOM gdome2</a></li><li><a href="ftp://xmlsoft.org/">FTP</a></li><li><a href="http://www.zlatkovic.com/projects/libxml/">Windows binaries</a></li><li><a href="http://garypennington.net/libxml2/">Solaris binaries</a></li><li><a href="http://www.zveno.com/open_source/libxml2xslt.html">MacOsX binaries</a></li><li><a href="http://sourceforge.net/projects/libxml2-pas/">Pascal bindings</a></li><li><a href="http://bugzilla.gnome.org/buglist.cgi?product=libxslt">Bug Tracker</a></li><li><a href="http://xsldbg.sourceforge.net/">Xsldbg Debugger</a></li><li><a href="http://www.mod-xslt.com/mod-xslt/">Apache module</a></li></ul></td></tr></table><table width="100%" border="0" cellspacing="1" cellpadding="3"><tr><td colspan="1" bgcolor="#eecfa1" align="center"><center><b>API Indexes</b></center></td></tr><tr><td bgcolor="#fffacd"><ul><li><a href="APIchunk0.html">Alphabetic</a></li><li><a href="APIconstructors.html">Constructors</a></li><li><a href="APIfunctions.html">Functions/Types</a></li><li><a href="APIfiles.html">Modules</a></li><li><a href="APIsymbols.html">Symbols</a></li></ul></td></tr></table></td></tr></table></td><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"><h3>Table  of content</h3><ul><li><a href="extensions.html#Introducti">Introduction</a></li>
11   <li><a href="extensions.html#Basics">Basics</a></li>
12   <li><a href="extensions.html#Keep">Extension modules</a></li>
13   <li><a href="extensions.html#Registerin">Registering a module</a></li>
14   <li><a href="extensions.html#module">Loading a module</a></li>
15   <li><a href="extensions.html#Registerin1">Registering an extension
16     function</a></li>
17   <li><a href="extensions.html#Implementi">Implementing an extension
18     function</a></li>
19   <li><a href="extensions.html#Examples">Examples for extension
20   functions</a></li>
21   <li><a href="extensions.html#Registerin2">Registering an extension
22     element</a></li>
23   <li><a href="extensions.html#Implementi1">Implementing an extension
24     element</a></li>
25   <li><a href="extensions.html#Example">Example for extension
26   elements</a></li>
27   <li><a href="extensions.html#shutdown">The shutdown of a module</a></li>
28   <li><a href="extensions.html#Future">Future work</a></li>
29 </ul><h3><a name="Introducti1" id="Introducti1">Introduction</a></h3><p>This document describes the work needed to write extensions to the
30 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><p>Before starting reading this document it is highly recommended to get
31 familiar with <a href="internals.html">the libxslt internals</a>.</p><p>Note: this documentation is by definition incomplete and I am not good at
32 spelling, grammar, so patches and suggestions are <a href="mailto:veillard@redhat.com">really welcome</a>.</p><h3><a name="Basics" id="Basics">Basics</a></h3><p>The <a href="http://www.w3.org/TR/xslt">XSLT specification</a> provides
33 two <a href="http://www.w3.org/TR/xslt">ways to extend an XSLT engine</a>:</p><ul><li>providing <a href="http://www.w3.org/TR/xslt">new extension
34     functions</a> which can be called from XPath expressions</li>
35   <li>providing <a href="http://www.w3.org/TR/xslt">new extension
36     elements</a> which can be inserted in stylesheets</li>
37 </ul><p>In both cases the extensions need to be associated to a new namespace,
38 i.e. an URI used as the name for the extension's namespace (there is no need
39 to have a resource there for this to work).</p><p>libxslt provides a few extensions itself, either in libxslt namespace
40 &quot;http://xmlsoft.org/XSLT/&quot; or in other namespace for well known extensions
41 provided by other XSLT processors like Saxon, Xalan or XT.</p><h3><a name="Keep" id="Keep">Extension modules</a></h3><p>Since extensions are bound to a namespace name, usually sets of extensions
42 coming from a given source are using the same namespace name defining in
43 practice a group of extensions providing elements, functions or both. From
44 libxslt point of view those are considered as an &quot;extension module&quot;, and most
45 of the APIs work at a module point of view.</p><p>Registration of new functions or elements are bound to the activation of
46 the module, this is currently done by declaring the namespace as an extension
47 by using the attribute  <code>extension-element-prefixes</code> on the
48 <code><a href="http://www.w3.org/TR/xslt">xsl:stylesheet</a></code>
49 element.</p><p>And extension module is defined by 3 objects:</p><ul><li>the namespace name associated</li>
50   <li>an initialization function</li>
51   <li>a shutdown function</li>
52 </ul><h3><a name="Registerin" id="Registerin">Registering a module</a></h3><p>Currently a libxslt module has to be compiled within the application using
53 libxslt, there is no code to load dynamically shared libraries associated to
54 namespace (this may be added but is likely to become a portability
55 nightmare).</p><p>So the current way to register a module is to link the code implementing
56 it with the application and to call a registration function:</p><pre>int xsltRegisterExtModule(const xmlChar *URI,
57                           xsltExtInitFunction initFunc,
58                           xsltExtShutdownFunction shutdownFunc);</pre><p>The associated header is read by:</p><pre>#include&lt;libxslt/extensions.h&gt;</pre><p>which also defines the type for the initialization and shutdown
59 functions</p><h3><a name="module" id="module">Loading a module</a></h3><p>Once the module URI has been registered and if the XSLT processor detects
60 that a given stylesheet needs the functionalities of an extended module, this
61 one is initialized.</p><p>The xsltExtInitFunction type defines the interface for an initialization
62 function:</p><pre>/**
63  * xsltExtInitFunction:
64  * @ctxt:  an XSLT transformation context
65  * @URI:  the namespace URI for the extension
66  *
67  * A function called at initialization time of an XSLT
68  * extension module
69  *
70  * Returns a pointer to the module specific data for this
71  * transformation
72  */
73 typedef void *(*xsltExtInitFunction)(xsltTransformContextPtr ctxt,
74                                      const xmlChar *URI);</pre><p>There are 3 things to notice:</p><ul><li>the function gets passed the namespace name URI as an argument, this
75     allow a single function to provide the initialization for multiple
76     logical modules</li>
77   <li>it also gets passed a transformation context, the initialization is
78     done at run time before any processing occurs on the stylesheet but it
79     will be invoked separately each time for each transformation</li>
80   <li>it returns a pointer, this can be used to store module specific
81     informations which can be retrieved later when a function or an element
82     from the extension are used, an obvious example is a connection to a
83     database which should be kept and reused along the transformation. NULL
84     is a perfectly valid return, there is no way to indicate a failure at
85     this level</li>
86 </ul><p>What this function is expected to do is:</p><ul><li>prepare the context for this module (like opening the database
87     connection)</li>
88   <li>register the extensions specific to this module</li>
89 </ul><h3><a name="Registerin1" id="Registerin1">Registering an extension function</a></h3><p>There is a single call to do this registration:</p><pre>int xsltRegisterExtFunction(xsltTransformContextPtr ctxt,
90                             const xmlChar *name,
91                             const xmlChar *URI,
92                             xmlXPathEvalFunc function);</pre><p>The registration is bound to a single transformation instance referred by
93 ctxt, name is the UTF8 encoded name for the NCName of the function, and URI
94 is the namespace name for the extension (no checking is done, a module could
95 register functions or elements from a different namespace, but it is not
96 recommended).</p><h3><a name="Implementi" id="Implementi">Implementing an extension function</a></h3><p>The implementation of the function must have the signature of a libxml
97 XPath function:</p><pre>/**
98  * xmlXPathEvalFunc:
99  * @ctxt: an XPath parser context
100  * @nargs: the number of arguments passed to the function
101  *
102  * an XPath evaluation function, the parameters are on the
103  * XPath context stack
104  */
105
106 typedef void (*xmlXPathEvalFunc)(xmlXPathParserContextPtr ctxt,
107                                  int nargs);</pre><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
108 find one from the other:</p><ul><li>The function xsltXPathGetTransformContext provide this lookup facility:
109     <pre>xsltTransformContextPtr
110          xsltXPathGetTransformContext
111                           (xmlXPathParserContextPtr ctxt);</pre>
112   </li>
113   <li>The <code>xmlXPathContextPtr</code> associated to an
114     <code>xsltTransformContext</code> is stored in the <code>xpathCtxt</code>
115     field.</li>
116 </ul><p>The first thing an extension function may want to do is to check the
117 arguments passed on the stack, the <code>nargs</code> will precise how many
118 of them were provided on the XPath expression. The macros valuePop will
119 extract them from the XPath stack:</p><pre>#include &lt;libxml/xpath.h&gt;
120 #include &lt;libxml/xpathInternals.h&gt;
121
122 xmlXPathObjectPtr obj = valuePop(ctxt); </pre><p>Note that <code>ctxt</code> is the XPath context not the XSLT one. It is
123 then possible to examine the content of the value. Check <a href="internals.html#Descriptio">the description of XPath objects</a> if
124 necessary. The following is a common sequcnce checking whether the argument
125 passed is a string and converting it using the built-in XPath
126 <code>string()</code> function if this is not the case:</p><pre>if (obj-&gt;type != XPATH_STRING) {
127     valuePush(ctxt, obj);
128     xmlXPathStringFunction(ctxt, 1);
129     obj = valuePop(ctxt);
130 }</pre><p>Most common XPath functions are available directly at the C level and are
131 exported either in <code>&lt;libxml/xpath.h&gt;</code> or in
132 <code>&lt;libxml/xpathInternals.h&gt;</code>.</p><p>The extension function may also need to retrieve the data associated to
133 this module instance (the database connection in the previous example) this
134 can be done using the xsltGetExtData:</p><pre>void * xsltGetExtData(xsltTransformContextPtr ctxt,
135                       const xmlChar *URI);</pre><p>again the URI to be provided is the one used which was used when
136 registering the module.</p><p>Once the function finishes, don't forget to:</p><ul><li>push the return value on the stack using <code>valuePush(ctxt,
137     obj)</code></li>
138   <li>deallocate the parameters passed to the function using
139     <code>xmlXPathFreeObject(obj)</code></li>
140 </ul><h3><a name="Examples" id="Examples">Examples for extension functions</a></h3><p>The module libxslt/functions.c containsthe sources of the XSLT built-in
141 functions, including document(), key(), generate-id(), etc. as well as a full
142 example module at the end. Here is the test function implementation for the
143 libxslt:test function:</p><pre>/**
144  * xsltExtFunctionTest:
145  * @ctxt:  the XPath Parser context
146  * @nargs:  the number of arguments
147  *
148  * function libxslt:test() for testing the extensions support.
149  */
150 static void
151 xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, int nargs)
152 {
153     xsltTransformContextPtr tctxt;
154     void *data;
155
156     tctxt = xsltXPathGetTransformContext(ctxt);
157     if (tctxt == NULL) {
158         xsltGenericError(xsltGenericErrorContext,
159             &quot;xsltExtFunctionTest: failed to get the transformation context\n&quot;);
160         return;
161     }
162     data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
163     if (data == NULL) {
164         xsltGenericError(xsltGenericErrorContext,
165             &quot;xsltExtFunctionTest: failed to get module data\n&quot;);
166         return;
167     }
168 #ifdef WITH_XSLT_DEBUG_FUNCTION
169     xsltGenericDebug(xsltGenericDebugContext,
170                      &quot;libxslt:test() called with %d args\n&quot;, nargs);
171 #endif
172 }</pre><h3><a name="Registerin2" id="Registerin2">Registering an extension element</a></h3><p>There is a single call to do this registration:</p><pre>int xsltRegisterExtElement(xsltTransformContextPtr ctxt,
173                            const xmlChar *name,
174                            const xmlChar *URI,
175                            xsltTransformFunction function);</pre><p>It is similar to the mechanism used to register an extension function,
176 except that the signature of an extension element implementation is
177 different.</p><p>The registration is bound to a single transformation instance referred by
178 ctxt, name is the UTF8 encoded name for the NCName of the element, and URI is
179 the namespace name for the extension (no checking is done, a module could
180 register elements for a different namespace, but it is not recommended).</p><h3><a name="Implementi1" id="Implementi1">Implementing an extension element</a></h3><p>The implementation of the element must have the signature of an XSLT
181 transformation function:</p><pre>/** 
182  * xsltTransformFunction: 
183  * @ctxt: the XSLT transformation context
184  * @node: the input node
185  * @inst: the stylesheet node 
186  * @comp: the compiled information from the stylesheet 
187  * 
188  * signature of the function associated to elements part of the
189  * stylesheet language like xsl:if or xsl:apply-templates.
190  */ 
191 typedef void (*xsltTransformFunction)
192                           (xsltTransformContextPtr ctxt,
193                            xmlNodePtr node,
194                            xmlNodePtr inst,
195                            xsltStylePreCompPtr comp);</pre><p>The first argument is the XSLT transformation context. The second and
196 third arguments are xmlNodePtr i.e. internal memory <a href="internals.html#libxml">representation of  XML nodes</a>. They are
197 respectively <code>node</code> from the the input document being transformed
198 by the stylesheet and <code>inst</code> the extension element in the
199 stylesheet. The last argument is <code>comp</code> a pointer to a precompiled
200 representation of <code>inst</code> but usually for extension function this
201 value is <code>NULL</code> by default (it could be added and associated to
202 the instruction in <code>inst-&gt;_private</code>).</p><p>The same functions are available from a function implementing an extension
203 element as in an extension function, including
204 <code>xsltGetExtData()</code>.</p><p>The goal of extension element being usually to enrich the generated
205 output, it is expected that they will grow the currently generated output
206 tree, this can be done by grabbing ctxt-&gt;insert which is the current
207 libxml node being generated (Note this can also be the intermediate value
208 tree being built for example to initialize a variable, the processing should
209 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
210 be employed to extend or modify the tree, but it is required to preserve the
211 insertion node and its ancestors since there is existing pointers to those
212 elements still in use in the XSLT template execution stack.</p><h3><a name="Example" id="Example">Example for extension elements</a></h3><p>The module libxslt/transform.c containsthe sources of the XSLT built-in
213 elements, including xsl:element, xsl:attribute, xsl:if, etc. There is a small
214 but full example in functions.c providing the implementation for the
215 libxslt:test element, it will output a comment in the result tree:</p><pre>/**
216  * xsltExtElementTest:
217  * @ctxt:  an XSLT processing context
218  * @node:  The current node
219  * @inst:  the instruction in the stylesheet
220  * @comp:  precomputed informations
221  *
222  * Process a libxslt:test node
223  */
224 static void
225 xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node,
226                    xmlNodePtr inst,
227                    xsltStylePreCompPtr comp)
228 {
229     xmlNodePtr comment;
230
231     if (ctxt == NULL) {
232         xsltGenericError(xsltGenericErrorContext,
233                          &quot;xsltExtElementTest: no transformation context\n&quot;);
234         return;
235     }
236     if (node == NULL) {
237         xsltGenericError(xsltGenericErrorContext,
238                          &quot;xsltExtElementTest: no current node\n&quot;);
239         return;
240     }
241     if (inst == NULL) {
242         xsltGenericError(xsltGenericErrorContext,
243                          &quot;xsltExtElementTest: no instruction\n&quot;);
244         return;
245     }
246     if (ctxt-&gt;insert == NULL) {
247         xsltGenericError(xsltGenericErrorContext,
248                          &quot;xsltExtElementTest: no insertion point\n&quot;);
249         return;
250     }
251     comment =
252         xmlNewComment((const xmlChar *)
253                       &quot;libxslt:test element test worked&quot;);
254     xmlAddChild(ctxt-&gt;insert, comment);
255 }</pre><h3><a name="shutdown" id="shutdown">The shutdown of a module</a></h3><p>When the XSLT processor ends a transformation, the shutdown function (if
256 it exists) of all the modules initialized are called.The
257 xsltExtShutdownFunction type defines the interface for a shutdown
258 function:</p><pre>/**
259  * xsltExtShutdownFunction:
260  * @ctxt:  an XSLT transformation context
261  * @URI:  the namespace URI for the extension
262  * @data:  the data associated to this module
263  *
264  * A function called at shutdown time of an XSLT extension module
265  */
266 typedef void (*xsltExtShutdownFunction) (xsltTransformContextPtr ctxt,
267                                          const xmlChar *URI,
268                                          void *data);</pre><p>this is really similar to a module initialization function except a third
269 argument is passed, it's the value that was returned by the initialization
270 function. This allow to deallocate resources from the module for example
271 close the connection to the database to keep the same example.</p><h3><a name="Future" id="Future">Future work</a></h3><p>Well some of the pieces missing:</p><ul><li>a way to load shared libraries to instanciate new modules</li>
272   <li>a better detection of extension function usage and their registration
273     without having to use the extension prefix which ought to be reserved to
274     element extensions.</li>
275   <li>more examples</li>
276   <li>implementations of the <a href="http://www.exslt.org/">EXSLT</a> common
277     extension libraries, Thomas Broyer nearly finished implementing them.</li>
278 </ul><p></p><p><a href="bugs.html">Daniel Veillard</a></p></td></tr></table></td></tr></table></td></tr></table></td></tr></table></td></tr></table></body></html>