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 | #define IN_LIBXSLT |
---|
13 | #include "libxslt.h" |
---|
14 | |
---|
15 | #include <string.h> |
---|
16 | |
---|
17 | #include <libxml/xmlmemory.h> |
---|
18 | #include <libxml/tree.h> |
---|
19 | #include <libxml/hash.h> |
---|
20 | #include <libxml/xmlerror.h> |
---|
21 | #include <libxml/parserInternals.h> |
---|
22 | #include <libxml/xpathInternals.h> |
---|
23 | #include "xslt.h" |
---|
24 | #include "xsltInternals.h" |
---|
25 | #include "xsltutils.h" |
---|
26 | #include "imports.h" |
---|
27 | #include "extensions.h" |
---|
28 | |
---|
29 | #ifdef WITH_XSLT_DEBUG |
---|
30 | #define WITH_XSLT_DEBUG_EXTENSIONS |
---|
31 | #endif |
---|
32 | |
---|
33 | /************************************************************************ |
---|
34 | * * |
---|
35 | * Private Types and Globals * |
---|
36 | * * |
---|
37 | ************************************************************************/ |
---|
38 | |
---|
39 | typedef struct _xsltExtDef xsltExtDef; |
---|
40 | typedef xsltExtDef *xsltExtDefPtr; |
---|
41 | struct _xsltExtDef { |
---|
42 | struct _xsltExtDef *next; |
---|
43 | xmlChar *prefix; |
---|
44 | xmlChar *URI; |
---|
45 | void *data; |
---|
46 | }; |
---|
47 | |
---|
48 | typedef struct _xsltExtModule xsltExtModule; |
---|
49 | typedef xsltExtModule *xsltExtModulePtr; |
---|
50 | struct _xsltExtModule { |
---|
51 | xsltExtInitFunction initFunc; |
---|
52 | xsltExtShutdownFunction shutdownFunc; |
---|
53 | xsltStyleExtInitFunction styleInitFunc; |
---|
54 | xsltStyleExtShutdownFunction styleShutdownFunc; |
---|
55 | }; |
---|
56 | |
---|
57 | typedef struct _xsltExtData xsltExtData; |
---|
58 | typedef xsltExtData *xsltExtDataPtr; |
---|
59 | struct _xsltExtData { |
---|
60 | xsltExtModulePtr extModule; |
---|
61 | void *extData; |
---|
62 | }; |
---|
63 | |
---|
64 | typedef struct _xsltExtElement xsltExtElement; |
---|
65 | typedef xsltExtElement *xsltExtElementPtr; |
---|
66 | struct _xsltExtElement { |
---|
67 | xsltPreComputeFunction precomp; |
---|
68 | xsltTransformFunction transform; |
---|
69 | }; |
---|
70 | |
---|
71 | static xmlHashTablePtr xsltExtensionsHash = NULL; |
---|
72 | static xmlHashTablePtr xsltFunctionsHash = NULL; |
---|
73 | static xmlHashTablePtr xsltElementsHash = NULL; |
---|
74 | static xmlHashTablePtr xsltTopLevelsHash = NULL; |
---|
75 | |
---|
76 | /************************************************************************ |
---|
77 | * * |
---|
78 | * Type functions * |
---|
79 | * * |
---|
80 | ************************************************************************/ |
---|
81 | |
---|
82 | /** |
---|
83 | * xsltNewExtDef: |
---|
84 | * @prefix: the extension prefix |
---|
85 | * @URI: the namespace URI |
---|
86 | * |
---|
87 | * Create a new XSLT ExtDef |
---|
88 | * |
---|
89 | * Returns the newly allocated xsltExtDefPtr or NULL in case of error |
---|
90 | */ |
---|
91 | static xsltExtDefPtr |
---|
92 | xsltNewExtDef(const xmlChar * prefix, const xmlChar * URI) |
---|
93 | { |
---|
94 | xsltExtDefPtr cur; |
---|
95 | |
---|
96 | cur = (xsltExtDefPtr) xmlMalloc(sizeof(xsltExtDef)); |
---|
97 | if (cur == NULL) { |
---|
98 | xsltTransformError(NULL, NULL, NULL, |
---|
99 | "xsltNewExtDef : malloc failed\n"); |
---|
100 | return (NULL); |
---|
101 | } |
---|
102 | memset(cur, 0, sizeof(xsltExtDef)); |
---|
103 | if (prefix != NULL) |
---|
104 | cur->prefix = xmlStrdup(prefix); |
---|
105 | if (URI != NULL) |
---|
106 | cur->URI = xmlStrdup(URI); |
---|
107 | return (cur); |
---|
108 | } |
---|
109 | |
---|
110 | /** |
---|
111 | * xsltFreeExtDef: |
---|
112 | * @extensiond: an XSLT extension definition |
---|
113 | * |
---|
114 | * Free up the memory allocated by @extensiond |
---|
115 | */ |
---|
116 | static void |
---|
117 | xsltFreeExtDef(xsltExtDefPtr extensiond) { |
---|
118 | if (extensiond == NULL) |
---|
119 | return; |
---|
120 | if (extensiond->prefix != NULL) |
---|
121 | xmlFree(extensiond->prefix); |
---|
122 | if (extensiond->URI != NULL) |
---|
123 | xmlFree(extensiond->URI); |
---|
124 | xmlFree(extensiond); |
---|
125 | } |
---|
126 | |
---|
127 | /** |
---|
128 | * xsltFreeExtDefList: |
---|
129 | * @extensiond: an XSLT extension definition list |
---|
130 | * |
---|
131 | * Free up the memory allocated by all the elements of @extensiond |
---|
132 | */ |
---|
133 | static void |
---|
134 | xsltFreeExtDefList(xsltExtDefPtr extensiond) { |
---|
135 | xsltExtDefPtr cur; |
---|
136 | |
---|
137 | while (extensiond != NULL) { |
---|
138 | cur = extensiond; |
---|
139 | extensiond = extensiond->next; |
---|
140 | xsltFreeExtDef(cur); |
---|
141 | } |
---|
142 | } |
---|
143 | |
---|
144 | /** |
---|
145 | * xsltNewExtModule: |
---|
146 | * @initFunc: the module initialization function |
---|
147 | * @shutdownFunc: the module shutdown function |
---|
148 | * @styleInitFunc: the stylesheet module data allocator function |
---|
149 | * @styleShutdownFunc: the stylesheet module data free function |
---|
150 | * |
---|
151 | * Create a new XSLT extension module |
---|
152 | * |
---|
153 | * Returns the newly allocated xsltExtModulePtr or NULL in case of error |
---|
154 | */ |
---|
155 | static xsltExtModulePtr |
---|
156 | xsltNewExtModule(xsltExtInitFunction initFunc, |
---|
157 | xsltExtShutdownFunction shutdownFunc, |
---|
158 | xsltStyleExtInitFunction styleInitFunc, |
---|
159 | xsltStyleExtShutdownFunction styleShutdownFunc) |
---|
160 | { |
---|
161 | xsltExtModulePtr cur; |
---|
162 | |
---|
163 | cur = (xsltExtModulePtr) xmlMalloc(sizeof(xsltExtModule)); |
---|
164 | if (cur == NULL) { |
---|
165 | xsltTransformError(NULL, NULL, NULL, |
---|
166 | "xsltNewExtModule : malloc failed\n"); |
---|
167 | return (NULL); |
---|
168 | } |
---|
169 | cur->initFunc = initFunc; |
---|
170 | cur->shutdownFunc = shutdownFunc; |
---|
171 | cur->styleInitFunc = styleInitFunc; |
---|
172 | cur->styleShutdownFunc = styleShutdownFunc; |
---|
173 | return (cur); |
---|
174 | } |
---|
175 | |
---|
176 | /** |
---|
177 | * xsltFreeExtModule: |
---|
178 | * @ext: an XSLT extension module |
---|
179 | * |
---|
180 | * Free up the memory allocated by @ext |
---|
181 | */ |
---|
182 | static void |
---|
183 | xsltFreeExtModule(xsltExtModulePtr ext) { |
---|
184 | if (ext == NULL) |
---|
185 | return; |
---|
186 | xmlFree(ext); |
---|
187 | } |
---|
188 | |
---|
189 | /** |
---|
190 | * xsltNewExtData: |
---|
191 | * @extModule: the module |
---|
192 | * @extData: the associated data |
---|
193 | * |
---|
194 | * Create a new XSLT extension module data wrapper |
---|
195 | * |
---|
196 | * Returns the newly allocated xsltExtDataPtr or NULL in case of error |
---|
197 | */ |
---|
198 | static xsltExtDataPtr |
---|
199 | xsltNewExtData(xsltExtModulePtr extModule, void *extData) |
---|
200 | { |
---|
201 | xsltExtDataPtr cur; |
---|
202 | |
---|
203 | if (extModule == NULL) |
---|
204 | return(NULL); |
---|
205 | cur = (xsltExtDataPtr) xmlMalloc(sizeof(xsltExtData)); |
---|
206 | if (cur == NULL) { |
---|
207 | xsltTransformError(NULL, NULL, NULL, |
---|
208 | "xsltNewExtData : malloc failed\n"); |
---|
209 | return (NULL); |
---|
210 | } |
---|
211 | cur->extModule = extModule; |
---|
212 | cur->extData = extData; |
---|
213 | return (cur); |
---|
214 | } |
---|
215 | |
---|
216 | /** |
---|
217 | * xsltFreeExtData: |
---|
218 | * @ext: an XSLT extension module data wrapper |
---|
219 | * |
---|
220 | * Free up the memory allocated by @ext |
---|
221 | */ |
---|
222 | static void |
---|
223 | xsltFreeExtData(xsltExtDataPtr ext) { |
---|
224 | if (ext == NULL) |
---|
225 | return; |
---|
226 | xmlFree(ext); |
---|
227 | } |
---|
228 | |
---|
229 | /** |
---|
230 | * xsltNewExtElement: |
---|
231 | * @precomp: the pre-computation function |
---|
232 | * @transform: the transformation function |
---|
233 | * |
---|
234 | * Create a new XSLT extension element |
---|
235 | * |
---|
236 | * Returns the newly allocated xsltExtElementPtr or NULL in case of |
---|
237 | * error |
---|
238 | */ |
---|
239 | static xsltExtElementPtr |
---|
240 | xsltNewExtElement (xsltPreComputeFunction precomp, |
---|
241 | xsltTransformFunction transform) { |
---|
242 | xsltExtElementPtr cur; |
---|
243 | |
---|
244 | if (transform == NULL) |
---|
245 | return(NULL); |
---|
246 | |
---|
247 | cur = (xsltExtElementPtr) xmlMalloc(sizeof(xsltExtElement)); |
---|
248 | if (cur == NULL) { |
---|
249 | xsltTransformError(NULL, NULL, NULL, |
---|
250 | "xsltNewExtElement : malloc failed\n"); |
---|
251 | return (NULL); |
---|
252 | } |
---|
253 | cur->precomp = precomp; |
---|
254 | cur->transform = transform; |
---|
255 | return(cur); |
---|
256 | } |
---|
257 | |
---|
258 | /** |
---|
259 | * xsltFreeExtElement: |
---|
260 | * @ext: an XSLT extension element |
---|
261 | * |
---|
262 | * Frees up the memory allocated by @ext |
---|
263 | */ |
---|
264 | static void |
---|
265 | xsltFreeExtElement (xsltExtElementPtr ext) { |
---|
266 | if (ext == NULL) |
---|
267 | return; |
---|
268 | xmlFree(ext); |
---|
269 | } |
---|
270 | |
---|
271 | |
---|
272 | /************************************************************************ |
---|
273 | * * |
---|
274 | * The stylesheet extension prefixes handling * |
---|
275 | * * |
---|
276 | ************************************************************************/ |
---|
277 | |
---|
278 | |
---|
279 | /** |
---|
280 | * xsltFreeExts: |
---|
281 | * @style: an XSLT stylesheet |
---|
282 | * |
---|
283 | * Free up the memory used by XSLT extensions in a stylesheet |
---|
284 | */ |
---|
285 | void |
---|
286 | xsltFreeExts(xsltStylesheetPtr style) { |
---|
287 | if (style->nsDefs != NULL) |
---|
288 | xsltFreeExtDefList((xsltExtDefPtr) style->nsDefs); |
---|
289 | } |
---|
290 | |
---|
291 | /** |
---|
292 | * xsltRegisterExtPrefix: |
---|
293 | * @style: an XSLT stylesheet |
---|
294 | * @prefix: the prefix used |
---|
295 | * @URI: the URI associated to the extension |
---|
296 | * |
---|
297 | * Registers an extension namespace |
---|
298 | * |
---|
299 | * Returns 0 in case of success, -1 in case of failure |
---|
300 | */ |
---|
301 | int |
---|
302 | xsltRegisterExtPrefix(xsltStylesheetPtr style, |
---|
303 | const xmlChar *prefix, const xmlChar *URI) { |
---|
304 | xsltExtDefPtr def, ret; |
---|
305 | |
---|
306 | if ((style == NULL) || (prefix == NULL) | (URI == NULL)) |
---|
307 | return(-1); |
---|
308 | |
---|
309 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
310 | xsltGenericDebug(xsltGenericDebugContext, |
---|
311 | "Registering extension prefix %s : %s\n", prefix, URI); |
---|
312 | #endif |
---|
313 | def = (xsltExtDefPtr) style->nsDefs; |
---|
314 | while (def != NULL) { |
---|
315 | if (xmlStrEqual(prefix, def->prefix)) |
---|
316 | return(-1); |
---|
317 | def = def->next; |
---|
318 | } |
---|
319 | ret = xsltNewExtDef(prefix, URI); |
---|
320 | if (ret == NULL) |
---|
321 | return(-1); |
---|
322 | ret->next = (xsltExtDefPtr) style->nsDefs; |
---|
323 | style->nsDefs = ret; |
---|
324 | |
---|
325 | /* |
---|
326 | * check wether there is an extension module with a stylesheet |
---|
327 | * initialization function. |
---|
328 | */ |
---|
329 | if (xsltExtensionsHash != NULL) { |
---|
330 | xsltExtModulePtr module; |
---|
331 | |
---|
332 | module = xmlHashLookup(xsltExtensionsHash, URI); |
---|
333 | if (module != NULL) { |
---|
334 | xsltExtDataPtr data; |
---|
335 | |
---|
336 | data = xsltStyleGetExtData(style, URI); |
---|
337 | } |
---|
338 | } |
---|
339 | return(0); |
---|
340 | } |
---|
341 | |
---|
342 | /************************************************************************ |
---|
343 | * * |
---|
344 | * The extensions modules interfaces * |
---|
345 | * * |
---|
346 | ************************************************************************/ |
---|
347 | |
---|
348 | /** |
---|
349 | * xsltRegisterExtFunction: |
---|
350 | * @ctxt: an XSLT transformation context |
---|
351 | * @name: the name of the element |
---|
352 | * @URI: the URI associated to the element |
---|
353 | * @function: the actual implementation which should be called |
---|
354 | * |
---|
355 | * Registers an extension function |
---|
356 | * |
---|
357 | * Returns 0 in case of success, -1 in case of failure |
---|
358 | */ |
---|
359 | int |
---|
360 | xsltRegisterExtFunction(xsltTransformContextPtr ctxt, const xmlChar *name, |
---|
361 | const xmlChar *URI, xmlXPathFunction function) { |
---|
362 | if ((ctxt == NULL) || (name == NULL) || |
---|
363 | (URI == NULL) || (function == NULL)) |
---|
364 | return(-1); |
---|
365 | if (ctxt->xpathCtxt != NULL) { |
---|
366 | xmlXPathRegisterFuncNS(ctxt->xpathCtxt, name, URI, function); |
---|
367 | } |
---|
368 | if (ctxt->extFunctions == NULL) |
---|
369 | ctxt->extFunctions = xmlHashCreate(10); |
---|
370 | if (ctxt->extFunctions == NULL) |
---|
371 | return(-1); |
---|
372 | return(xmlHashAddEntry2(ctxt->extFunctions, name, URI, (void *) function)); |
---|
373 | } |
---|
374 | |
---|
375 | /** |
---|
376 | * xsltRegisterExtElement: |
---|
377 | * @ctxt: an XSLT transformation context |
---|
378 | * @name: the name of the element |
---|
379 | * @URI: the URI associated to the element |
---|
380 | * @function: the actual implementation which should be called |
---|
381 | * |
---|
382 | * Registers an extension element |
---|
383 | * |
---|
384 | * Returns 0 in case of success, -1 in case of failure |
---|
385 | */ |
---|
386 | int |
---|
387 | xsltRegisterExtElement(xsltTransformContextPtr ctxt, const xmlChar *name, |
---|
388 | const xmlChar *URI, xsltTransformFunction function) { |
---|
389 | if ((ctxt == NULL) || (name == NULL) || |
---|
390 | (URI == NULL) || (function == NULL)) |
---|
391 | return(-1); |
---|
392 | if (ctxt->extElements == NULL) |
---|
393 | ctxt->extElements = xmlHashCreate(10); |
---|
394 | if (ctxt->extElements == NULL) |
---|
395 | return(-1); |
---|
396 | return(xmlHashAddEntry2(ctxt->extElements, name, URI, (void *) function)); |
---|
397 | } |
---|
398 | |
---|
399 | /** |
---|
400 | * xsltFreeCtxtExts: |
---|
401 | * @ctxt: an XSLT transformation context |
---|
402 | * |
---|
403 | * Free the XSLT extension data |
---|
404 | */ |
---|
405 | void |
---|
406 | xsltFreeCtxtExts(xsltTransformContextPtr ctxt) { |
---|
407 | if (ctxt->extElements != NULL) |
---|
408 | xmlHashFree(ctxt->extElements, NULL); |
---|
409 | if (ctxt->extFunctions != NULL) |
---|
410 | xmlHashFree(ctxt->extFunctions, NULL); |
---|
411 | } |
---|
412 | |
---|
413 | /** |
---|
414 | * xsltStyleGetExtData: |
---|
415 | * @style: an XSLT stylesheet |
---|
416 | * @URI: the URI associated to the exension module |
---|
417 | * |
---|
418 | * Retrieve the data associated to the extension module in this given |
---|
419 | * stylesheet. |
---|
420 | * |
---|
421 | * Returns the pointer or NULL if not present |
---|
422 | */ |
---|
423 | void * |
---|
424 | xsltStyleGetExtData(xsltStylesheetPtr style, const xmlChar * URI) { |
---|
425 | xsltExtDataPtr data = NULL; |
---|
426 | xsltStylesheetPtr tmp; |
---|
427 | |
---|
428 | |
---|
429 | if ((style == NULL) || (URI == NULL)) |
---|
430 | return (NULL); |
---|
431 | |
---|
432 | tmp = style; |
---|
433 | while (tmp != NULL) { |
---|
434 | if (tmp->extInfos != NULL) { |
---|
435 | data = (xsltExtDataPtr) xmlHashLookup(tmp->extInfos, URI); |
---|
436 | if (data != NULL) |
---|
437 | break; |
---|
438 | } |
---|
439 | tmp = xsltNextImport(tmp); |
---|
440 | } |
---|
441 | if (data == NULL) { |
---|
442 | if (style->extInfos == NULL) { |
---|
443 | style->extInfos = xmlHashCreate(10); |
---|
444 | if (style->extInfos == NULL) |
---|
445 | return(NULL); |
---|
446 | } |
---|
447 | } |
---|
448 | if (data == NULL) { |
---|
449 | void *extData; |
---|
450 | xsltExtModulePtr module; |
---|
451 | |
---|
452 | module = xmlHashLookup(xsltExtensionsHash, URI); |
---|
453 | if (module == NULL) { |
---|
454 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
455 | xsltGenericDebug(xsltGenericDebugContext, |
---|
456 | "Not registered extension module: %s\n", URI); |
---|
457 | #endif |
---|
458 | return(NULL); |
---|
459 | } else { |
---|
460 | if (module->styleInitFunc == NULL) { |
---|
461 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
462 | xsltGenericDebug(xsltGenericDebugContext, |
---|
463 | "Registering style module: %s\n", URI); |
---|
464 | #endif |
---|
465 | extData = NULL; |
---|
466 | } else { |
---|
467 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
468 | xsltGenericDebug(xsltGenericDebugContext, |
---|
469 | "Initializing module: %s\n", URI); |
---|
470 | #endif |
---|
471 | extData = module->styleInitFunc(style, URI); |
---|
472 | } |
---|
473 | |
---|
474 | data = xsltNewExtData(module, extData); |
---|
475 | if (data == NULL) |
---|
476 | return (NULL); |
---|
477 | if (xmlHashAddEntry(style->extInfos, URI, |
---|
478 | (void *) data) < 0) { |
---|
479 | xsltGenericError(xsltGenericErrorContext, |
---|
480 | "Failed to register module data: %s\n", URI); |
---|
481 | if (module->styleShutdownFunc) |
---|
482 | module->styleShutdownFunc(style, URI, extData); |
---|
483 | xsltFreeExtData(data); |
---|
484 | return(NULL); |
---|
485 | } |
---|
486 | } |
---|
487 | } |
---|
488 | return (data->extData); |
---|
489 | } |
---|
490 | |
---|
491 | /** |
---|
492 | * xsltGetExtData: |
---|
493 | * @ctxt: an XSLT transformation context |
---|
494 | * @URI: the URI associated to the exension module |
---|
495 | * |
---|
496 | * Retrieve the data associated to the extension module in this given |
---|
497 | * transformation. |
---|
498 | * |
---|
499 | * Returns the pointer or NULL if not present |
---|
500 | */ |
---|
501 | void * |
---|
502 | xsltGetExtData(xsltTransformContextPtr ctxt, const xmlChar * URI) { |
---|
503 | xsltExtDataPtr data; |
---|
504 | |
---|
505 | if ((ctxt == NULL) || (URI == NULL)) |
---|
506 | return (NULL); |
---|
507 | if (ctxt->extInfos == NULL) { |
---|
508 | ctxt->extInfos = xmlHashCreate(10); |
---|
509 | if (ctxt->extInfos == NULL) |
---|
510 | return(NULL); |
---|
511 | data = NULL; |
---|
512 | } else { |
---|
513 | data = (xsltExtDataPtr) xmlHashLookup(ctxt->extInfos, URI); |
---|
514 | } |
---|
515 | if (data == NULL) { |
---|
516 | void *extData; |
---|
517 | xsltExtModulePtr module; |
---|
518 | |
---|
519 | module = xmlHashLookup(xsltExtensionsHash, URI); |
---|
520 | if (module == NULL) { |
---|
521 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
522 | xsltGenericDebug(xsltGenericDebugContext, |
---|
523 | "Not registered extension module: %s\n", URI); |
---|
524 | #endif |
---|
525 | return(NULL); |
---|
526 | } else { |
---|
527 | if (module->initFunc == NULL) |
---|
528 | return(NULL); |
---|
529 | |
---|
530 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
531 | xsltGenericDebug(xsltGenericDebugContext, |
---|
532 | "Initializing module: %s\n", URI); |
---|
533 | #endif |
---|
534 | |
---|
535 | extData = module->initFunc(ctxt, URI); |
---|
536 | if (extData == NULL) |
---|
537 | return(NULL); |
---|
538 | |
---|
539 | data = xsltNewExtData(module, extData); |
---|
540 | if (data == NULL) |
---|
541 | return (NULL); |
---|
542 | if (xmlHashAddEntry(ctxt->extInfos, URI, |
---|
543 | (void *) data) < 0) { |
---|
544 | xsltTransformError(ctxt, NULL, NULL, |
---|
545 | "Failed to register module data: %s\n", URI); |
---|
546 | if (module->shutdownFunc) |
---|
547 | module->shutdownFunc(ctxt, URI, extData); |
---|
548 | xsltFreeExtData(data); |
---|
549 | return(NULL); |
---|
550 | } |
---|
551 | } |
---|
552 | } |
---|
553 | return (data->extData); |
---|
554 | } |
---|
555 | |
---|
556 | typedef struct _xsltInitExtCtxt xsltInitExtCtxt; |
---|
557 | struct _xsltInitExtCtxt { |
---|
558 | xsltTransformContextPtr ctxt; |
---|
559 | int ret; |
---|
560 | }; |
---|
561 | |
---|
562 | /** |
---|
563 | * xsltInitCtxtExt: |
---|
564 | * @styleData: the registered stylesheet data for the module |
---|
565 | * @ctxt: the XSLT transformation context + the return value |
---|
566 | * @URI: the extension URI |
---|
567 | * |
---|
568 | * Initializes an extension module |
---|
569 | */ |
---|
570 | static void |
---|
571 | xsltInitCtxtExt (xsltExtDataPtr styleData, xsltInitExtCtxt *ctxt, |
---|
572 | const xmlChar *URI) { |
---|
573 | xsltExtModulePtr module; |
---|
574 | xsltExtDataPtr ctxtData; |
---|
575 | void *extData; |
---|
576 | |
---|
577 | if ((styleData == NULL) || (ctxt == NULL) || (URI == NULL) || |
---|
578 | (ctxt->ret == -1)) { |
---|
579 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
580 | xsltGenericDebug(xsltGenericDebugContext, |
---|
581 | "xsltInitCtxtExt: NULL param or error\n"); |
---|
582 | #endif |
---|
583 | return; |
---|
584 | } |
---|
585 | module = styleData->extModule; |
---|
586 | if ((module == NULL) || (module->initFunc == NULL)) { |
---|
587 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
588 | xsltGenericDebug(xsltGenericDebugContext, |
---|
589 | "xsltInitCtxtExt: no module or no initFunc\n"); |
---|
590 | #endif |
---|
591 | return; |
---|
592 | } |
---|
593 | |
---|
594 | extData = module->initFunc(ctxt->ctxt, URI); |
---|
595 | if (extData == NULL) { |
---|
596 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
597 | xsltGenericDebug(xsltGenericDebugContext, |
---|
598 | "xsltInitCtxtExt: no extData\n"); |
---|
599 | #endif |
---|
600 | } |
---|
601 | ctxtData = xsltNewExtData(module, extData); |
---|
602 | if (ctxtData == NULL) { |
---|
603 | ctxt->ret = -1; |
---|
604 | return; |
---|
605 | } |
---|
606 | |
---|
607 | if (ctxt->ctxt->extInfos == NULL) |
---|
608 | ctxt->ctxt->extInfos = xmlHashCreate(10); |
---|
609 | if (ctxt->ctxt->extInfos == NULL) { |
---|
610 | ctxt->ret = -1; |
---|
611 | return; |
---|
612 | } |
---|
613 | |
---|
614 | if (xmlHashAddEntry(ctxt->ctxt->extInfos, URI, ctxtData) < 0) { |
---|
615 | xsltGenericError(xsltGenericErrorContext, |
---|
616 | "Failed to register module data: %s\n", URI); |
---|
617 | if (module->shutdownFunc) |
---|
618 | module->shutdownFunc(ctxt->ctxt, URI, extData); |
---|
619 | xsltFreeExtData(ctxtData); |
---|
620 | ctxt->ret = -1; |
---|
621 | return; |
---|
622 | } |
---|
623 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
624 | xsltGenericDebug(xsltGenericDebugContext, "Registered module %s\n", |
---|
625 | URI); |
---|
626 | #endif |
---|
627 | ctxt->ret++; |
---|
628 | } |
---|
629 | |
---|
630 | /** |
---|
631 | * xsltInitCtxtExts: |
---|
632 | * @ctxt: an XSLT transformation context |
---|
633 | * |
---|
634 | * Initialize the set of modules with registered stylesheet data |
---|
635 | * |
---|
636 | * Returns the number of modules initialized or -1 in case of error |
---|
637 | */ |
---|
638 | int |
---|
639 | xsltInitCtxtExts(xsltTransformContextPtr ctxt) |
---|
640 | { |
---|
641 | xsltStylesheetPtr style; |
---|
642 | xsltInitExtCtxt ctx; |
---|
643 | |
---|
644 | if (ctxt == NULL) |
---|
645 | return (-1); |
---|
646 | |
---|
647 | style = ctxt->style; |
---|
648 | if (style == NULL) |
---|
649 | return (-1); |
---|
650 | |
---|
651 | ctx.ctxt = ctxt; |
---|
652 | ctx.ret = 0; |
---|
653 | |
---|
654 | while (style != NULL) { |
---|
655 | if (style->extInfos != NULL) { |
---|
656 | xmlHashScan(style->extInfos, |
---|
657 | (xmlHashScanner) xsltInitCtxtExt, &ctx); |
---|
658 | if (ctx.ret == -1) |
---|
659 | return(-1); |
---|
660 | } |
---|
661 | style = xsltNextImport(style); |
---|
662 | } |
---|
663 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
664 | xsltGenericDebug(xsltGenericDebugContext, "Registered %d modules\n", |
---|
665 | ctx.ret); |
---|
666 | #endif |
---|
667 | return (ctx.ret); |
---|
668 | } |
---|
669 | |
---|
670 | /** |
---|
671 | * xsltShutdownCtxtExt: |
---|
672 | * @data: the registered data for the module |
---|
673 | * @ctxt: the XSLT transformation context |
---|
674 | * @URI: the extension URI |
---|
675 | * |
---|
676 | * Shutdown an extension module loaded |
---|
677 | */ |
---|
678 | static void |
---|
679 | xsltShutdownCtxtExt(xsltExtDataPtr data, xsltTransformContextPtr ctxt, |
---|
680 | const xmlChar * URI) |
---|
681 | { |
---|
682 | xsltExtModulePtr module; |
---|
683 | |
---|
684 | if ((data == NULL) || (ctxt == NULL) || (URI == NULL)) |
---|
685 | return; |
---|
686 | module = data->extModule; |
---|
687 | if ((module == NULL) || (module->shutdownFunc == NULL)) |
---|
688 | return; |
---|
689 | |
---|
690 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
691 | xsltGenericDebug(xsltGenericDebugContext, |
---|
692 | "Shutting down module : %s\n", URI); |
---|
693 | #endif |
---|
694 | module->shutdownFunc(ctxt, URI, data->extData); |
---|
695 | xmlHashRemoveEntry(ctxt->extInfos, URI, |
---|
696 | (xmlHashDeallocator) xsltFreeExtData); |
---|
697 | } |
---|
698 | |
---|
699 | /** |
---|
700 | * xsltShutdownCtxtExts: |
---|
701 | * @ctxt: an XSLT transformation context |
---|
702 | * |
---|
703 | * Shutdown the set of modules loaded |
---|
704 | */ |
---|
705 | void |
---|
706 | xsltShutdownCtxtExts(xsltTransformContextPtr ctxt) |
---|
707 | { |
---|
708 | if (ctxt == NULL) |
---|
709 | return; |
---|
710 | if (ctxt->extInfos == NULL) |
---|
711 | return; |
---|
712 | xmlHashScan(ctxt->extInfos, (xmlHashScanner) xsltShutdownCtxtExt, ctxt); |
---|
713 | xmlHashFree(ctxt->extInfos, (xmlHashDeallocator) xsltFreeExtData); |
---|
714 | ctxt->extInfos = NULL; |
---|
715 | } |
---|
716 | |
---|
717 | /** |
---|
718 | * xsltShutdownExt: |
---|
719 | * @data: the registered data for the module |
---|
720 | * @ctxt: the XSLT stylesheet |
---|
721 | * @URI: the extension URI |
---|
722 | * |
---|
723 | * Shutdown an extension module loaded |
---|
724 | */ |
---|
725 | static void |
---|
726 | xsltShutdownExt(xsltExtDataPtr data, xsltStylesheetPtr style, |
---|
727 | const xmlChar * URI) |
---|
728 | { |
---|
729 | xsltExtModulePtr module; |
---|
730 | |
---|
731 | if ((data == NULL) || (style == NULL) || (URI == NULL)) |
---|
732 | return; |
---|
733 | module = data->extModule; |
---|
734 | if ((module == NULL) || (module->styleShutdownFunc == NULL)) |
---|
735 | return; |
---|
736 | |
---|
737 | #ifdef WITH_XSLT_DEBUG_EXTENSIONS |
---|
738 | xsltGenericDebug(xsltGenericDebugContext, |
---|
739 | "Shutting down module : %s\n", URI); |
---|
740 | #endif |
---|
741 | module->styleShutdownFunc(style, URI, data->extData); |
---|
742 | xmlHashRemoveEntry(style->extInfos, URI, |
---|
743 | (xmlHashDeallocator) xsltFreeExtData); |
---|
744 | } |
---|
745 | |
---|
746 | /** |
---|
747 | * xsltShutdownExts: |
---|
748 | * @style: an XSLT stylesheet |
---|
749 | * |
---|
750 | * Shutdown the set of modules loaded |
---|
751 | */ |
---|
752 | void |
---|
753 | xsltShutdownExts(xsltStylesheetPtr style) |
---|
754 | { |
---|
755 | if (style == NULL) |
---|
756 | return; |
---|
757 | if (style->extInfos == NULL) |
---|
758 | return; |
---|
759 | xmlHashScan(style->extInfos, (xmlHashScanner) xsltShutdownExt, style); |
---|
760 | xmlHashFree(style->extInfos, (xmlHashDeallocator) xsltFreeExtData); |
---|
761 | style->extInfos = NULL; |
---|
762 | } |
---|
763 | |
---|
764 | /** |
---|
765 | * xsltCheckExtPrefix: |
---|
766 | * @style: the stylesheet |
---|
767 | * @prefix: the namespace prefix (possibly NULL) |
---|
768 | * |
---|
769 | * Check if the given prefix is one of the declared extensions |
---|
770 | * |
---|
771 | * Returns 1 if this is an extension, 0 otherwise |
---|
772 | */ |
---|
773 | int |
---|
774 | xsltCheckExtPrefix(xsltStylesheetPtr style, const xmlChar *prefix) { |
---|
775 | xsltExtDefPtr cur; |
---|
776 | |
---|
777 | if ((style == NULL) || (style->nsDefs == NULL)) |
---|
778 | return(0); |
---|
779 | |
---|
780 | if (prefix == NULL) |
---|
781 | prefix = BAD_CAST "#default"; |
---|
782 | |
---|
783 | cur = (xsltExtDefPtr) style->nsDefs; |
---|
784 | while (cur != NULL) { |
---|
785 | if (xmlStrEqual(prefix, cur->prefix)) |
---|
786 | return(1); |
---|
787 | cur = cur->next; |
---|
788 | } |
---|
789 | return(0); |
---|
790 | } |
---|
791 | |
---|
792 | /** |
---|
793 | * xsltRegisterExtModuleFull: |
---|
794 | * @URI: URI associated to this module |
---|
795 | * @initFunc: the module initialization function |
---|
796 | * @shutdownFunc: the module shutdown function |
---|
797 | * @styleInitFunc: the module initialization function |
---|
798 | * @styleShutdownFunc: the module shutdown function |
---|
799 | * |
---|
800 | * Register an XSLT extension module to the library. |
---|
801 | * |
---|
802 | * Returns 0 if sucessful, -1 in case of error |
---|
803 | */ |
---|
804 | int |
---|
805 | xsltRegisterExtModuleFull(const xmlChar * URI, |
---|
806 | xsltExtInitFunction initFunc, |
---|
807 | xsltExtShutdownFunction shutdownFunc, |
---|
808 | xsltStyleExtInitFunction styleInitFunc, |
---|
809 | xsltStyleExtShutdownFunction styleShutdownFunc) |
---|
810 | { |
---|
811 | int ret; |
---|
812 | xsltExtModulePtr module; |
---|
813 | |
---|
814 | if ((URI == NULL) || (initFunc == NULL)) |
---|
815 | return (-1); |
---|
816 | if (xsltExtensionsHash == NULL) |
---|
817 | xsltExtensionsHash = xmlHashCreate(10); |
---|
818 | |
---|
819 | if (xsltExtensionsHash == NULL) |
---|
820 | return (-1); |
---|
821 | |
---|
822 | module = xmlHashLookup(xsltExtensionsHash, URI); |
---|
823 | if (module != NULL) { |
---|
824 | if ((module->initFunc == initFunc) && |
---|
825 | (module->shutdownFunc == shutdownFunc)) |
---|
826 | return (0); |
---|
827 | return (-1); |
---|
828 | } |
---|
829 | module = xsltNewExtModule(initFunc, shutdownFunc, |
---|
830 | styleInitFunc, styleShutdownFunc); |
---|
831 | if (module == NULL) |
---|
832 | return (-1); |
---|
833 | ret = xmlHashAddEntry(xsltExtensionsHash, URI, (void *) module); |
---|
834 | return (ret); |
---|
835 | } |
---|
836 | |
---|
837 | /** |
---|
838 | * xsltRegisterExtModule: |
---|
839 | * @URI: URI associated to this module |
---|
840 | * @initFunc: the module initialization function |
---|
841 | * @shutdownFunc: the module shutdown function |
---|
842 | * |
---|
843 | * Register an XSLT extension module to the library. |
---|
844 | * |
---|
845 | * Returns 0 if sucessful, -1 in case of error |
---|
846 | */ |
---|
847 | int |
---|
848 | xsltRegisterExtModule(const xmlChar * URI, |
---|
849 | xsltExtInitFunction initFunc, |
---|
850 | xsltExtShutdownFunction shutdownFunc) { |
---|
851 | return xsltRegisterExtModuleFull(URI, initFunc, shutdownFunc, |
---|
852 | NULL, NULL); |
---|
853 | } |
---|
854 | |
---|
855 | /** |
---|
856 | * xsltUnregisterExtModule: |
---|
857 | * @URI: URI associated to this module |
---|
858 | * |
---|
859 | * Unregister an XSLT extension module from the library. |
---|
860 | * |
---|
861 | * Returns 0 if sucessful, -1 in case of error |
---|
862 | */ |
---|
863 | int |
---|
864 | xsltUnregisterExtModule(const xmlChar * URI) |
---|
865 | { |
---|
866 | int ret; |
---|
867 | |
---|
868 | if (URI == NULL) |
---|
869 | return (-1); |
---|
870 | if (xsltExtensionsHash == NULL) |
---|
871 | return (-1); |
---|
872 | |
---|
873 | ret = |
---|
874 | xmlHashRemoveEntry(xsltExtensionsHash, URI, |
---|
875 | (xmlHashDeallocator) xsltFreeExtModule); |
---|
876 | return (ret); |
---|
877 | } |
---|
878 | |
---|
879 | /** |
---|
880 | * xsltUnregisterAllExtModules: |
---|
881 | * |
---|
882 | * Unregister all the XSLT extension module from the library. |
---|
883 | */ |
---|
884 | static void |
---|
885 | xsltUnregisterAllExtModules(void) |
---|
886 | { |
---|
887 | if (xsltExtensionsHash == NULL) |
---|
888 | return; |
---|
889 | |
---|
890 | xmlHashFree(xsltExtensionsHash, (xmlHashDeallocator) xsltFreeExtModule); |
---|
891 | xsltExtensionsHash = NULL; |
---|
892 | } |
---|
893 | |
---|
894 | /** |
---|
895 | * xsltXPathGetTransformContext: |
---|
896 | * @ctxt: an XPath transformation context |
---|
897 | * |
---|
898 | * Provides the XSLT transformation context from the XPath transformation |
---|
899 | * context. This is useful when an XPath function in the extension module |
---|
900 | * is called by the XPath interpreter and that the XSLT context is needed |
---|
901 | * for example to retrieve the associated data pertaining to this XSLT |
---|
902 | * transformation. |
---|
903 | * |
---|
904 | * Returns the XSLT transformation context or NULL in case of error. |
---|
905 | */ |
---|
906 | xsltTransformContextPtr |
---|
907 | xsltXPathGetTransformContext(xmlXPathParserContextPtr ctxt) |
---|
908 | { |
---|
909 | if ((ctxt == NULL) || (ctxt->context == NULL)) |
---|
910 | return(NULL); |
---|
911 | return(ctxt->context->extra); |
---|
912 | } |
---|
913 | |
---|
914 | /** |
---|
915 | * xsltRegisterExtModuleFunction: |
---|
916 | * @name: the function name |
---|
917 | * @URI: the function namespace URI |
---|
918 | * @function: the function callback |
---|
919 | * |
---|
920 | * Registers an extension module function. |
---|
921 | * |
---|
922 | * Returns 0 if successful, -1 in case of error. |
---|
923 | */ |
---|
924 | int |
---|
925 | xsltRegisterExtModuleFunction (const xmlChar *name, const xmlChar *URI, |
---|
926 | xmlXPathFunction function) { |
---|
927 | if ((name == NULL) || (URI == NULL) || (function == NULL)) |
---|
928 | return(-1); |
---|
929 | |
---|
930 | if (xsltFunctionsHash == NULL) |
---|
931 | xsltFunctionsHash = xmlHashCreate(10); |
---|
932 | if (xsltFunctionsHash == NULL) |
---|
933 | return(-1); |
---|
934 | |
---|
935 | xmlHashUpdateEntry2(xsltFunctionsHash, name, URI, |
---|
936 | (void *) function, NULL); |
---|
937 | |
---|
938 | return(0); |
---|
939 | } |
---|
940 | |
---|
941 | /** |
---|
942 | * xsltExtModuleFunctionLookup: |
---|
943 | * @name: the function name |
---|
944 | * @URI: the function namespace URI |
---|
945 | * |
---|
946 | * Looks up an extension module function |
---|
947 | * |
---|
948 | * Returns the function if found, NULL otherwise. |
---|
949 | */ |
---|
950 | xmlXPathFunction |
---|
951 | xsltExtModuleFunctionLookup (const xmlChar *name, const xmlChar *URI) { |
---|
952 | if ((xsltFunctionsHash == NULL) || (name == NULL) || (URI == NULL)) |
---|
953 | return(NULL); |
---|
954 | |
---|
955 | return (xmlXPathFunction) xmlHashLookup2(xsltFunctionsHash, name, URI); |
---|
956 | } |
---|
957 | |
---|
958 | /** |
---|
959 | * xsltUnregisterExtModuleFunction: |
---|
960 | * @name: the function name |
---|
961 | * @URI: the function namespace URI |
---|
962 | * |
---|
963 | * Unregisters an extension module function |
---|
964 | * |
---|
965 | * Returns 0 if successful, -1 in case of error. |
---|
966 | */ |
---|
967 | int |
---|
968 | xsltUnregisterExtModuleFunction (const xmlChar *name, |
---|
969 | const xmlChar *URI) { |
---|
970 | if ((xsltFunctionsHash == NULL) || (name == NULL) || (URI == NULL)) |
---|
971 | return(-1); |
---|
972 | |
---|
973 | return xmlHashRemoveEntry2 (xsltFunctionsHash, name, URI, NULL); |
---|
974 | } |
---|
975 | |
---|
976 | /** |
---|
977 | * xsltUnregisterAllExtModuleFunction: |
---|
978 | * |
---|
979 | * Unregisters all extension module function |
---|
980 | */ |
---|
981 | static void |
---|
982 | xsltUnregisterAllExtModuleFunction (void) { |
---|
983 | xmlHashFree(xsltFunctionsHash, NULL); |
---|
984 | xsltFunctionsHash = NULL; |
---|
985 | } |
---|
986 | |
---|
987 | |
---|
988 | /** |
---|
989 | * xsltNewElemPreComp: |
---|
990 | * @style: the XSLT stylesheet |
---|
991 | * @inst: the element node |
---|
992 | * @function: the transform function |
---|
993 | * |
---|
994 | * Creates and initializes an #xsltElemPreComp |
---|
995 | * |
---|
996 | * Returns the new and initialized #xsltElemPreComp |
---|
997 | */ |
---|
998 | xsltElemPreCompPtr |
---|
999 | xsltNewElemPreComp (xsltStylesheetPtr style, xmlNodePtr inst, |
---|
1000 | xsltTransformFunction function) { |
---|
1001 | xsltElemPreCompPtr cur; |
---|
1002 | |
---|
1003 | cur = (xsltElemPreCompPtr) xmlMalloc (sizeof(xsltElemPreComp)); |
---|
1004 | if (cur == NULL) { |
---|
1005 | xsltTransformError(NULL, style, NULL, |
---|
1006 | "xsltNewExtElement : malloc failed\n"); |
---|
1007 | return (NULL); |
---|
1008 | } |
---|
1009 | memset(cur, 0, sizeof(xsltElemPreComp)); |
---|
1010 | |
---|
1011 | xsltInitElemPreComp (cur, style, inst, function, |
---|
1012 | (xsltElemPreCompDeallocator) xmlFree); |
---|
1013 | |
---|
1014 | return (cur); |
---|
1015 | } |
---|
1016 | |
---|
1017 | /** |
---|
1018 | * xsltInitElemPreComp: |
---|
1019 | * @comp: an #xsltElemPreComp (or generally a derived structure) |
---|
1020 | * @style: the XSLT stylesheet |
---|
1021 | * @inst: the element node |
---|
1022 | * @function: the transform function |
---|
1023 | * @freeFunc: the @comp deallocator |
---|
1024 | * |
---|
1025 | * Initializes an existing #xsltElemPreComp structure. This is usefull |
---|
1026 | * when extending an #xsltElemPreComp to store precomputed data. |
---|
1027 | * This function MUST be called on any extension element precomputed |
---|
1028 | * data struct. |
---|
1029 | */ |
---|
1030 | void |
---|
1031 | xsltInitElemPreComp (xsltElemPreCompPtr comp, xsltStylesheetPtr style, |
---|
1032 | xmlNodePtr inst, xsltTransformFunction function, |
---|
1033 | xsltElemPreCompDeallocator freeFunc) { |
---|
1034 | comp->type = XSLT_FUNC_EXTENSION; |
---|
1035 | comp->func = function; |
---|
1036 | comp->inst = inst; |
---|
1037 | comp->free = freeFunc; |
---|
1038 | |
---|
1039 | comp->next = style->preComps; |
---|
1040 | style->preComps = comp; |
---|
1041 | } |
---|
1042 | |
---|
1043 | /** |
---|
1044 | * xsltPreComputeExtModuleElement: |
---|
1045 | * @style: the stylesheet |
---|
1046 | * @inst: the element node |
---|
1047 | * |
---|
1048 | * Precomputes an extension module element |
---|
1049 | * |
---|
1050 | * Returns the precomputed data |
---|
1051 | */ |
---|
1052 | xsltElemPreCompPtr |
---|
1053 | xsltPreComputeExtModuleElement (xsltStylesheetPtr style, |
---|
1054 | xmlNodePtr inst) { |
---|
1055 | xsltExtElementPtr ext; |
---|
1056 | xsltElemPreCompPtr comp = NULL; |
---|
1057 | |
---|
1058 | if ((style == NULL) || (inst == NULL) || |
---|
1059 | (inst->type != XML_ELEMENT_NODE) || (inst->ns == NULL)) |
---|
1060 | return (NULL); |
---|
1061 | |
---|
1062 | ext = (xsltExtElementPtr) |
---|
1063 | xmlHashLookup2 (xsltElementsHash, inst->name, |
---|
1064 | inst->ns->href); |
---|
1065 | if (ext == NULL) |
---|
1066 | return (NULL); |
---|
1067 | |
---|
1068 | if (ext->precomp != NULL) |
---|
1069 | comp = ext->precomp(style, inst, ext->transform); |
---|
1070 | if (comp == NULL) |
---|
1071 | comp = xsltNewElemPreComp (style, inst, ext->transform); |
---|
1072 | |
---|
1073 | return (comp); |
---|
1074 | } |
---|
1075 | |
---|
1076 | /** |
---|
1077 | * xsltRegisterExtModuleElement: |
---|
1078 | * @name: the element name |
---|
1079 | * @URI: the element namespace URI |
---|
1080 | * @precomp: the pre-computation callback |
---|
1081 | * @transform: the transformation callback |
---|
1082 | * |
---|
1083 | * Registers an extension module element. |
---|
1084 | * |
---|
1085 | * Returns 0 if successful, -1 in case of error. |
---|
1086 | */ |
---|
1087 | int |
---|
1088 | xsltRegisterExtModuleElement (const xmlChar *name, const xmlChar *URI, |
---|
1089 | xsltPreComputeFunction precomp, |
---|
1090 | xsltTransformFunction transform) { |
---|
1091 | xsltExtElementPtr ext; |
---|
1092 | |
---|
1093 | if ((name == NULL) || (URI == NULL) || (transform == NULL)) |
---|
1094 | return(-1); |
---|
1095 | |
---|
1096 | if (xsltElementsHash == NULL) |
---|
1097 | xsltElementsHash = xmlHashCreate(10); |
---|
1098 | if (xsltElementsHash == NULL) |
---|
1099 | return(-1); |
---|
1100 | |
---|
1101 | ext = xsltNewExtElement(precomp, transform); |
---|
1102 | if (ext == NULL) |
---|
1103 | return(-1); |
---|
1104 | |
---|
1105 | xmlHashUpdateEntry2(xsltElementsHash, name, URI, (void *) ext, |
---|
1106 | (xmlHashDeallocator) xsltFreeExtElement); |
---|
1107 | |
---|
1108 | return(0); |
---|
1109 | } |
---|
1110 | |
---|
1111 | /** |
---|
1112 | * xsltExtElementLookup: |
---|
1113 | * @ctxt: an XSLT process context |
---|
1114 | * @name: the element name |
---|
1115 | * @URI: the element namespace URI |
---|
1116 | * |
---|
1117 | * Looks up an extension element. @ctxt can be NULL to search only in |
---|
1118 | * module elements. |
---|
1119 | * |
---|
1120 | * Returns the element callback or NULL if not found |
---|
1121 | */ |
---|
1122 | xsltTransformFunction |
---|
1123 | xsltExtElementLookup (xsltTransformContextPtr ctxt, |
---|
1124 | const xmlChar *name, const xmlChar *URI) { |
---|
1125 | xsltTransformFunction ret; |
---|
1126 | |
---|
1127 | if ((name == NULL) || (URI == NULL)) |
---|
1128 | return(NULL); |
---|
1129 | |
---|
1130 | if ((ctxt != NULL) && (ctxt->extElements != NULL)) { |
---|
1131 | ret = (xsltTransformFunction) |
---|
1132 | xmlHashLookup2(ctxt->extElements, name, URI); |
---|
1133 | if (ret != NULL) |
---|
1134 | return(ret); |
---|
1135 | } |
---|
1136 | return xsltExtModuleElementLookup(name, URI); |
---|
1137 | } |
---|
1138 | |
---|
1139 | /** |
---|
1140 | * xsltExtModuleElementLookup: |
---|
1141 | * @name: the element name |
---|
1142 | * @URI: the element namespace URI |
---|
1143 | * |
---|
1144 | * Looks up an extension module element |
---|
1145 | * |
---|
1146 | * Returns the callback function if found, NULL otherwise. |
---|
1147 | */ |
---|
1148 | xsltTransformFunction |
---|
1149 | xsltExtModuleElementLookup (const xmlChar *name, const xmlChar *URI) { |
---|
1150 | xsltExtElementPtr ext; |
---|
1151 | |
---|
1152 | if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL)) |
---|
1153 | return(NULL); |
---|
1154 | |
---|
1155 | ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI); |
---|
1156 | |
---|
1157 | if (ext == NULL) |
---|
1158 | return(NULL); |
---|
1159 | return(ext->transform); |
---|
1160 | } |
---|
1161 | |
---|
1162 | /** |
---|
1163 | * xsltExtModuleElementPreComputeLookup: |
---|
1164 | * @name: the element name |
---|
1165 | * @URI: the element namespace URI |
---|
1166 | * |
---|
1167 | * Looks up an extension module element pre-computation function |
---|
1168 | * |
---|
1169 | * Returns the callback function if found, NULL otherwise. |
---|
1170 | */ |
---|
1171 | xsltPreComputeFunction |
---|
1172 | xsltExtModuleElementPreComputeLookup (const xmlChar *name, |
---|
1173 | const xmlChar *URI) { |
---|
1174 | xsltExtElementPtr ext; |
---|
1175 | |
---|
1176 | if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL)) |
---|
1177 | return(NULL); |
---|
1178 | |
---|
1179 | ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI); |
---|
1180 | |
---|
1181 | if (ext == NULL) |
---|
1182 | return(NULL); |
---|
1183 | return(ext->precomp); |
---|
1184 | } |
---|
1185 | |
---|
1186 | /** |
---|
1187 | * xsltUnregisterExtModuleElement: |
---|
1188 | * @name: the element name |
---|
1189 | * @URI: the element namespace URI |
---|
1190 | * |
---|
1191 | * Unregisters an extension module element |
---|
1192 | * |
---|
1193 | * Returns 0 if successful, -1 in case of error. |
---|
1194 | */ |
---|
1195 | int |
---|
1196 | xsltUnregisterExtModuleElement (const xmlChar *name, |
---|
1197 | const xmlChar *URI) { |
---|
1198 | if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL)) |
---|
1199 | return(-1); |
---|
1200 | |
---|
1201 | return xmlHashRemoveEntry2 (xsltElementsHash, name, URI, |
---|
1202 | (xmlHashDeallocator) xsltFreeExtElement); |
---|
1203 | } |
---|
1204 | |
---|
1205 | /** |
---|
1206 | * xsltUnregisterAllExtModuleElement: |
---|
1207 | * |
---|
1208 | * Unregisters all extension module element |
---|
1209 | */ |
---|
1210 | static void |
---|
1211 | xsltUnregisterAllExtModuleElement (void) { |
---|
1212 | xmlHashFree(xsltElementsHash, (xmlHashDeallocator) xsltFreeExtElement); |
---|
1213 | xsltElementsHash = NULL; |
---|
1214 | } |
---|
1215 | |
---|
1216 | /** |
---|
1217 | * xsltRegisterExtModuleTopLevel: |
---|
1218 | * @name: the top-level element name |
---|
1219 | * @URI: the top-level element namespace URI |
---|
1220 | * @function: the top-level element callback |
---|
1221 | * |
---|
1222 | * Registers an extension module top-level element. |
---|
1223 | * |
---|
1224 | * Returns 0 if successful, -1 in case of error. |
---|
1225 | */ |
---|
1226 | int |
---|
1227 | xsltRegisterExtModuleTopLevel (const xmlChar *name, const xmlChar *URI, |
---|
1228 | xsltTopLevelFunction function) { |
---|
1229 | if ((name == NULL) || (URI == NULL) || (function == NULL)) |
---|
1230 | return(-1); |
---|
1231 | |
---|
1232 | if (xsltTopLevelsHash == NULL) |
---|
1233 | xsltTopLevelsHash = xmlHashCreate(10); |
---|
1234 | if (xsltTopLevelsHash == NULL) |
---|
1235 | return(-1); |
---|
1236 | |
---|
1237 | xmlHashUpdateEntry2(xsltTopLevelsHash, name, URI, |
---|
1238 | (void *) function, NULL); |
---|
1239 | |
---|
1240 | return(0); |
---|
1241 | } |
---|
1242 | |
---|
1243 | /** |
---|
1244 | * xsltExtModuleTopLevelLookup: |
---|
1245 | * @name: the top-level element name |
---|
1246 | * @URI: the top-level element namespace URI |
---|
1247 | * |
---|
1248 | * Looks up an extension module top-level element |
---|
1249 | * |
---|
1250 | * Returns the callback function if found, NULL otherwise. |
---|
1251 | */ |
---|
1252 | xsltTopLevelFunction |
---|
1253 | xsltExtModuleTopLevelLookup (const xmlChar *name, const xmlChar *URI) { |
---|
1254 | if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL)) |
---|
1255 | return(NULL); |
---|
1256 | |
---|
1257 | return((xsltTopLevelFunction) |
---|
1258 | xmlHashLookup2(xsltTopLevelsHash, name, URI)); |
---|
1259 | } |
---|
1260 | |
---|
1261 | /** |
---|
1262 | * xsltUnregisterExtModuleTopLevel: |
---|
1263 | * @name: the top-level element name |
---|
1264 | * @URI: the top-level element namespace URI |
---|
1265 | * |
---|
1266 | * Unregisters an extension module top-level element |
---|
1267 | * |
---|
1268 | * Returns 0 if successful, -1 in case of error. |
---|
1269 | */ |
---|
1270 | int |
---|
1271 | xsltUnregisterExtModuleTopLevel (const xmlChar *name, |
---|
1272 | const xmlChar *URI) { |
---|
1273 | if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL)) |
---|
1274 | return(-1); |
---|
1275 | |
---|
1276 | return xmlHashRemoveEntry2 (xsltTopLevelsHash, name, URI, NULL); |
---|
1277 | } |
---|
1278 | |
---|
1279 | /** |
---|
1280 | * xsltUnregisterAllExtModuleTopLevel: |
---|
1281 | * |
---|
1282 | * Unregisters all extension module function |
---|
1283 | */ |
---|
1284 | static void |
---|
1285 | xsltUnregisterAllExtModuleTopLevel (void) { |
---|
1286 | xmlHashFree(xsltTopLevelsHash, NULL); |
---|
1287 | xsltTopLevelsHash = NULL; |
---|
1288 | } |
---|
1289 | |
---|
1290 | |
---|
1291 | /************************************************************************ |
---|
1292 | * * |
---|
1293 | * Test module http://xmlsoft.org/XSLT/ * |
---|
1294 | * * |
---|
1295 | ************************************************************************/ |
---|
1296 | |
---|
1297 | /************************************************************************ |
---|
1298 | * * |
---|
1299 | * Test of the extension module API * |
---|
1300 | * * |
---|
1301 | ************************************************************************/ |
---|
1302 | |
---|
1303 | static xmlChar *testData = NULL; |
---|
1304 | static xmlChar *testStyleData = NULL; |
---|
1305 | |
---|
1306 | /** |
---|
1307 | * xsltExtFunctionTest: |
---|
1308 | * @ctxt: the XPath Parser context |
---|
1309 | * @nargs: the number of arguments |
---|
1310 | * |
---|
1311 | * function libxslt:test() for testing the extensions support. |
---|
1312 | */ |
---|
1313 | static void |
---|
1314 | xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, int nargs ATTRIBUTE_UNUSED) |
---|
1315 | { |
---|
1316 | xsltTransformContextPtr tctxt; |
---|
1317 | void *data = NULL; |
---|
1318 | |
---|
1319 | tctxt = xsltXPathGetTransformContext(ctxt); |
---|
1320 | |
---|
1321 | if (testData == NULL) { |
---|
1322 | xsltGenericDebug(xsltGenericDebugContext, |
---|
1323 | "xsltExtFunctionTest: not initialized," |
---|
1324 | " calling xsltGetExtData\n"); |
---|
1325 | data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL); |
---|
1326 | if (data == NULL) { |
---|
1327 | xsltTransformError(tctxt, NULL, NULL, |
---|
1328 | "xsltExtElementTest: not initialized\n"); |
---|
1329 | return; |
---|
1330 | } |
---|
1331 | } |
---|
1332 | if (tctxt == NULL) { |
---|
1333 | xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, |
---|
1334 | "xsltExtFunctionTest: failed to get the transformation context\n"); |
---|
1335 | return; |
---|
1336 | } |
---|
1337 | if (data == NULL) |
---|
1338 | data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL); |
---|
1339 | if (data == NULL) { |
---|
1340 | xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, |
---|
1341 | "xsltExtFunctionTest: failed to get module data\n"); |
---|
1342 | return; |
---|
1343 | } |
---|
1344 | if (data != testData) { |
---|
1345 | xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, |
---|
1346 | "xsltExtFunctionTest: got wrong module data\n"); |
---|
1347 | return; |
---|
1348 | } |
---|
1349 | #ifdef WITH_XSLT_DEBUG_FUNCTION |
---|
1350 | xsltGenericDebug(xsltGenericDebugContext, |
---|
1351 | "libxslt:test() called with %d args\n", nargs); |
---|
1352 | #endif |
---|
1353 | } |
---|
1354 | |
---|
1355 | /** |
---|
1356 | * xsltExtElementPreCompTest: |
---|
1357 | * @style: the stylesheet |
---|
1358 | * @inst: the instruction in the stylesheet |
---|
1359 | * |
---|
1360 | * Process a libxslt:test node |
---|
1361 | */ |
---|
1362 | static xsltElemPreCompPtr |
---|
1363 | xsltExtElementPreCompTest(xsltStylesheetPtr style, xmlNodePtr inst, |
---|
1364 | xsltTransformFunction function) { |
---|
1365 | xsltElemPreCompPtr ret; |
---|
1366 | |
---|
1367 | if (style == NULL) { |
---|
1368 | xsltTransformError(NULL, NULL, inst, |
---|
1369 | "xsltExtElementTest: no transformation context\n"); |
---|
1370 | return (NULL); |
---|
1371 | } |
---|
1372 | if (testStyleData == NULL) { |
---|
1373 | xsltGenericDebug(xsltGenericDebugContext, |
---|
1374 | "xsltExtElementPreCompTest: not initialized," |
---|
1375 | " calling xsltStyleGetExtData\n"); |
---|
1376 | xsltStyleGetExtData(style, (const xmlChar *) XSLT_DEFAULT_URL); |
---|
1377 | if (testStyleData == NULL) { |
---|
1378 | xsltTransformError(NULL, style, inst, |
---|
1379 | "xsltExtElementPreCompTest: not initialized\n"); |
---|
1380 | if (style != NULL) style->errors++; |
---|
1381 | return (NULL); |
---|
1382 | } |
---|
1383 | } |
---|
1384 | if (inst == NULL) { |
---|
1385 | xsltTransformError(NULL, style, inst, |
---|
1386 | "xsltExtElementPreCompTest: no instruction\n"); |
---|
1387 | if (style != NULL) style->errors++; |
---|
1388 | return (NULL); |
---|
1389 | } |
---|
1390 | ret = xsltNewElemPreComp (style, inst, function); |
---|
1391 | return (ret); |
---|
1392 | } |
---|
1393 | |
---|
1394 | /** |
---|
1395 | * xsltExtElementTest: |
---|
1396 | * @ctxt: an XSLT processing context |
---|
1397 | * @node: The current node |
---|
1398 | * @inst: the instruction in the stylesheet |
---|
1399 | * @comp: precomputed informations |
---|
1400 | * |
---|
1401 | * Process a libxslt:test node |
---|
1402 | */ |
---|
1403 | static void |
---|
1404 | xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node, |
---|
1405 | xmlNodePtr inst, |
---|
1406 | xsltElemPreCompPtr comp ATTRIBUTE_UNUSED) |
---|
1407 | { |
---|
1408 | xmlNodePtr commentNode; |
---|
1409 | |
---|
1410 | if (testData == NULL) { |
---|
1411 | xsltGenericDebug(xsltGenericDebugContext, |
---|
1412 | "xsltExtElementTest: not initialized," |
---|
1413 | " calling xsltGetExtData\n"); |
---|
1414 | xsltGetExtData(ctxt, (const xmlChar *) XSLT_DEFAULT_URL); |
---|
1415 | if (testData == NULL) { |
---|
1416 | xsltTransformError(ctxt, NULL, inst, |
---|
1417 | "xsltExtElementTest: not initialized\n"); |
---|
1418 | return; |
---|
1419 | } |
---|
1420 | } |
---|
1421 | if (ctxt == NULL) { |
---|
1422 | xsltTransformError(ctxt, NULL, inst, |
---|
1423 | "xsltExtElementTest: no transformation context\n"); |
---|
1424 | return; |
---|
1425 | } |
---|
1426 | if (node == NULL) { |
---|
1427 | xsltTransformError(ctxt, NULL, inst, |
---|
1428 | "xsltExtElementTest: no current node\n"); |
---|
1429 | return; |
---|
1430 | } |
---|
1431 | if (inst == NULL) { |
---|
1432 | xsltTransformError(ctxt, NULL, inst, |
---|
1433 | "xsltExtElementTest: no instruction\n"); |
---|
1434 | return; |
---|
1435 | } |
---|
1436 | if (ctxt->insert == NULL) { |
---|
1437 | xsltTransformError(ctxt, NULL, inst, |
---|
1438 | "xsltExtElementTest: no insertion point\n"); |
---|
1439 | return; |
---|
1440 | } |
---|
1441 | commentNode = |
---|
1442 | xmlNewComment((const xmlChar *) |
---|
1443 | "libxslt:test element test worked"); |
---|
1444 | xmlAddChild(ctxt->insert, commentNode); |
---|
1445 | } |
---|
1446 | |
---|
1447 | /** |
---|
1448 | * xsltExtInitTest: |
---|
1449 | * @ctxt: an XSLT transformation context |
---|
1450 | * @URI: the namespace URI for the extension |
---|
1451 | * |
---|
1452 | * A function called at initialization time of an XSLT extension module |
---|
1453 | * |
---|
1454 | * Returns a pointer to the module specific data for this transformation |
---|
1455 | */ |
---|
1456 | static void * |
---|
1457 | xsltExtInitTest(xsltTransformContextPtr ctxt, const xmlChar * URI) { |
---|
1458 | if (testStyleData == NULL) { |
---|
1459 | xsltGenericDebug(xsltGenericErrorContext, |
---|
1460 | "xsltExtInitTest: not initialized," |
---|
1461 | " calling xsltStyleGetExtData\n"); |
---|
1462 | xsltStyleGetExtData(ctxt->style, URI); |
---|
1463 | if (testStyleData == NULL) { |
---|
1464 | xsltTransformError(ctxt, NULL, NULL, |
---|
1465 | "xsltExtInitTest: not initialized\n"); |
---|
1466 | return (NULL); |
---|
1467 | } |
---|
1468 | } |
---|
1469 | if (testData != NULL) { |
---|
1470 | xsltTransformError(ctxt, NULL, NULL, |
---|
1471 | "xsltExtInitTest: already initialized\n"); |
---|
1472 | return (NULL); |
---|
1473 | } |
---|
1474 | testData = (void *) "test data"; |
---|
1475 | xsltGenericDebug(xsltGenericDebugContext, |
---|
1476 | "Registered test module : %s\n", URI); |
---|
1477 | return (testData); |
---|
1478 | } |
---|
1479 | |
---|
1480 | |
---|
1481 | /** |
---|
1482 | * xsltExtShutdownTest: |
---|
1483 | * @ctxt: an XSLT transformation context |
---|
1484 | * @URI: the namespace URI for the extension |
---|
1485 | * @data: the data associated to this module |
---|
1486 | * |
---|
1487 | * A function called at shutdown time of an XSLT extension module |
---|
1488 | */ |
---|
1489 | static void |
---|
1490 | xsltExtShutdownTest(xsltTransformContextPtr ctxt, |
---|
1491 | const xmlChar * URI, void *data) { |
---|
1492 | if (testData == NULL) { |
---|
1493 | xsltTransformError(ctxt, NULL, NULL, |
---|
1494 | "xsltExtShutdownTest: not initialized\n"); |
---|
1495 | return; |
---|
1496 | } |
---|
1497 | if (data != testData) { |
---|
1498 | xsltTransformError(ctxt, NULL, NULL, |
---|
1499 | "xsltExtShutdownTest: wrong data\n"); |
---|
1500 | } |
---|
1501 | testData = NULL; |
---|
1502 | xsltGenericDebug(xsltGenericDebugContext, |
---|
1503 | "Unregistered test module : %s\n", URI); |
---|
1504 | } |
---|
1505 | /** |
---|
1506 | * xsltExtStyleInitTest: |
---|
1507 | * @style: an XSLT stylesheet |
---|
1508 | * @URI: the namespace URI for the extension |
---|
1509 | * |
---|
1510 | * A function called at initialization time of an XSLT extension module |
---|
1511 | * |
---|
1512 | * Returns a pointer to the module specific data for this transformation |
---|
1513 | */ |
---|
1514 | static void * |
---|
1515 | xsltExtStyleInitTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED, |
---|
1516 | const xmlChar * URI) |
---|
1517 | { |
---|
1518 | if (testStyleData != NULL) { |
---|
1519 | xsltTransformError(NULL, NULL, NULL, |
---|
1520 | "xsltExtInitTest: already initialized\n"); |
---|
1521 | return (NULL); |
---|
1522 | } |
---|
1523 | testStyleData = (void *) "test data"; |
---|
1524 | xsltGenericDebug(xsltGenericDebugContext, |
---|
1525 | "Registered test module : %s\n", URI); |
---|
1526 | return (testStyleData); |
---|
1527 | } |
---|
1528 | |
---|
1529 | |
---|
1530 | /** |
---|
1531 | * xsltExtStyleShutdownTest: |
---|
1532 | * @style: an XSLT stylesheet |
---|
1533 | * @URI: the namespace URI for the extension |
---|
1534 | * @data: the data associated to this module |
---|
1535 | * |
---|
1536 | * A function called at shutdown time of an XSLT extension module |
---|
1537 | */ |
---|
1538 | static void |
---|
1539 | xsltExtStyleShutdownTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED, |
---|
1540 | const xmlChar * URI, void *data) { |
---|
1541 | if (testStyleData == NULL) { |
---|
1542 | xsltGenericError(xsltGenericErrorContext, |
---|
1543 | "xsltExtShutdownTest: not initialized\n"); |
---|
1544 | return; |
---|
1545 | } |
---|
1546 | if (data != testStyleData) { |
---|
1547 | xsltTransformError(NULL, NULL, NULL, |
---|
1548 | "xsltExtShutdownTest: wrong data\n"); |
---|
1549 | } |
---|
1550 | testStyleData = NULL; |
---|
1551 | xsltGenericDebug(xsltGenericDebugContext, |
---|
1552 | "Unregistered test module : %s\n", URI); |
---|
1553 | } |
---|
1554 | |
---|
1555 | /** |
---|
1556 | * xsltRegisterTestModule: |
---|
1557 | * |
---|
1558 | * Registers the test module |
---|
1559 | */ |
---|
1560 | void |
---|
1561 | xsltRegisterTestModule (void) { |
---|
1562 | xsltRegisterExtModuleFull((const xmlChar *) XSLT_DEFAULT_URL, |
---|
1563 | xsltExtInitTest, xsltExtShutdownTest, |
---|
1564 | xsltExtStyleInitTest, |
---|
1565 | xsltExtStyleShutdownTest); |
---|
1566 | xsltRegisterExtModuleFunction((const xmlChar *) "test", |
---|
1567 | (const xmlChar *) XSLT_DEFAULT_URL, |
---|
1568 | xsltExtFunctionTest); |
---|
1569 | xsltRegisterExtModuleElement((const xmlChar *) "test", |
---|
1570 | (const xmlChar *) XSLT_DEFAULT_URL, |
---|
1571 | xsltExtElementPreCompTest , |
---|
1572 | xsltExtElementTest); |
---|
1573 | } |
---|
1574 | |
---|
1575 | /** |
---|
1576 | * xsltCleanupGlobals: |
---|
1577 | * |
---|
1578 | * Unregister all global variables set up by the XSLT library |
---|
1579 | */ |
---|
1580 | void |
---|
1581 | xsltCleanupGlobals(void) |
---|
1582 | { |
---|
1583 | xsltUnregisterAllExtModules(); |
---|
1584 | xsltUnregisterAllExtModuleFunction(); |
---|
1585 | xsltUnregisterAllExtModuleElement(); |
---|
1586 | xsltUnregisterAllExtModuleTopLevel(); |
---|
1587 | } |
---|
1588 | |
---|
1589 | static void |
---|
1590 | xsltDebugDumpExtensionsCallback(void* function ATTRIBUTE_UNUSED, |
---|
1591 | FILE *output, const xmlChar* name, |
---|
1592 | const xmlChar* URI, |
---|
1593 | const xmlChar* not_used ATTRIBUTE_UNUSED) { |
---|
1594 | if (!name||!URI) |
---|
1595 | return; |
---|
1596 | fprintf(output,"{%s}%s\n",URI,name); |
---|
1597 | } |
---|
1598 | |
---|
1599 | /** |
---|
1600 | * xsltDebugDumpExtensions: |
---|
1601 | * @output: the FILE * for the output, if NULL stdout is used |
---|
1602 | * |
---|
1603 | * Dumps a list of the registered XSLT extension functions and elements |
---|
1604 | */ |
---|
1605 | void |
---|
1606 | xsltDebugDumpExtensions(FILE * output) |
---|
1607 | { |
---|
1608 | if (output == NULL) |
---|
1609 | output = stdout; |
---|
1610 | fprintf(output,"Registered XSLT Extensions\n--------------------------\n"); |
---|
1611 | if (!xsltFunctionsHash) |
---|
1612 | fprintf(output,"No registered extension functions\n"); |
---|
1613 | else { |
---|
1614 | fprintf(output,"Registered Extension Functions:\n"); |
---|
1615 | xmlHashScanFull(xsltFunctionsHash,(xmlHashScannerFull)xsltDebugDumpExtensionsCallback,output); |
---|
1616 | } |
---|
1617 | if (!xsltElementsHash) |
---|
1618 | fprintf(output,"\nNo registered extension elements\n"); |
---|
1619 | else { |
---|
1620 | fprintf(output,"\nRegistered Extension Elements:\n"); |
---|
1621 | xmlHashScanFull(xsltElementsHash,(xmlHashScannerFull)xsltDebugDumpExtensionsCallback,output); |
---|
1622 | } |
---|
1623 | |
---|
1624 | } |
---|
1625 | |
---|