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