1/* 2 * extensions.c: Implemetation of the extensions support 3 * 4 * Reference: 5 * http://www.w3.org/TR/1999/REC-xslt-19991116 6 * 7 * See Copyright for the status of this software. 8 * 9 * daniel@veillard.com 10 */ 11 12#include <libxslt/libxslt.h> 13 14#ifdef WITH_MODULES 15 16#include <string.h> 17#include <limits.h> 18 19#include <libxml/xmlmemory.h> 20#include <libxml/tree.h> 21#include <libxml/hash.h> 22#include <libxml/xmlerror.h> 23#include <libxml/parserInternals.h> 24#include <libxml/xpathInternals.h> 25#include <libxml/list.h> 26#include <libxml/xmlIO.h> 27#include <libxslt/xslt.h> 28#include <libxslt/xsltInternals.h> 29#include <libxslt/xsltutils.h> 30#include <libxslt/imports.h> 31#include <libxslt/extensions.h> 32 33#define XSLT_TESTPLUGIN_URL "http://xmlsoft.org/xslt/testplugin" 34 35/* make sure init function is exported on win32 */ 36#if defined(_WIN32) 37 #define PLUGINPUBFUN __declspec(dllexport) 38#else 39 #define PLUGINPUBFUN 40#endif 41 42/* include a prototype to make gcc happy */ 43void 44PLUGINPUBFUN xmlsoft_org_xslt_testplugin_init(void); 45 46/************************************************************************ 47 * * 48 * Test plugin module http://xmlsoft.org/xslt/testplugin * 49 * * 50 ************************************************************************/ 51 52/************************************************************************ 53 * * 54 * Test of the extension module API * 55 * * 56 ************************************************************************/ 57 58static xmlChar *testData = NULL; 59static xmlChar *testStyleData = NULL; 60 61/** 62 * xsltExtFunctionTest: 63 * @ctxt: the XPath Parser context 64 * @nargs: the number of arguments 65 * 66 * function libxslt:test() for testing the extensions support. 67 */ 68static void 69xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, 70 int nargs ATTRIBUTE_UNUSED) 71{ 72 xsltTransformContextPtr tctxt; 73 void *data = NULL; 74 75 tctxt = xsltXPathGetTransformContext(ctxt); 76 77 if (testData == NULL) { 78 xsltGenericDebug(xsltGenericDebugContext, 79 "xsltExtFunctionTest: not initialized," 80 " calling xsltGetExtData\n"); 81 data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_TESTPLUGIN_URL); 82 if (data == NULL) { 83 xsltTransformError(tctxt, NULL, NULL, 84 "xsltExtElementTest: not initialized\n"); 85 return; 86 } 87 } 88 if (tctxt == NULL) { 89 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 90 "xsltExtFunctionTest: failed to get the transformation context\n"); 91 return; 92 } 93 if (data == NULL) 94 data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_TESTPLUGIN_URL); 95 if (data == NULL) { 96 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 97 "xsltExtFunctionTest: failed to get module data\n"); 98 return; 99 } 100 if (data != testData) { 101 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 102 "xsltExtFunctionTest: got wrong module data\n"); 103 return; 104 } 105#ifdef WITH_XSLT_DEBUG_FUNCTION 106 xsltGenericDebug(xsltGenericDebugContext, 107 "libxslt:test() called with %d args\n", nargs); 108#endif 109} 110 111/** 112 * xsltExtElementPreCompTest: 113 * @style: the stylesheet 114 * @inst: the instruction in the stylesheet 115 * 116 * Process a libxslt:test node 117 */ 118static xsltElemPreCompPtr 119xsltExtElementPreCompTest(xsltStylesheetPtr style, xmlNodePtr inst, 120 xsltTransformFunction function) 121{ 122 xsltElemPreCompPtr ret; 123 124 if (style == NULL) { 125 xsltTransformError(NULL, NULL, inst, 126 "xsltExtElementTest: no transformation context\n"); 127 return (NULL); 128 } 129 if (testStyleData == NULL) { 130 xsltGenericDebug(xsltGenericDebugContext, 131 "xsltExtElementPreCompTest: not initialized," 132 " calling xsltStyleGetExtData\n"); 133 xsltStyleGetExtData(style, (const xmlChar *) XSLT_TESTPLUGIN_URL); 134 if (testStyleData == NULL) { 135 xsltTransformError(NULL, style, inst, 136 "xsltExtElementPreCompTest: not initialized\n"); 137 if (style != NULL) 138 style->errors++; 139 return (NULL); 140 } 141 } 142 if (inst == NULL) { 143 xsltTransformError(NULL, style, inst, 144 "xsltExtElementPreCompTest: no instruction\n"); 145 if (style != NULL) 146 style->errors++; 147 return (NULL); 148 } 149 ret = xsltNewElemPreComp(style, inst, function); 150 return (ret); 151} 152 153/** 154 * xsltExtElementTest: 155 * @ctxt: an XSLT processing context 156 * @node: The current node 157 * @inst: the instruction in the stylesheet 158 * @comp: precomputed informations 159 * 160 * Process a libxslt:test node 161 */ 162static void 163xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node, 164 xmlNodePtr inst, 165 xsltElemPreCompPtr comp ATTRIBUTE_UNUSED) 166{ 167 xmlNodePtr commentNode; 168 169 if (testData == NULL) { 170 xsltGenericDebug(xsltGenericDebugContext, 171 "xsltExtElementTest: not initialized," 172 " calling xsltGetExtData\n"); 173 xsltGetExtData(ctxt, (const xmlChar *) XSLT_TESTPLUGIN_URL); 174 if (testData == NULL) { 175 xsltTransformError(ctxt, NULL, inst, 176 "xsltExtElementTest: not initialized\n"); 177 return; 178 } 179 } 180 if (ctxt == NULL) { 181 xsltTransformError(ctxt, NULL, inst, 182 "xsltExtElementTest: no transformation context\n"); 183 return; 184 } 185 if (node == NULL) { 186 xsltTransformError(ctxt, NULL, inst, 187 "xsltExtElementTest: no current node\n"); 188 return; 189 } 190 if (inst == NULL) { 191 xsltTransformError(ctxt, NULL, inst, 192 "xsltExtElementTest: no instruction\n"); 193 return; 194 } 195 if (ctxt->insert == NULL) { 196 xsltTransformError(ctxt, NULL, inst, 197 "xsltExtElementTest: no insertion point\n"); 198 return; 199 } 200 commentNode = xmlNewComment((const xmlChar *) 201 "libxslt:testplugin element test worked"); 202 xmlAddChild(ctxt->insert, commentNode); 203} 204 205/** 206 * xsltExtInitTest: 207 * @ctxt: an XSLT transformation context 208 * @URI: the namespace URI for the extension 209 * 210 * A function called at initialization time of an XSLT extension module 211 * 212 * Returns a pointer to the module specific data for this transformation 213 */ 214static void * 215xsltExtInitTest(xsltTransformContextPtr ctxt, const xmlChar * URI) 216{ 217 if (testStyleData == NULL) { 218 xsltGenericDebug(xsltGenericErrorContext, 219 "xsltExtInitTest: not initialized," 220 " calling xsltStyleGetExtData\n"); 221 xsltStyleGetExtData(ctxt->style, URI); 222 if (testStyleData == NULL) { 223 xsltTransformError(ctxt, NULL, NULL, 224 "xsltExtInitTest: not initialized\n"); 225 return (NULL); 226 } 227 } 228 if (testData != NULL) { 229 xsltTransformError(ctxt, NULL, NULL, 230 "xsltExtInitTest: already initialized\n"); 231 return (NULL); 232 } 233 testData = (void *) "test data"; 234 xsltGenericDebug(xsltGenericDebugContext, 235 "Registered test plugin module : %s\n", URI); 236 return (testData); 237} 238 239 240/** 241 * xsltExtShutdownTest: 242 * @ctxt: an XSLT transformation context 243 * @URI: the namespace URI for the extension 244 * @data: the data associated to this module 245 * 246 * A function called at shutdown time of an XSLT extension module 247 */ 248static void 249xsltExtShutdownTest(xsltTransformContextPtr ctxt, 250 const xmlChar * URI, void *data) 251{ 252 if (testData == NULL) { 253 xsltTransformError(ctxt, NULL, NULL, 254 "xsltExtShutdownTest: not initialized\n"); 255 return; 256 } 257 if (data != testData) { 258 xsltTransformError(ctxt, NULL, NULL, 259 "xsltExtShutdownTest: wrong data\n"); 260 } 261 testData = NULL; 262 xsltGenericDebug(xsltGenericDebugContext, 263 "Unregistered test plugin module : %s\n", URI); 264} 265 266/** 267 * xsltExtStyleInitTest: 268 * @style: an XSLT stylesheet 269 * @URI: the namespace URI for the extension 270 * 271 * A function called at initialization time of an XSLT extension module 272 * 273 * Returns a pointer to the module specific data for this transformation 274 */ 275static void * 276xsltExtStyleInitTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED, 277 const xmlChar * URI) 278{ 279 if (testStyleData != NULL) { 280 xsltTransformError(NULL, NULL, NULL, 281 "xsltExtInitTest: already initialized\n"); 282 return (NULL); 283 } 284 testStyleData = (void *) "test data"; 285 xsltGenericDebug(xsltGenericDebugContext, 286 "Registered test plugin module : %s\n", URI); 287 return (testStyleData); 288} 289 290 291/** 292 * xsltExtStyleShutdownTest: 293 * @style: an XSLT stylesheet 294 * @URI: the namespace URI for the extension 295 * @data: the data associated to this module 296 * 297 * A function called at shutdown time of an XSLT extension module 298 */ 299static void 300xsltExtStyleShutdownTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED, 301 const xmlChar * URI, void *data) 302{ 303 if (testStyleData == NULL) { 304 xsltGenericError(xsltGenericErrorContext, 305 "xsltExtShutdownTest: not initialized\n"); 306 return; 307 } 308 if (data != testStyleData) { 309 xsltTransformError(NULL, NULL, NULL, 310 "xsltExtShutdownTest: wrong data\n"); 311 } 312 testStyleData = NULL; 313 xsltGenericDebug(xsltGenericDebugContext, 314 "Unregistered test plugin module : %s\n", URI); 315} 316 317/** 318 * xmlsoft_org_xslt_testplugin_init: 319 * 320 * Registers the test plugin module 321 */ 322 323void 324PLUGINPUBFUN xmlsoft_org_xslt_testplugin_init(void) 325{ 326 xsltRegisterExtModuleFull((const xmlChar *) XSLT_TESTPLUGIN_URL, 327 xsltExtInitTest, xsltExtShutdownTest, 328 xsltExtStyleInitTest, 329 xsltExtStyleShutdownTest); 330 xsltRegisterExtModuleFunction((const xmlChar *) "testplugin", 331 (const xmlChar *) XSLT_TESTPLUGIN_URL, 332 xsltExtFunctionTest); 333 xsltRegisterExtModuleElement((const xmlChar *) "testplugin", 334 (const xmlChar *) XSLT_TESTPLUGIN_URL, 335 xsltExtElementPreCompTest, 336 xsltExtElementTest); 337} 338 339#endif /*WITH_MODULES*/ 340