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