diff options
author | Daniel Veillard <veillard@src.gnome.org> | 2006-06-09 13:40:33 +0000 |
---|---|---|
committer | Daniel Veillard <veillard@src.gnome.org> | 2006-06-09 13:40:33 +0000 |
commit | 54f9859bf2bf1ded0454bfbaf6070d0b9aab43ee (patch) | |
tree | be14caa750d95698179362f7800a49b16cc6b385 /doc/extensions.html | |
parent | d9d50ec1505a65ccc62f692df28efe6112990d8a (diff) | |
download | libxslt-54f9859bf2bf1ded0454bfbaf6070d0b9aab43ee.tar.gz libxslt-54f9859bf2bf1ded0454bfbaf6070d0b9aab43ee.tar.bz2 libxslt-54f9859bf2bf1ded0454bfbaf6070d0b9aab43ee.zip |
Fixing the screwups introduced by amaya, Daniel
Diffstat (limited to 'doc/extensions.html')
-rw-r--r-- | doc/extensions.html | 265 |
1 files changed, 132 insertions, 133 deletions
diff --git a/doc/extensions.html b/doc/extensions.html index ac06e7ff..aab2f428 100644 --- a/doc/extensions.html +++ b/doc/extensions.html @@ -13,53 +13,54 @@ A:link, A:visited, A:active { text-decoration: underline } <li><a href="extensions.html#Keep">Extension modules</a></li> <li><a href="extensions.html#Registerin">Registering a module</a></li> <li><a href="extensions.html#module">Loading a module</a></li> - <li><a href="extensions.html#Registerin1">Registering an - extensionfunction</a></li> - <li><a href="extensions.html#Implementi">Implementing an - extensionfunction</a></li> - <li><a href="extensions.html#Examples">Examples for - extensionfunctions</a></li> - <li><a href="extensions.html#Registerin2">Registering an - extensionelement</a></li> - <li><a href="extensions.html#Implementi1">Implementing an - extensionelement</a></li> - <li><a href="extensions.html#Example">Example for extensionelements</a></li> + <li><a href="extensions.html#Registerin1">Registering an extension + function</a></li> + <li><a href="extensions.html#Implementi">Implementing an extension + function</a></li> + <li><a href="extensions.html#Examples">Examples for extension + functions</a></li> + <li><a href="extensions.html#Registerin2">Registering an extension + element</a></li> + <li><a href="extensions.html#Implementi1">Implementing an extension + element</a></li> + <li><a href="extensions.html#Example">Example for extension + elements</a></li> <li><a href="extensions.html#shutdown">The shutdown of a module</a></li> <li><a href="extensions.html#Future">Future work</a></li> -</ul><h3><a name="Introducti1" id="Introducti1">Introduction</a></h3><p>This document describes the work needed to write extensions to thestandard -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 -getfamiliar with <a href="internals.html">the libxslt internals</a>.</p><p>Note: this documentation is by definition incomplete and I am not good -atspelling, 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>providestwo -<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 - extensionfunctions</a>which can be called from XPath expressions</li> - <li>providing <a href="http://www.w3.org/TR/xslt">new - extensionelements</a>which can be inserted in stylesheets</li> -</ul><p>In both cases the extensions need to be associated to a new namespace,i.e. -an URI used as the name for the extension's namespace (there is no needto -have a resource there for this to work).</p><p>libxslt provides a few extensions itself, either in the libxslt -namespace"http://xmlsoft.org/XSLT/namespace" or in namespaces for other well -knownextensions 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 -extensionscoming from a given source are using the same namespace name -defining inpractice a group of extensions providing elements, functions or -both. Fromthe libxslt point of view those are considered as an "extension -module", andmost of the APIs work at a module point of view.</p><p>Registration of new functions or elements are bound to the activation -ofthe module. This is currently done by declaring the namespace as an -extensionby using the attribute <code>extension-element-prefixes</code>on -the<code><a href="http://www.w3.org/TR/xslt">xsl:stylesheet</a></code>element.</p><p>An extension module is defined by 3 objects:</p><ul><li>the namespace name associated</li> +</ul><h3><a name="Introducti1" id="Introducti1">Introduction</a></h3><p>This document describes the work needed to write extensions to the +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 +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 +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 +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 + functions</a> which can be called from XPath expressions</li> + <li>providing <a href="http://www.w3.org/TR/xslt">new extension + elements</a> which can be inserted in stylesheets</li> +</ul><p>In both cases the extensions need to be associated to a new namespace, +i.e. an URI used as the name for the extension's namespace (there is no need +to have a resource there for this to work).</p><p>libxslt provides a few extensions itself, either in the libxslt namespace +"http://xmlsoft.org/XSLT/namespace" or in namespaces for other well known +extensions 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 +coming from a given source are using the same namespace name defining in +practice a group of extensions providing elements, functions or both. From +the libxslt point of view those are considered as an "extension module", and +most of the APIs work at a module point of view.</p><p>Registration of new functions or elements are bound to the activation of +the module. This is currently done by declaring the namespace as an extension +by using the attribute <code>extension-element-prefixes</code> on the +<code><a href="http://www.w3.org/TR/xslt">xsl:stylesheet</a></code> +element.</p><p>An extension module is defined by 3 objects:</p><ul><li>the namespace name associated</li> <li>an initialization function</li> <li>a shutdown function</li> -</ul><h3><a name="Registerin" id="Registerin">Registering a module</a></h3><p>Currently a libxslt module has to be compiled within the application -usinglibxslt. There is no code to load dynamically shared libraries -associated toa namespace (this may be added but is likely to become a -portabilitynightmare).</p><p>The current way to register a module is to link the code implementing -itwith the application and to call a registration function:</p><pre>int xsltRegisterExtModule(const xmlChar *URI, +</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 +libxslt. There is no code to load dynamically shared libraries associated to +a namespace (this may be added but is likely to become a portability +nightmare).</p><p>The current way to register a module is to link the code implementing it +with the application and to call a registration function:</p><pre>int xsltRegisterExtModule(const xmlChar *URI, xsltExtInitFunction initFunc, - xsltExtShutdownFunction shutdownFunc);</pre><p>The associated header is read by:</p><pre>#include<libxslt/extensions.h></pre><p>which also defines the type for the initialization and -shutdownfunctions</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 -detectsthat a given stylesheet needs the functionalities of an extended -module, thisone is initialized.</p><p>The xsltExtInitFunction type defines the interface for an -initializationfunction:</p><pre>/** + xsltExtShutdownFunction shutdownFunc);</pre><p>The associated header is read by:</p><pre>#include<libxslt/extensions.h></pre><p>which also defines the type for the initialization and shutdown +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 +that a given stylesheet needs the functionalities of an extended module, this +one is initialized.</p><p>The xsltExtInitFunction type defines the interface for an initialization +function:</p><pre>/** * xsltExtInitFunction: * @ctxt: an XSLT transformation context * @URI: the namespace URI for the extension @@ -71,30 +72,30 @@ initializationfunction:</p><pre>/** * transformation */ typedef void *(*xsltExtInitFunction)(xsltTransformContextPtr ctxt, - 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. - Thisallows a single function to provide the initialization for - multiplelogical modules.</li> - <li>It also gets passed a transformation context. The initialization isdone - at run time before any processing occurs on the stylesheet but itwill be - invoked separately each time for each transformation.</li> - <li>It returns a pointer. This can be used to store module - specificinformation which can be retrieved later when a function or an - elementfrom the extension is used. An obvious example is a connection to - adatabase which should be kept and reused along with the - transformation.NULL is a perfectly valid return; there is no way to - indicate a failureat this level</li> -</ul><p>What this function is expected to do is:</p><ul><li>prepare the context for this module (like opening the - databaseconnection)</li> + 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 + allows a single function to provide the initialization for multiple + logical modules.</li> + <li>It also gets passed a transformation context. The initialization is + done at run time before any processing occurs on the stylesheet but it + will be invoked separately each time for each transformation.</li> + <li>It returns a pointer. This can be used to store module specific + information which can be retrieved later when a function or an element + from the extension is used. An obvious example is a connection to a + database which should be kept and reused along with the transformation. + NULL is a perfectly valid return; there is no way to indicate a failure + at this level</li> +</ul><p>What this function is expected to do is:</p><ul><li>prepare the context for this module (like opening the database + connection)</li> <li>register the extensions specific to this module</li> </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, const xmlChar *name, const xmlChar *URI, - xmlXPathEvalFunc function);</pre><p>The registration is bound to a single transformation instance referred -byctxt, name is the UTF8 encoded name for the NCName of the function, and -URIis the namespace name for the extension (no checking is done, a module -couldregister functions or elements from a different namespace, but it is -notrecommended).</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 -libxmlXPath function:</p><pre>/** + xmlXPathEvalFunc function);</pre><p>The registration is bound to a single transformation instance referred by +ctxt, name is the UTF8 encoded name for the NCName of the function, and URI +is the namespace name for the extension (no checking is done, a module could +register functions or elements from a different namespace, but it is not +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 +XPath function:</p><pre>/** * xmlXPathEvalFunc: * @ctxt: an XPath parser context * @nargs: the number of arguments passed to the function @@ -104,43 +105,43 @@ libxmlXPath function:</p><pre>/** */ typedef void (*xmlXPathEvalFunc)(xmlXPathParserContextPtr ctxt, - 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 tofind -one from the other:</p><ul><li>The function xsltXPathGetTransformContext provides this lookup facility: + 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 +find one from the other:</p><ul><li>The function xsltXPathGetTransformContext provides this lookup facility: <pre>xsltTransformContextPtr xsltXPathGetTransformContext (xmlXPathParserContextPtr ctxt);</pre> </li> - <li>The <code>xmlXPathContextPtr</code>associated to - an<code>xsltTransformContext</code>is stored in the - <code>xpathCtxt</code>field.</li> -</ul><p>The first thing an extension function may want to do is to check -thearguments passed on the stack, the <code>nargs</code>parameter will tell -howmany of them were provided on the XPath expression. The macro valuePop -willextract them from the XPath stack:</p><pre>#include <libxml/xpath.h> + <li>The <code>xmlXPathContextPtr</code> associated to an + <code>xsltTransformContext</code> is stored in the <code>xpathCtxt</code> + field.</li> +</ul><p>The first thing an extension function may want to do is to check the +arguments passed on the stack, the <code>nargs</code> parameter will tell how +many of them were provided on the XPath expression. The macro valuePop will +extract them from the XPath stack:</p><pre>#include <libxml/xpath.h> #include <libxml/xpathInternals.h> -xmlXPathObjectPtr obj = valuePop(ctxt); </pre><p>Note that <code>ctxt</code>is the XPath context not the XSLT one. It -isthen possible to examine the content of the value. Check <a href="internals.html#Descriptio">the description of XPath -objects</a>ifnecessary. The following is a common sequence checking whether -the argumentpassed is a string and converting it using the built-in -XPath<code>string()</code>function if this is not the case:</p><pre>if (obj->type != XPATH_STRING) { +xmlXPathObjectPtr obj = valuePop(ctxt); </pre><p>Note that <code>ctxt</code> is the XPath context not the XSLT one. It is +then possible to examine the content of the value. Check <a href="internals.html#Descriptio">the description of XPath objects</a> if +necessary. The following is a common sequence checking whether the argument +passed is a string and converting it using the built-in XPath +<code>string()</code> function if this is not the case:</p><pre>if (obj->type != XPATH_STRING) { valuePush(ctxt, obj); xmlXPathStringFunction(ctxt, 1); obj = valuePop(ctxt); -}</pre><p>Most common XPath functions are available directly at the C level and -areexported either in <code><libxml/xpath.h></code>or -in<code><libxml/xpathInternals.h></code>.</p><p>The extension function may also need to retrieve the data associated -tothis module instance (the database connection in the previous example) -thiscan be done using the xsltGetExtData:</p><pre>void * xsltGetExtData(xsltTransformContextPtr ctxt, - const xmlChar *URI);</pre><p>Again the URI to be provided is the one which was used when registeringthe -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,obj)</code></li> - <li>deallocate the parameters passed to the function - using<code>xmlXPathFreeObject(obj)</code></li> -</ul><h3><a name="Examples" id="Examples">Examples for extension functions</a></h3><p>The module libxslt/functions.c contains the sources of the XSLT -built-infunctions, including document(), key(), generate-id(), etc. as well -as a fullexample module at the end. Here is the test function implementation -for thelibxslt:test function:</p><pre>/** +}</pre><p>Most common XPath functions are available directly at the C level and are +exported either in <code><libxml/xpath.h></code> or in +<code><libxml/xpathInternals.h></code>.</p><p>The extension function may also need to retrieve the data associated to +this module instance (the database connection in the previous example) this +can be done using the xsltGetExtData:</p><pre>void * xsltGetExtData(xsltTransformContextPtr ctxt, + const xmlChar *URI);</pre><p>Again the URI to be provided is the one which was used when 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, + obj)</code></li> + <li>deallocate the parameters passed to the function using + <code>xmlXPathFreeObject(obj)</code></li> +</ul><h3><a name="Examples" id="Examples">Examples for extension functions</a></h3><p>The module libxslt/functions.c contains the sources of the XSLT built-in +functions, including document(), key(), generate-id(), etc. as well as a full +example module at the end. Here is the test function implementation for the +libxslt:test function:</p><pre>/** * xsltExtFunctionTest: * @ctxt: the XPath Parser context * @nargs: the number of arguments @@ -172,14 +173,13 @@ xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, int nargs) }</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, const xmlChar *name, const xmlChar *URI, - xsltTransformFunction function);</pre><p>It is similar to the mechanism used to register an extension -function,except that the signature of an extension element implementation -isdifferent.</p><p>The registration is bound to a single transformation instance referred -toby ctxt, name is the UTF8 encoded name for the NCName of the element, and -URIis the namespace name for the extension (no checking is done, a module -couldregister 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 -XSLTtransformation function:</p><pre>/** + xsltTransformFunction function);</pre><p>It is similar to the mechanism used to register an extension function, +except that the signature of an extension element implementation is +different.</p><p>The registration is bound to a single transformation instance referred to +by ctxt, name is the UTF8 encoded name for the NCName of the element, and URI +is the namespace name for the extension (no checking is done, a module could +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 +transformation function:</p><pre>/** * xsltTransformFunction: * @ctxt: the XSLT transformation context * @node: the input node @@ -193,27 +193,27 @@ typedef void (*xsltTransformFunction) (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, - xsltStylePreCompPtr comp);</pre><p>The first argument is the XSLT transformation context. The second andthird -arguments are xmlNodePtr i.e. internal memory <a href="internals.html#libxml">representation of XML nodes</a>. They -arerespectively <code>node</code>from the the input document being -transformedby the stylesheet and <code>inst</code>the extension element in -thestylesheet. The last argument is <code>comp</code>a pointer to a -precompiledrepresentation of <code>inst</code>but usually for an extension -functionthis value is <code>NULL</code>by default (it could be added and -associatedto the instruction in <code>inst->_private</code>).</p><p>The same functions are available from a function implementing an -extensionelement as in an extension function, -including<code>xsltGetExtData()</code>.</p><p>The goal of an extension element being usually to enrich the -generatedoutput, it is expected that they will grow the currently generated -outputtree. This can be done by grabbing ctxt->insert which is the -currentlibxml node being generated (Note this can also be the intermediate -valuetree being built for example to initialize a variable, the processing -shouldbe similar). The functions for libxml tree manipulation from <a href="http://xmlsoft.org/html/libxml-tree.html"><libxml/tree.h></a>canbe -employed to extend or modify the tree, but it is required to preserve -theinsertion node and its ancestors since there are existing pointers to -thoseelements 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 contains the sources of the XSLT -built-inelements, including xsl:element, xsl:attribute, xsl:if, etc. There is -a smallbut full example in functions.c providing the implementation for -thelibxslt:test element, it will output a comment in the result tree:</p><pre>/** + xsltStylePreCompPtr comp);</pre><p>The first argument is the XSLT transformation context. The second and +third arguments are xmlNodePtr i.e. internal memory <a href="internals.html#libxml">representation of XML nodes</a>. They are +respectively <code>node</code> from the the input document being transformed +by the stylesheet and <code>inst</code> the extension element in the +stylesheet. The last argument is <code>comp</code> a pointer to a precompiled +representation of <code>inst</code> but usually for an extension function +this value is <code>NULL</code> by default (it could be added and associated +to the instruction in <code>inst->_private</code>).</p><p>The same functions are available from a function implementing an extension +element as in an extension function, including +<code>xsltGetExtData()</code>.</p><p>The goal of an extension element being usually to enrich the generated +output, it is expected that they will grow the currently generated output +tree. This can be done by grabbing ctxt->insert which is the current +libxml node being generated (Note this can also be the intermediate value +tree being built for example to initialize a variable, the processing should +be similar). The functions for libxml tree manipulation from <a href="http://xmlsoft.org/html/libxml-tree.html"><libxml/tree.h></a> can +be employed to extend or modify the tree, but it is required to preserve the +insertion node and its ancestors since there are existing pointers to those +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 contains the sources of the XSLT built-in +elements, including xsl:element, xsl:attribute, xsl:if, etc. There is a small +but full example in functions.c providing the implementation for the +libxslt:test element, it will output a comment in the result tree:</p><pre>/** * xsltExtElementTest: * @ctxt: an XSLT processing context * @node: The current node @@ -253,10 +253,10 @@ xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNewComment((const xmlChar *) "libxslt:test element test worked"); xmlAddChild(ctxt->insert, comment); -}</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 (ifit -exists) for each of the modules initialized is called. -ThexsltExtShutdownFunction type defines the interface for a -shutdownfunction:</p><pre>/** +}</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 +it exists) for each of the modules initialized is called. The +xsltExtShutdownFunction type defines the interface for a shutdown +function:</p><pre>/** * xsltExtShutdownFunction: * @ctxt: an XSLT transformation context * @URI: the namespace URI for the extension @@ -266,15 +266,14 @@ shutdownfunction:</p><pre>/** */ typedef void (*xsltExtShutdownFunction) (xsltTransformContextPtr ctxt, const xmlChar *URI, - void *data);</pre><p>This is really similar to a module initialization function except a -thirdargument is passed, it's the value that was returned by the -initializationfunction. This allows the routine to deallocate resources from -the module forexample 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 instantiate new modules</li> - <li>a better detection of extension functions usage and their - registrationwithout having to use the extension prefix which ought to be - reserved toelement extensions.</li> + void *data);</pre><p>This is really similar to a module initialization function except a third +argument is passed, it's the value that was returned by the initialization +function. This allows the routine to deallocate resources from the module for +example 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 instantiate new modules</li> + <li>a better detection of extension functions usage and their registration + without having to use the extension prefix which ought to be reserved to + element extensions.</li> <li>more examples</li> - <li>implementations of the <a href="http://www.exslt.org/">EXSLT</a>commonextension libraries, Thomas - Broyer nearly finished implementing them.</li> + <li>implementations of the <a href="http://www.exslt.org/">EXSLT</a> common + extension libraries, Thomas Broyer nearly finished implementing them.</li> </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> |