VirtualBox

source: vbox/trunk/src/libs/libxslt-1.1.22/doc/extensions.html@ 32671

最後變更 在這個檔案從32671是 7296,由 vboxsync 提交於 17 年 前

Added libxslt-1.1.22 sources.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Date Revision Author Id
檔案大小: 22.2 KB
 
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">
4TD {font-family: Verdana,Arial,Helvetica}
5BODY {font-family: Verdana,Arial,Helvetica; margin-top: 2em; margin-left: 0em; margin-right: 0em}
6H1 {font-family: Verdana,Arial,Helvetica}
7H2 {font-family: Verdana,Arial,Helvetica}
8H3 {font-family: Verdana,Arial,Helvetica}
9A: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
31standard 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
32familiar with <a href="internals.html">the libxslt internals</a>.</p><p>Note: this documentation is by definition incomplete and I am not good at
33spelling, grammar, so patches and suggestions are <a href="mailto:[email protected]">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
34two <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,
39i.e. an URI used as the name for the extension's namespace (there is no need
40to 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
42extensions 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
43coming from a given source are using the same namespace name defining in
44practice a group of extensions providing elements, functions or both. From
45the libxslt point of view those are considered as an "extension module", and
46most of the APIs work at a module point of view.</p><p>Registration of new functions or elements are bound to the activation of
47the module. This is currently done by declaring the namespace as an extension
48by using the attribute <code>extension-element-prefixes</code> on the
49<code><a href="http://www.w3.org/TR/xslt">xsl:stylesheet</a></code>
50element.</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
54libxslt. There is no code to load dynamically shared libraries associated to
55a namespace (this may be added but is likely to become a portability
56nightmare).</p><p>The current way to register a module is to link the code implementing it
57with 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
60functions</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
61that a given stylesheet needs the functionalities of an extended module, this
62one is initialized.</p><p>The xsltExtInitFunction type defines the interface for an initialization
63function:</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 */
74typedef 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
94ctxt, name is the UTF8 encoded name for the NCName of the function, and URI
95is the namespace name for the extension (no checking is done, a module could
96register functions or elements from a different namespace, but it is not
97recommended).</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
98XPath 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
107typedef 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
109find 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
118arguments passed on the stack, the <code>nargs</code> parameter will tell how
119many of them were provided on the XPath expression. The macro valuePop will
120extract them from the XPath stack:</p><pre>#include &lt;libxml/xpath.h&gt;
121#include &lt;libxml/xpathInternals.h&gt;
122
123xmlXPathObjectPtr obj = valuePop(ctxt); </pre><p>Note that <code>ctxt</code> is the XPath context not the XSLT one. It is
124then possible to examine the content of the value. Check <a href="internals.html#Descriptio">the description of XPath objects</a> if
125necessary. The following is a common sequence checking whether the argument
126passed 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
132exported 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
134this module instance (the database connection in the previous example) this
135can 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
137the 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
142functions, including document(), key(), generate-id(), etc. as well as a full
143example module at the end. Here is the test function implementation for the
144libxslt: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 */
151static void
152xsltExtFunctionTest(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,
177except that the signature of an extension element implementation is
178different.</p><p>The registration is bound to a single transformation instance referred to
179by ctxt, name is the UTF8 encoded name for the NCName of the element, and URI
180is the namespace name for the extension (no checking is done, a module could
181register 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
182transformation 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 */
192typedef 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
197third arguments are xmlNodePtr i.e. internal memory <a href="internals.html#libxml">representation of XML nodes</a>. They are
198respectively <code>node</code> from the the input document being transformed
199by the stylesheet and <code>inst</code> the extension element in the
200stylesheet. The last argument is <code>comp</code> a pointer to a precompiled
201representation of <code>inst</code> but usually for an extension function
202this value is <code>NULL</code> by default (it could be added and associated
203to the instruction in <code>inst-&gt;_private</code>).</p><p>The same functions are available from a function implementing an extension
204element as in an extension function, including
205<code>xsltGetExtData()</code>.</p><p>The goal of an extension element being usually to enrich the generated
206output, it is expected that they will grow the currently generated output
207tree. This can be done by grabbing ctxt-&gt;insert which is the current
208libxml node being generated (Note this can also be the intermediate value
209tree being built for example to initialize a variable, the processing should
210be similar). The functions for libxml tree manipulation from <a href="http://xmlsoft.org/html/libxml-tree.html">&lt;libxml/tree.h&gt;</a> can
211be employed to extend or modify the tree, but it is required to preserve the
212insertion node and its ancestors since there are existing pointers to those
213elements 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
214elements, including xsl:element, xsl:attribute, xsl:if, etc. There is a small
215but full example in functions.c providing the implementation for the
216libxslt: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 */
225static void
226xsltExtElementTest(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
257it exists) for each of the modules initialized is called. The
258xsltExtShutdownFunction type defines the interface for a shutdown
259function:</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 */
267typedef 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
270argument is passed, it's the value that was returned by the initialization
271function. This allows the routine to deallocate resources from the module for
272example 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>
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette