"Fossies" - the Fresh Open Source Software Archive

Member "libxslt-1.1.34/doc/extensions.html" (30 Oct 2019, 22740 Bytes) of package /linux/www/libxslt-1.1.34.tar.gz:


The requested HTML page contains a <FORM> tag that is unusable on "Fossies" in "automatic" (rendered) mode so that page is shown as HTML source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    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="#a06060" 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="180"><a href="http://www.gnome.org/"><img src="gnome2.png" alt="GNOME2 Logo" /></a><a href="http://www.w3.org/Status"><img src="w3c.png" alt="W3C 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><li><a href="ChangeLog.html">ChangeLog</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>,
   11           <a href="tutorial2/libxslt_pipes.html">Tutorial2</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 libxml2</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.explain.com.au/oss/libxml2xslt.html">MacOsX binaries</a></li><li><a href="https://gitlab.gnome.org/GNOME/libxslt/issues">Bug Tracker</a></li><li><a href="http://codespeak.net/lxml/">lxml Python bindings</a></li><li><a href="http://cpan.uwinnipeg.ca/dist/XML-LibXSLT">Perl XSLT bindings</a></li><li><a href="http://www.zend.com/php5/articles/php5-xmlphp.php#Heading17">XSLT with PHP</a></li><li><a href="http://www.mod-xslt2.com/">Apache module</a></li><li><a href="http://sourceforge.net/projects/libxml2-pas/">Pascal bindings</a></li><li><a href="http://xsldbg.sourceforge.net/">Xsldbg Debugger</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>
   12   <li><a href="extensions.html#Introducti">Introduction</a></li>
   13   <li><a href="extensions.html#Basics">Basics</a></li>
   14   <li><a href="extensions.html#Keep">Extension modules</a></li>
   15   <li><a href="extensions.html#Registerin">Registering a module</a></li>
   16   <li><a href="extensions.html#module">Loading a module</a></li>
   17   <li><a href="extensions.html#Registerin1">Registering an extension
   18     function</a></li>
   19   <li><a href="extensions.html#Implementi">Implementing an extension
   20     function</a></li>
   21   <li><a href="extensions.html#Examples">Examples for extension
   22   functions</a></li>
   23   <li><a href="extensions.html#Registerin2">Registering an extension
   24     element</a></li>
   25   <li><a href="extensions.html#Implementi1">Implementing an extension
   26     element</a></li>
   27   <li><a href="extensions.html#Example">Example for extension
   28   elements</a></li>
   29   <li><a href="extensions.html#shutdown">The shutdown of a module</a></li>
   30   <li><a href="extensions.html#Future">Future work</a></li>
   31 </ul><h3><a name="Introducti1" id="Introducti1">Introduction</a></h3><p>This document describes the work needed to write extensions to the
   32 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
   33 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
   34 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
   35 two <a href="http://www.w3.org/TR/xslt">ways to extend an XSLT engine</a>:</p><ul>
   36   <li>providing <a href="http://www.w3.org/TR/xslt">new extension
   37     functions</a> which can be called from XPath expressions</li>
   38   <li>providing <a href="http://www.w3.org/TR/xslt">new extension
   39     elements</a> which can be inserted in stylesheets</li>
   40 </ul><p>In both cases the extensions need to be associated to a new namespace,
   41 i.e. an URI used as the name for the extension's namespace (there is no need
   42 to have a resource there for this to work).</p><p>libxslt provides a few extensions itself, either in the libxslt namespace
   43 "http://xmlsoft.org/XSLT/namespace" or in namespaces for other well known
   44 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
   45 coming from a given source are using the same namespace name defining in
   46 practice a group of extensions providing elements, functions or both. From
   47 the libxslt point of view those are considered as an "extension module", and
   48 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
   49 the module. This is currently done by declaring the namespace as an extension
   50 by using the attribute  <code>extension-element-prefixes</code> on the
   51 <code><a href="http://www.w3.org/TR/xslt">xsl:stylesheet</a></code>
   52 element.</p><p>An extension module is defined by 3 objects:</p><ul>
   53   <li>the namespace name associated</li>
   54   <li>an initialization function</li>
   55   <li>a shutdown function</li>
   56 </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
   57 libxslt. There is no code to load dynamically shared libraries associated to
   58 a namespace (this may be added but is likely to become a portability
   59 nightmare).</p><p>The current way to register a module is to link the code implementing it
   60 with the application and to call a registration function:</p><pre>int xsltRegisterExtModule(const xmlChar *URI,
   61                           xsltExtInitFunction initFunc,
   62                           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
   63 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
   64 that a given stylesheet needs the functionalities of an extended module, this
   65 one is initialized.</p><p>The xsltExtInitFunction type defines the interface for an initialization
   66 function:</p><pre>/**
   67  * xsltExtInitFunction:
   68  * @ctxt:  an XSLT transformation context
   69  * @URI:  the namespace URI for the extension
   70  *
   71  * A function called at initialization time of an XSLT
   72  * extension module
   73  *
   74  * Returns a pointer to the module specific data for this
   75  * transformation
   76  */
   77 typedef void *(*xsltExtInitFunction)(xsltTransformContextPtr ctxt,
   78                                      const xmlChar *URI);</pre><p>There are 3 things to notice:</p><ul>
   79   <li>The function gets passed the namespace name URI as an argument. This
   80     allows a single function to provide the initialization for multiple
   81     logical modules.</li>
   82   <li>It also gets passed a transformation context. The initialization is
   83     done at run time before any processing occurs on the stylesheet but it
   84     will be invoked separately each time for each transformation.</li>
   85   <li>It returns a pointer.  This can be used to store module specific
   86     information which can be retrieved later when a function or an element
   87     from the extension is used.  An obvious example is a connection to a
   88     database which should be kept and reused along with the transformation.
   89     NULL is a perfectly valid return; there is no way to indicate a failure
   90     at this level</li>
   91 </ul><p>What this function is expected to do is:</p><ul>
   92   <li>prepare the context for this module (like opening the database
   93     connection)</li>
   94   <li>register the extensions specific to this module</li>
   95 </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,
   96                             const xmlChar *name,
   97                             const xmlChar *URI,
   98                             xmlXPathEvalFunc function);</pre><p>The registration is bound to a single transformation instance referred by
   99 ctxt, name is the UTF8 encoded name for the NCName of the function, and URI
  100 is the namespace name for the extension (no checking is done, a module could
  101 register functions or elements from a different namespace, but it is not
  102 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
  103 XPath function:</p><pre>/**
  104  * xmlXPathEvalFunc:
  105  * @ctxt: an XPath parser context
  106  * @nargs: the number of arguments passed to the function
  107  *
  108  * an XPath evaluation function, the parameters are on the
  109  * XPath context stack
  110  */
  111 
  112 typedef void (*xmlXPathEvalFunc)(xmlXPathParserContextPtr ctxt,
  113                                  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
  114 find one from the other:</p><ul>
  115   <li>The function xsltXPathGetTransformContext provides this lookup facility:
  116     <pre>xsltTransformContextPtr
  117          xsltXPathGetTransformContext
  118                           (xmlXPathParserContextPtr ctxt);</pre>
  119   </li>
  120   <li>The <code>xmlXPathContextPtr</code> associated to an
  121     <code>xsltTransformContext</code> is stored in the <code>xpathCtxt</code>
  122     field.</li>
  123 </ul><p>The first thing an extension function may want to do is to check the
  124 arguments passed on the stack, the <code>nargs</code> parameter will tell how
  125 many of them were provided on the XPath expression. The macro valuePop will
  126 extract them from the XPath stack:</p><pre>#include &lt;libxml/xpath.h&gt;
  127 #include &lt;libxml/xpathInternals.h&gt;
  128 
  129 xmlXPathObjectPtr obj = valuePop(ctxt); </pre><p>Note that <code>ctxt</code> is the XPath context not the XSLT one. It is
  130 then possible to examine the content of the value. Check <a href="internals.html#Descriptio">the description of XPath objects</a> if
  131 necessary. The following is a common sequence checking whether the argument
  132 passed is a string and converting it using the built-in XPath
  133 <code>string()</code> function if this is not the case:</p><pre>if (obj-&gt;type != XPATH_STRING) {
  134     valuePush(ctxt, obj);
  135     xmlXPathStringFunction(ctxt, 1);
  136     obj = valuePop(ctxt);
  137 }</pre><p>Most common XPath functions are available directly at the C level and are
  138 exported either in <code>&lt;libxml/xpath.h&gt;</code> or in
  139 <code>&lt;libxml/xpathInternals.h&gt;</code>.</p><p>The extension function may also need to retrieve the data associated to
  140 this module instance (the database connection in the previous example) this
  141 can be done using the xsltGetExtData:</p><pre>void * xsltGetExtData(xsltTransformContextPtr ctxt,
  142                       const xmlChar *URI);</pre><p>Again the URI to be provided is the one which was used when registering
  143 the module.</p><p>Once the function finishes, don't forget to:</p><ul>
  144   <li>push the return value on the stack using <code>valuePush(ctxt,
  145     obj)</code></li>
  146   <li>deallocate the parameters passed to the function using
  147     <code>xmlXPathFreeObject(obj)</code></li>
  148 </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
  149 functions, including document(), key(), generate-id(), etc. as well as a full
  150 example module at the end. Here is the test function implementation for the
  151 libxslt:test function:</p><pre>/**
  152  * xsltExtFunctionTest:
  153  * @ctxt:  the XPath Parser context
  154  * @nargs:  the number of arguments
  155  *
  156  * function libxslt:test() for testing the extensions support.
  157  */
  158 static void
  159 xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, int nargs)
  160 {
  161     xsltTransformContextPtr tctxt;
  162     void *data;
  163 
  164     tctxt = xsltXPathGetTransformContext(ctxt);
  165     if (tctxt == NULL) {
  166         xsltGenericError(xsltGenericErrorContext,
  167             "xsltExtFunctionTest: failed to get the transformation context\n");
  168         return;
  169     }
  170     data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
  171     if (data == NULL) {
  172         xsltGenericError(xsltGenericErrorContext,
  173             "xsltExtFunctionTest: failed to get module data\n");
  174         return;
  175     }
  176 #ifdef WITH_XSLT_DEBUG_FUNCTION
  177     xsltGenericDebug(xsltGenericDebugContext,
  178                      "libxslt:test() called with %d args\n", nargs);
  179 #endif
  180 }</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,
  181                            const xmlChar *name,
  182                            const xmlChar *URI,
  183                            xsltTransformFunction function);</pre><p>It is similar to the mechanism used to register an extension function,
  184 except that the signature of an extension element implementation is
  185 different.</p><p>The registration is bound to a single transformation instance referred to
  186 by ctxt, name is the UTF8 encoded name for the NCName of the element, and URI
  187 is the namespace name for the extension (no checking is done, a module could
  188 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
  189 transformation function:</p><pre>/** 
  190  * xsltTransformFunction: 
  191  * @ctxt: the XSLT transformation context
  192  * @node: the input node
  193  * @inst: the stylesheet node 
  194  * @comp: the compiled information from the stylesheet 
  195  * 
  196  * signature of the function associated to elements part of the
  197  * stylesheet language like xsl:if or xsl:apply-templates.
  198  */ 
  199 typedef void (*xsltTransformFunction)
  200                           (xsltTransformContextPtr ctxt,
  201                            xmlNodePtr node,
  202                            xmlNodePtr inst,
  203                            xsltStylePreCompPtr comp);</pre><p>The first argument is the XSLT transformation context. The second and
  204 third arguments are xmlNodePtr i.e. internal memory <a href="internals.html#libxml">representation of  XML nodes</a>. They are
  205 respectively <code>node</code> from the the input document being transformed
  206 by the stylesheet and <code>inst</code> the extension element in the
  207 stylesheet. The last argument is <code>comp</code> a pointer to a precompiled
  208 representation of <code>inst</code> but usually for an extension function
  209 this value is <code>NULL</code> by default (it could be added and associated
  210 to the instruction in <code>inst-&gt;_private</code>).</p><p>The same functions are available from a function implementing an extension
  211 element as in an extension function, including
  212 <code>xsltGetExtData()</code>.</p><p>The goal of an extension element being usually to enrich the generated
  213 output, it is expected that they will grow the currently generated output
  214 tree. This can be done by grabbing ctxt-&gt;insert which is the current
  215 libxml node being generated (Note this can also be the intermediate value
  216 tree being built for example to initialize a variable, the processing should
  217 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
  218 be employed to extend or modify the tree, but it is required to preserve the
  219 insertion node and its ancestors since there are existing pointers to those
  220 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
  221 elements, including xsl:element, xsl:attribute, xsl:if, etc. There is a small
  222 but full example in functions.c providing the implementation for the
  223 libxslt:test element, it will output a comment in the result tree:</p><pre>/**
  224  * xsltExtElementTest:
  225  * @ctxt:  an XSLT processing context
  226  * @node:  The current node
  227  * @inst:  the instruction in the stylesheet
  228  * @comp:  precomputed information
  229  *
  230  * Process a libxslt:test node
  231  */
  232 static void
  233 xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node,
  234                    xmlNodePtr inst,
  235                    xsltStylePreCompPtr comp)
  236 {
  237     xmlNodePtr comment;
  238 
  239     if (ctxt == NULL) {
  240         xsltGenericError(xsltGenericErrorContext,
  241                          "xsltExtElementTest: no transformation context\n");
  242         return;
  243     }
  244     if (node == NULL) {
  245         xsltGenericError(xsltGenericErrorContext,
  246                          "xsltExtElementTest: no current node\n");
  247         return;
  248     }
  249     if (inst == NULL) {
  250         xsltGenericError(xsltGenericErrorContext,
  251                          "xsltExtElementTest: no instruction\n");
  252         return;
  253     }
  254     if (ctxt-&gt;insert == NULL) {
  255         xsltGenericError(xsltGenericErrorContext,
  256                          "xsltExtElementTest: no insertion point\n");
  257         return;
  258     }
  259     comment =
  260         xmlNewComment((const xmlChar *)
  261                       "libxslt:test element test worked");
  262     xmlAddChild(ctxt-&gt;insert, comment);
  263 }</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
  264 it exists) for each of the modules initialized is called.  The
  265 xsltExtShutdownFunction type defines the interface for a shutdown
  266 function:</p><pre>/**
  267  * xsltExtShutdownFunction:
  268  * @ctxt:  an XSLT transformation context
  269  * @URI:  the namespace URI for the extension
  270  * @data:  the data associated to this module
  271  *
  272  * A function called at shutdown time of an XSLT extension module
  273  */
  274 typedef void (*xsltExtShutdownFunction) (xsltTransformContextPtr ctxt,
  275                                          const xmlChar *URI,
  276                                          void *data);</pre><p>This is really similar to a module initialization function except a third
  277 argument is passed, it's the value that was returned by the initialization
  278 function. This allows the routine to deallocate resources from the module for
  279 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>
  280   <li>a way to load shared libraries to instantiate new modules</li>
  281   <li>a better detection of extension functions usage and their registration
  282     without having to use the extension prefix which ought to be reserved to
  283     element extensions.</li>
  284   <li>more examples</li>
  285   <li>implementations of the <a href="http://www.exslt.org/">EXSLT</a> common
  286     extension libraries, Thomas Broyer nearly finished implementing them.</li>
  287 </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>