2 * extensions.c: Implemetation of the extensions support
5 * http://www.w3.org/TR/1999/REC-xslt-19991116
7 * See Copyright for the status of this software.
16 #include <libxml/xmlmemory.h>
17 #include <libxml/tree.h>
18 #include <libxml/hash.h>
19 #include <libxml/xmlerror.h>
20 #include <libxml/parserInternals.h>
21 #include <libxml/xpathInternals.h>
23 #include "xsltInternals.h"
24 #include "xsltutils.h"
26 #include "extensions.h"
28 #ifdef WITH_XSLT_DEBUG
29 #define WITH_XSLT_DEBUG_EXTENSIONS
32 /************************************************************************
34 * Private Types and Globals *
36 ************************************************************************/
38 typedef struct _xsltExtDef xsltExtDef;
39 typedef xsltExtDef *xsltExtDefPtr;
41 struct _xsltExtDef *next;
47 typedef struct _xsltExtModule xsltExtModule;
48 typedef xsltExtModule *xsltExtModulePtr;
49 struct _xsltExtModule {
50 xsltExtInitFunction initFunc;
51 xsltExtShutdownFunction shutdownFunc;
52 xsltStyleExtInitFunction styleInitFunc;
53 xsltStyleExtShutdownFunction styleShutdownFunc;
56 typedef struct _xsltExtData xsltExtData;
57 typedef xsltExtData *xsltExtDataPtr;
59 xsltExtModulePtr extModule;
63 typedef struct _xsltExtElement xsltExtElement;
64 typedef xsltExtElement *xsltExtElementPtr;
65 struct _xsltExtElement {
66 xsltPreComputeFunction precomp;
67 xsltTransformFunction transform;
70 static xmlHashTablePtr xsltExtensionsHash = NULL;
71 static xmlHashTablePtr xsltFunctionsHash = NULL;
72 static xmlHashTablePtr xsltElementsHash = NULL;
73 static xmlHashTablePtr xsltTopLevelsHash = NULL;
75 /************************************************************************
79 ************************************************************************/
83 * @prefix: the extension prefix
84 * @URI: the namespace URI
86 * Create a new XSLT ExtDef
88 * Returns the newly allocated xsltExtDefPtr or NULL in case of error
91 xsltNewExtDef(const xmlChar * prefix, const xmlChar * URI)
95 cur = (xsltExtDefPtr) xmlMalloc(sizeof(xsltExtDef));
97 xsltPrintErrorContext(NULL, NULL, NULL);
98 xsltGenericError(xsltGenericErrorContext,
99 "xsltNewExtDef : malloc failed\n");
102 memset(cur, 0, sizeof(xsltExtDef));
104 cur->prefix = xmlStrdup(prefix);
106 cur->URI = xmlStrdup(URI);
112 * @extensiond: an XSLT extension definition
114 * Free up the memory allocated by @extensiond
117 xsltFreeExtDef(xsltExtDefPtr extensiond) {
118 if (extensiond == NULL)
120 if (extensiond->prefix != NULL)
121 xmlFree(extensiond->prefix);
122 if (extensiond->URI != NULL)
123 xmlFree(extensiond->URI);
128 * xsltFreeExtDefList:
129 * @extensiond: an XSLT extension definition list
131 * Free up the memory allocated by all the elements of @extensiond
134 xsltFreeExtDefList(xsltExtDefPtr extensiond) {
137 while (extensiond != NULL) {
139 extensiond = extensiond->next;
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
151 * Create a new XSLT extension module
153 * Returns the newly allocated xsltExtModulePtr or NULL in case of error
155 static xsltExtModulePtr
156 xsltNewExtModule(xsltExtInitFunction initFunc,
157 xsltExtShutdownFunction shutdownFunc,
158 xsltStyleExtInitFunction styleInitFunc,
159 xsltStyleExtShutdownFunction styleShutdownFunc)
161 xsltExtModulePtr cur;
163 cur = (xsltExtModulePtr) xmlMalloc(sizeof(xsltExtModule));
165 xsltPrintErrorContext(NULL, NULL, NULL);
166 xsltGenericError(xsltGenericErrorContext,
167 "xsltNewExtModule : malloc failed\n");
170 cur->initFunc = initFunc;
171 cur->shutdownFunc = shutdownFunc;
172 cur->styleInitFunc = styleInitFunc;
173 cur->styleShutdownFunc = styleShutdownFunc;
179 * @ext: an XSLT extension module
181 * Free up the memory allocated by @ext
184 xsltFreeExtModule(xsltExtModulePtr ext) {
192 * @extModule: the module
193 * @extData: the associated data
195 * Create a new XSLT extension module data wrapper
197 * Returns the newly allocated xsltExtDataPtr or NULL in case of error
199 static xsltExtDataPtr
200 xsltNewExtData(xsltExtModulePtr extModule, void *extData)
204 if (extModule == NULL)
206 cur = (xsltExtDataPtr) xmlMalloc(sizeof(xsltExtData));
208 xsltPrintErrorContext(NULL, NULL, NULL);
209 xsltGenericError(xsltGenericErrorContext,
210 "xsltNewExtData : malloc failed\n");
213 cur->extModule = extModule;
214 cur->extData = extData;
220 * @ext: an XSLT extension module data wrapper
222 * Free up the memory allocated by @ext
225 xsltFreeExtData(xsltExtDataPtr ext) {
233 * @precomp: the pre-computation function
234 * @transform: the transformation function
236 * Create a new XSLT extension element
238 * Returns the newly allocated xsltExtElementPtr or NULL in case of
241 static xsltExtElementPtr
242 xsltNewExtElement (xsltPreComputeFunction precomp,
243 xsltTransformFunction transform) {
244 xsltExtElementPtr cur;
246 if (transform == NULL)
249 cur = (xsltExtElementPtr) xmlMalloc(sizeof(xsltExtElement));
251 xsltPrintErrorContext(NULL, NULL, NULL);
252 xsltGenericError(xsltGenericErrorContext,
253 "xsltNewExtElement : malloc failed\n");
256 cur->precomp = precomp;
257 cur->transform = transform;
262 * xsltFreeExtElement:
263 * @ext: an XSLT extension element
265 * Frees up the memory allocated by @ext
268 xsltFreeExtElement (xsltExtElementPtr ext) {
275 /************************************************************************
277 * The stylesheet extension prefixes handling *
279 ************************************************************************/
284 * @style: an XSLT stylesheet
286 * Free up the memory used by XSLT extensions in a stylesheet
289 xsltFreeExts(xsltStylesheetPtr style) {
290 if (style->nsDefs != NULL)
291 xsltFreeExtDefList((xsltExtDefPtr) style->nsDefs);
295 * xsltRegisterExtPrefix:
296 * @style: an XSLT stylesheet
297 * @prefix: the prefix used
298 * @URI: the URI associated to the extension
300 * Registers an extension namespace
302 * Returns 0 in case of success, -1 in case of failure
305 xsltRegisterExtPrefix(xsltStylesheetPtr style,
306 const xmlChar *prefix, const xmlChar *URI) {
307 xsltExtDefPtr def, ret;
309 if ((style == NULL) || (prefix == NULL) | (URI == NULL))
312 def = (xsltExtDefPtr) style->nsDefs;
313 while (def != NULL) {
314 if (xmlStrEqual(prefix, def->prefix))
318 ret = xsltNewExtDef(prefix, URI);
321 ret->next = (xsltExtDefPtr) style->nsDefs;
326 /************************************************************************
328 * The extensions modules interfaces *
330 ************************************************************************/
333 * xsltRegisterExtFunction:
334 * @ctxt: an XSLT transformation context
335 * @name: the name of the element
336 * @URI: the URI associated to the element
337 * @function: the actual implementation which should be called
339 * Registers an extension function
341 * Returns 0 in case of success, -1 in case of failure
344 xsltRegisterExtFunction(xsltTransformContextPtr ctxt, const xmlChar *name,
345 const xmlChar *URI, xmlXPathFunction function) {
346 if ((ctxt == NULL) || (name == NULL) ||
347 (URI == NULL) || (function == NULL))
349 if (ctxt->xpathCtxt != NULL) {
350 xmlXPathRegisterFuncNS(ctxt->xpathCtxt, name, URI, function);
352 if (ctxt->extFunctions == NULL)
353 ctxt->extFunctions = xmlHashCreate(10);
354 if (ctxt->extFunctions == NULL)
356 return(xmlHashAddEntry2(ctxt->extFunctions, name, URI, (void *) function));
360 * xsltRegisterExtElement:
361 * @ctxt: an XSLT transformation context
362 * @name: the name of the element
363 * @URI: the URI associated to the element
364 * @function: the actual implementation which should be called
366 * Registers an extension element
368 * Returns 0 in case of success, -1 in case of failure
371 xsltRegisterExtElement(xsltTransformContextPtr ctxt, const xmlChar *name,
372 const xmlChar *URI, xsltTransformFunction function) {
373 if ((ctxt == NULL) || (name == NULL) ||
374 (URI == NULL) || (function == NULL))
376 if (ctxt->extElements == NULL)
377 ctxt->extElements = xmlHashCreate(10);
378 if (ctxt->extElements == NULL)
380 return(xmlHashAddEntry2(ctxt->extElements, name, URI, (void *) function));
385 * @ctxt: an XSLT transformation context
387 * Free the XSLT extension data
390 xsltFreeCtxtExts(xsltTransformContextPtr ctxt) {
391 if (ctxt->extElements != NULL)
392 xmlHashFree(ctxt->extElements, NULL);
393 if (ctxt->extFunctions != NULL)
394 xmlHashFree(ctxt->extFunctions, NULL);
398 * xsltStyleGetExtData:
399 * @style: an XSLT stylesheet
400 * @URI: the URI associated to the exension module
402 * Retrieve the data associated to the extension module in this given
405 * Returns the pointer or NULL if not present
408 xsltStyleGetExtData(xsltStylesheetPtr style, const xmlChar * URI) {
409 xsltExtDataPtr data = NULL;
410 xsltStylesheetPtr tmp;
413 if ((style == NULL) || (URI == NULL))
417 while (tmp != NULL) {
418 if (tmp->extInfos != NULL) {
419 data = (xsltExtDataPtr) xmlHashLookup(tmp->extInfos, URI);
423 tmp = xsltNextImport(tmp);
426 if (style->extInfos == NULL) {
427 style->extInfos = xmlHashCreate(10);
428 if (style->extInfos == NULL)
434 xsltExtModulePtr module;
436 module = xmlHashLookup(xsltExtensionsHash, URI);
437 if (module == NULL) {
438 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
439 xsltGenericDebug(xsltGenericDebugContext,
440 "Not registered extension module: %s\n", URI);
444 if (module->styleInitFunc == NULL)
447 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
448 xsltGenericDebug(xsltGenericDebugContext,
449 "Initializing module: %s\n", URI);
452 extData = module->styleInitFunc(style, URI);
456 data = xsltNewExtData(module, extData);
459 if (xmlHashAddEntry(style->extInfos, URI,
460 (void *) data) < 0) {
461 xsltGenericError(xsltGenericErrorContext,
462 "Failed to register module data: %s\n", URI);
463 if (module->styleShutdownFunc)
464 module->styleShutdownFunc(style, URI, extData);
465 xsltFreeExtData(data);
470 return (data->extData);
475 * @ctxt: an XSLT transformation context
476 * @URI: the URI associated to the exension module
478 * Retrieve the data associated to the extension module in this given
481 * Returns the pointer or NULL if not present
484 xsltGetExtData(xsltTransformContextPtr ctxt, const xmlChar * URI) {
487 if ((ctxt == NULL) || (URI == NULL))
489 if (ctxt->extInfos == NULL) {
490 ctxt->extInfos = xmlHashCreate(10);
491 if (ctxt->extInfos == NULL)
495 data = (xsltExtDataPtr) xmlHashLookup(ctxt->extInfos, URI);
499 xsltExtModulePtr module;
501 module = xmlHashLookup(xsltExtensionsHash, URI);
502 if (module == NULL) {
503 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
504 xsltGenericDebug(xsltGenericDebugContext,
505 "Not registered extension module: %s\n", URI);
509 if (module->initFunc == NULL)
512 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
513 xsltGenericDebug(xsltGenericDebugContext,
514 "Initializing module: %s\n", URI);
517 extData = module->initFunc(ctxt, URI);
521 data = xsltNewExtData(module, extData);
524 if (xmlHashAddEntry(ctxt->extInfos, URI,
525 (void *) data) < 0) {
526 xsltPrintErrorContext(ctxt, NULL, NULL);
527 xsltGenericError(xsltGenericErrorContext,
528 "Failed to register module data: %s\n", URI);
529 if (module->shutdownFunc)
530 module->shutdownFunc(ctxt, URI, extData);
531 xsltFreeExtData(data);
536 return (data->extData);
539 typedef struct _xsltInitExtCtxt xsltInitExtCtxt;
540 struct _xsltInitExtCtxt {
541 xsltTransformContextPtr ctxt;
547 * @styleData: the registered stylesheet data for the module
548 * @ctxt: the XSLT transformation context + the return value
549 * @URI: the extension URI
551 * Initializes an extension module
554 xsltInitCtxtExt (xsltExtDataPtr styleData, xsltInitExtCtxt *ctxt,
555 const xmlChar *URI) {
556 xsltExtModulePtr module;
557 xsltExtDataPtr ctxtData;
560 if ((styleData == NULL) || (ctxt == NULL) || (URI == NULL) ||
562 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
563 xsltGenericDebug(xsltGenericDebugContext,
564 "xsltInitCtxtExt: NULL param or error\n");
568 module = styleData->extModule;
569 if ((module == NULL) || (module->initFunc == NULL)) {
570 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
571 xsltGenericDebug(xsltGenericDebugContext,
572 "xsltInitCtxtExt: no module or no initFunc\n");
577 extData = module->initFunc(ctxt->ctxt, URI);
578 if (extData == NULL) {
579 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
580 xsltGenericDebug(xsltGenericDebugContext,
581 "xsltInitCtxtExt: no extData\n");
585 ctxtData = xsltNewExtData(module, extData);
586 if (ctxtData == NULL) {
591 if (ctxt->ctxt->extInfos == NULL)
592 ctxt->ctxt->extInfos = xmlHashCreate(10);
593 if (ctxt->ctxt->extInfos == NULL) {
598 if (xmlHashAddEntry(ctxt->ctxt->extInfos, URI, ctxtData) < 0) {
599 xsltGenericError(xsltGenericErrorContext,
600 "Failed to register module data: %s\n", URI);
601 if (module->shutdownFunc)
602 module->shutdownFunc(ctxt->ctxt, URI, extData);
603 xsltFreeExtData(ctxtData);
607 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
608 xsltGenericDebug(xsltGenericDebugContext, "Registered module %s\n",
616 * @ctxt: an XSLT transformation context
618 * Initialize the set of modules with registered stylesheet data
620 * Returns the number of modules initialized or -1 in case of error
623 xsltInitCtxtExts(xsltTransformContextPtr ctxt)
625 xsltStylesheetPtr style;
638 while (style != NULL) {
639 if (style->extInfos != NULL) {
640 xmlHashScan(style->extInfos,
641 (xmlHashScanner) xsltInitCtxtExt, &ctx);
645 style = xsltNextImport(style);
647 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
648 xsltGenericDebug(xsltGenericDebugContext, "Registered %d modules\n",
655 * xsltShutdownCtxtExt:
656 * @data: the registered data for the module
657 * @ctxt: the XSLT transformation context
658 * @URI: the extension URI
660 * Shutdown an extension module loaded
663 xsltShutdownCtxtExt(xsltExtDataPtr data, xsltTransformContextPtr ctxt,
666 xsltExtModulePtr module;
668 if ((data == NULL) || (ctxt == NULL) || (URI == NULL))
670 module = data->extModule;
671 if ((module == NULL) || (module->shutdownFunc == NULL))
674 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
675 xsltGenericDebug(xsltGenericDebugContext,
676 "Shutting down module : %s\n", URI);
678 module->shutdownFunc(ctxt, URI, data->extData);
679 xmlHashRemoveEntry(ctxt->extInfos, URI,
680 (xmlHashDeallocator) xsltFreeExtData);
684 * xsltShutdownCtxtExts:
685 * @ctxt: an XSLT transformation context
687 * Shutdown the set of modules loaded
690 xsltShutdownCtxtExts(xsltTransformContextPtr ctxt)
694 if (ctxt->extInfos == NULL)
696 xmlHashScan(ctxt->extInfos, (xmlHashScanner) xsltShutdownCtxtExt, ctxt);
697 xmlHashFree(ctxt->extInfos, (xmlHashDeallocator) xsltFreeExtData);
698 ctxt->extInfos = NULL;
703 * @data: the registered data for the module
704 * @ctxt: the XSLT stylesheet
705 * @URI: the extension URI
707 * Shutdown an extension module loaded
710 xsltShutdownExt(xsltExtDataPtr data, xsltStylesheetPtr style,
713 xsltExtModulePtr module;
715 if ((data == NULL) || (style == NULL) || (URI == NULL))
717 module = data->extModule;
718 if ((module == NULL) || (module->styleShutdownFunc == NULL))
721 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
722 xsltGenericDebug(xsltGenericDebugContext,
723 "Shutting down module : %s\n", URI);
725 module->styleShutdownFunc(style, URI, data->extData);
726 xmlHashRemoveEntry(style->extInfos, URI,
727 (xmlHashDeallocator) xsltFreeExtData);
732 * @style: an XSLT stylesheet
734 * Shutdown the set of modules loaded
737 xsltShutdownExts(xsltStylesheetPtr style)
741 if (style->extInfos == NULL)
743 xmlHashScan(style->extInfos, (xmlHashScanner) xsltShutdownExt, style);
744 xmlHashFree(style->extInfos, (xmlHashDeallocator) xsltFreeExtData);
745 style->extInfos = NULL;
749 * xsltCheckExtPrefix:
750 * @style: the stylesheet
751 * @prefix: the namespace prefix (possibly NULL)
753 * Check if the given prefix is one of the declared extensions
755 * Returns 1 if this is an extension, 0 otherwise
758 xsltCheckExtPrefix(xsltStylesheetPtr style, const xmlChar *prefix) {
761 if ((style == NULL) || (style->nsDefs == NULL))
764 cur = (xsltExtDefPtr) style->nsDefs;
765 while (cur != NULL) {
766 if (xmlStrEqual(prefix, cur->prefix))
774 * xsltRegisterExtModuleFull:
775 * @URI: URI associated to this module
776 * @initFunc: the module initialization function
777 * @shutdownFunc: the module shutdown function
778 * @styleInitFunc: the module initialization function
779 * @styleShutdownFunc: the module shutdown function
781 * Register an XSLT extension module to the library.
783 * Returns 0 if sucessful, -1 in case of error
786 xsltRegisterExtModuleFull(const xmlChar * URI,
787 xsltExtInitFunction initFunc,
788 xsltExtShutdownFunction shutdownFunc,
789 xsltStyleExtInitFunction styleInitFunc,
790 xsltStyleExtShutdownFunction styleShutdownFunc)
793 xsltExtModulePtr module;
795 if ((URI == NULL) || (initFunc == NULL))
797 if (xsltExtensionsHash == NULL)
798 xsltExtensionsHash = xmlHashCreate(10);
800 if (xsltExtensionsHash == NULL)
803 module = xmlHashLookup(xsltExtensionsHash, URI);
804 if (module != NULL) {
805 if ((module->initFunc == initFunc) &&
806 (module->shutdownFunc == shutdownFunc))
810 module = xsltNewExtModule(initFunc, shutdownFunc,
811 styleInitFunc, styleShutdownFunc);
814 ret = xmlHashAddEntry(xsltExtensionsHash, URI, (void *) module);
819 * xsltRegisterExtModule:
820 * @URI: URI associated to this module
821 * @initFunc: the module initialization function
822 * @shutdownFunc: the module shutdown function
824 * Register an XSLT extension module to the library.
826 * Returns 0 if sucessful, -1 in case of error
829 xsltRegisterExtModule(const xmlChar * URI,
830 xsltExtInitFunction initFunc,
831 xsltExtShutdownFunction shutdownFunc) {
832 return xsltRegisterExtModuleFull(URI, initFunc, shutdownFunc,
837 * xsltUnregisterExtModule:
838 * @URI: URI associated to this module
840 * Unregister an XSLT extension module from the library.
842 * Returns 0 if sucessful, -1 in case of error
845 xsltUnregisterExtModule(const xmlChar * URI)
851 if (xsltExtensionsHash == NULL)
855 xmlHashRemoveEntry(xsltExtensionsHash, URI,
856 (xmlHashDeallocator) xsltFreeExtModule);
861 * xsltUnregisterAllExtModules:
863 * Unregister all the XSLT extension module from the library.
866 xsltUnregisterAllExtModules(void)
868 if (xsltExtensionsHash == NULL)
871 xmlHashFree(xsltExtensionsHash, (xmlHashDeallocator) xsltFreeExtModule);
872 xsltExtensionsHash = NULL;
876 * xsltXPathGetTransformContext:
877 * @ctxt: an XPath transformation context
879 * Returns the XSLT transformation context from the XPath transformation
880 * context. This is useful when an XPath function in the extension module
881 * is called by the XPath interpreter and that the XSLT context is needed
882 * for example to retrieve the associated data pertaining to this XSLT
885 * Returns the XSLT transformation context or NULL in case of error.
887 xsltTransformContextPtr
888 xsltXPathGetTransformContext(xmlXPathParserContextPtr ctxt)
890 if ((ctxt == NULL) || (ctxt->context == NULL))
892 return(ctxt->context->extra);
896 * xsltRegisterExtModuleFunction:
897 * @name: the function name
898 * @URI: the function namespace URI
899 * @function: the function callback
901 * Registers an extension module function.
903 * Returns 0 if successful, -1 in case of error.
906 xsltRegisterExtModuleFunction (const xmlChar *name, const xmlChar *URI,
907 xmlXPathFunction function) {
908 if ((name == NULL) || (URI == NULL) || (function == NULL))
911 if (xsltFunctionsHash == NULL)
912 xsltFunctionsHash = xmlHashCreate(10);
913 if (xsltFunctionsHash == NULL)
916 xmlHashUpdateEntry2(xsltFunctionsHash, name, URI,
917 (void *) function, NULL);
923 * xsltExtModuleFunctionLookup:
924 * @name: the function name
925 * @URI: the function namespace URI
927 * Looks up an extension module function
929 * Returns the function if found, NULL otherwise.
932 xsltExtModuleFunctionLookup (const xmlChar *name, const xmlChar *URI) {
933 if ((xsltFunctionsHash == NULL) || (name == NULL) || (URI == NULL))
936 return (xmlXPathFunction) xmlHashLookup2(xsltFunctionsHash, name, URI);
940 * xsltUnregisterExtModuleFunction:
941 * @name: the function name
942 * @URI: the function namespace URI
944 * Unregisters an extension module function
946 * Returns 0 if successful, -1 in case of error.
949 xsltUnregisterExtModuleFunction (const xmlChar *name,
950 const xmlChar *URI) {
951 if ((xsltFunctionsHash == NULL) || (name == NULL) || (URI == NULL))
954 return xmlHashRemoveEntry2 (xsltFunctionsHash, name, URI, NULL);
958 * xsltUnregisterAllExtModuleFunction:
960 * Unregisters all extension module function
963 xsltUnregisterAllExtModuleFunction (void) {
964 xmlHashFree(xsltFunctionsHash, NULL);
965 xsltFunctionsHash = NULL;
970 * xsltNewElemPreComp:
971 * @style: the XSLT stylesheet
972 * @inst: the element node
973 * @function: the transform function
975 * Creates and initializes an #xsltElemPreComp
977 * Returns the new and initialized #xsltElemPreComp
980 xsltNewElemPreComp (xsltStylesheetPtr style, xmlNodePtr inst,
981 xsltTransformFunction function) {
982 xsltElemPreCompPtr cur;
984 cur = (xsltElemPreCompPtr) xmlMalloc (sizeof(xsltElemPreComp));
986 xsltPrintErrorContext(NULL, style, NULL);
987 xsltGenericError(xsltGenericErrorContext,
988 "xsltNewExtElement : malloc failed\n");
991 memset(cur, 0, sizeof(xsltElemPreComp));
993 xsltInitElemPreComp (cur, style, inst, function,
994 (xsltElemPreCompDeallocator) xmlFree);
1000 * xsltInitElemPreComp:
1001 * @comp: an #xsltElemPreComp (or generally a derived structure)
1002 * @style: the XSLT stylesheet
1003 * @inst: the element node
1004 * @function: the transform function
1005 * @freeFunc: the @comp deallocator
1007 * Initializes an existing #xsltElemPreComp structure. This is usefull
1008 * when extending an #xsltElemPreComp to store precomputed data.
1009 * This function MUST be called on any extension element precomputed
1013 xsltInitElemPreComp (xsltElemPreCompPtr comp, xsltStylesheetPtr style,
1014 xmlNodePtr inst, xsltTransformFunction function,
1015 xsltElemPreCompDeallocator freeFunc) {
1016 comp->type = XSLT_FUNC_EXTENSION;
1017 comp->func = function;
1019 comp->free = freeFunc;
1021 comp->next = style->preComps;
1022 style->preComps = comp;
1026 * xsltPreComputeExtModuleElement:
1027 * @style: the stylesheet
1028 * @inst: the element node
1030 * Precomputes an extension module element
1032 * Returns the precomputed data
1035 xsltPreComputeExtModuleElement (xsltStylesheetPtr style,
1037 xsltExtElementPtr ext;
1038 xsltElemPreCompPtr comp = NULL;
1040 if ((style == NULL) || (inst == NULL) ||
1041 (inst->type != XML_ELEMENT_NODE) || (inst->ns == NULL))
1044 ext = (xsltExtElementPtr)
1045 xmlHashLookup2 (xsltElementsHash, inst->name,
1050 if (ext->precomp != NULL)
1051 comp = ext->precomp(style, inst, ext->transform);
1053 comp = xsltNewElemPreComp (style, inst, ext->transform);
1059 * xsltRegisterExtModuleElement:
1060 * @name: the element name
1061 * @URI: the element namespace URI
1062 * @precomp: the pre-computation callback
1063 * @transform: the transformation callback
1065 * Registers an extension module element.
1067 * Returns 0 if successful, -1 in case of error.
1070 xsltRegisterExtModuleElement (const xmlChar *name, const xmlChar *URI,
1071 xsltPreComputeFunction precomp,
1072 xsltTransformFunction transform) {
1073 xsltExtElementPtr ext;
1075 if ((name == NULL) || (URI == NULL) || (transform == NULL))
1078 if (xsltElementsHash == NULL)
1079 xsltElementsHash = xmlHashCreate(10);
1080 if (xsltElementsHash == NULL)
1083 ext = xsltNewExtElement(precomp, transform);
1087 xmlHashUpdateEntry2(xsltElementsHash, name, URI, (void *) ext,
1088 (xmlHashDeallocator) xsltFreeExtElement);
1094 * xsltExtElementLookup:
1095 * @ctxt: an XSLT process context
1096 * @name: the element name
1097 * @URI: the element namespace URI
1099 * Looks up an extension element. @ctxt can be NULL to search only in
1102 * Returns the element callback or NULL if not found
1104 xsltTransformFunction
1105 xsltExtElementLookup (xsltTransformContextPtr ctxt,
1106 const xmlChar *name, const xmlChar *URI) {
1107 xsltTransformFunction ret;
1109 if ((name == NULL) || (URI == NULL))
1112 if ((ctxt != NULL) && (ctxt->extElements != NULL)) {
1113 ret = (xsltTransformFunction)
1114 xmlHashLookup2(ctxt->extElements, name, URI);
1118 return xsltExtModuleElementLookup(name, URI);
1122 * xsltExtModuleElementLookup:
1123 * @name: the element name
1124 * @URI: the element namespace URI
1126 * Looks up an extension module element
1128 * Returns the callback function if found, NULL otherwise.
1130 xsltTransformFunction
1131 xsltExtModuleElementLookup (const xmlChar *name, const xmlChar *URI) {
1132 xsltExtElementPtr ext;
1134 if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL))
1137 ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
1141 return(ext->transform);
1145 * xsltExtModuleElementPreComputeLookup:
1146 * @name: the element name
1147 * @URI: the element namespace URI
1149 * Looks up an extension module element pre-computation function
1151 * Returns the callback function if found, NULL otherwise.
1153 xsltPreComputeFunction
1154 xsltExtModuleElementPreComputeLookup (const xmlChar *name,
1155 const xmlChar *URI) {
1156 xsltExtElementPtr ext;
1158 if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL))
1161 ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
1165 return(ext->precomp);
1169 * xsltUnregisterExtModuleElement:
1170 * @name: the element name
1171 * @URI: the element namespace URI
1173 * Unregisters an extension module element
1175 * Returns 0 if successful, -1 in case of error.
1178 xsltUnregisterExtModuleElement (const xmlChar *name,
1179 const xmlChar *URI) {
1180 if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL))
1183 return xmlHashRemoveEntry2 (xsltElementsHash, name, URI,
1184 (xmlHashDeallocator) xsltFreeExtElement);
1188 * xsltUnregisterAllExtModuleElement:
1190 * Unregisters all extension module element
1193 xsltUnregisterAllExtModuleElement (void) {
1194 xmlHashFree(xsltElementsHash, (xmlHashDeallocator) xsltFreeExtElement);
1195 xsltElementsHash = NULL;
1199 * xsltRegisterExtModuleTopLevel:
1200 * @name: the top-level element name
1201 * @URI: the top-level element namespace URI
1202 * @function: the top-level element callback
1204 * Registers an extension module top-level element.
1206 * Returns 0 if successful, -1 in case of error.
1209 xsltRegisterExtModuleTopLevel (const xmlChar *name, const xmlChar *URI,
1210 xsltTopLevelFunction function) {
1211 if ((name == NULL) || (URI == NULL) || (function == NULL))
1214 if (xsltTopLevelsHash == NULL)
1215 xsltTopLevelsHash = xmlHashCreate(10);
1216 if (xsltTopLevelsHash == NULL)
1219 xmlHashUpdateEntry2(xsltTopLevelsHash, name, URI,
1220 (void *) function, NULL);
1226 * xsltExtModuleTopLevelLookup:
1227 * @name: the top-level element name
1228 * @URI: the top-level element namespace URI
1230 * Looks up an extension module top-level element
1232 * Returns the callback function if found, NULL otherwise.
1234 xsltTopLevelFunction
1235 xsltExtModuleTopLevelLookup (const xmlChar *name, const xmlChar *URI) {
1236 if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL))
1239 return((xsltTopLevelFunction)
1240 xmlHashLookup2(xsltTopLevelsHash, name, URI));
1244 * xsltUnregisterExtModuleTopLevel:
1245 * @name: the top-level element name
1246 * @URI: the top-level element namespace URI
1248 * Unregisters an extension module top-level element
1250 * Returns 0 if successful, -1 in case of error.
1253 xsltUnregisterExtModuleTopLevel (const xmlChar *name,
1254 const xmlChar *URI) {
1255 if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL))
1258 return xmlHashRemoveEntry2 (xsltTopLevelsHash, name, URI, NULL);
1262 * xsltUnregisterAllExtModuleTopLevel:
1264 * Unregisters all extension module function
1267 xsltUnregisterAllExtModuleTopLevel (void) {
1268 xmlHashFree(xsltTopLevelsHash, NULL);
1269 xsltTopLevelsHash = NULL;
1273 /************************************************************************
1275 * Test module http://xmlsoft.org/XSLT/ *
1277 ************************************************************************/
1279 /************************************************************************
1281 * Test of the extension module API *
1283 ************************************************************************/
1285 static xmlChar *testData = NULL;
1286 static xmlChar *testStyleData = NULL;
1289 * xsltExtFunctionTest:
1290 * @ctxt: the XPath Parser context
1291 * @nargs: the number of arguments
1293 * function libxslt:test() for testing the extensions support.
1296 xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, int nargs ATTRIBUTE_UNUSED)
1298 xsltTransformContextPtr tctxt;
1301 tctxt = xsltXPathGetTransformContext(ctxt);
1303 if (testData == NULL) {
1304 xsltGenericDebug(xsltGenericDebugContext,
1305 "xsltExtFunctionTest: not initialized,"
1306 " calling xsltGetExtData\n");
1307 data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
1309 xsltPrintErrorContext(tctxt, NULL, NULL);
1310 xsltGenericError(xsltGenericErrorContext,
1311 "xsltExtElementTest: not initialized\n");
1315 if (tctxt == NULL) {
1316 xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
1317 xsltGenericError(xsltGenericErrorContext,
1318 "xsltExtFunctionTest: failed to get the transformation context\n");
1322 data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
1324 xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
1325 xsltGenericError(xsltGenericErrorContext,
1326 "xsltExtFunctionTest: failed to get module data\n");
1329 if (data != testData) {
1330 xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
1331 xsltGenericError(xsltGenericErrorContext,
1332 "xsltExtFunctionTest: got wrong module data\n");
1335 #ifdef WITH_XSLT_DEBUG_FUNCTION
1336 xsltGenericDebug(xsltGenericDebugContext,
1337 "libxslt:test() called with %d args\n", nargs);
1342 * xsltExtElementPreCompTest:
1343 * @style: the stylesheet
1344 * @inst: the instruction in the stylesheet
1346 * Process a libxslt:test node
1348 static xsltElemPreCompPtr
1349 xsltExtElementPreCompTest(xsltStylesheetPtr style, xmlNodePtr inst,
1350 xsltTransformFunction function) {
1351 xsltElemPreCompPtr ret;
1353 if (style == NULL) {
1354 xsltPrintErrorContext(NULL, NULL, inst);
1355 xsltGenericError(xsltGenericErrorContext,
1356 "xsltExtElementTest: no transformation context\n");
1359 if (testStyleData == NULL) {
1360 xsltGenericDebug(xsltGenericDebugContext,
1361 "xsltExtElementPreCompTest: not initialized,"
1362 " calling xsltStyleGetExtData\n");
1363 xsltStyleGetExtData(style, (const xmlChar *) XSLT_DEFAULT_URL);
1364 if (testStyleData == NULL) {
1365 xsltPrintErrorContext(NULL, style, inst);
1366 xsltGenericError(xsltGenericErrorContext,
1367 "xsltExtElementPreCompTest: not initialized\n");
1373 xsltPrintErrorContext(NULL, style, inst);
1374 xsltGenericError(xsltGenericErrorContext,
1375 "xsltExtElementPreCompTest: no instruction\n");
1379 ret = xsltNewElemPreComp (style, inst, function);
1384 * xsltExtElementTest:
1385 * @ctxt: an XSLT processing context
1386 * @node: The current node
1387 * @inst: the instruction in the stylesheet
1388 * @comp: precomputed informations
1390 * Process a libxslt:test node
1393 xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node,
1395 xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
1397 xmlNodePtr commentNode;
1399 if (testData == NULL) {
1400 xsltGenericDebug(xsltGenericDebugContext,
1401 "xsltExtElementTest: not initialized,"
1402 " calling xsltGetExtData\n");
1403 xsltGetExtData(ctxt, (const xmlChar *) XSLT_DEFAULT_URL);
1404 if (testData == NULL) {
1405 xsltPrintErrorContext(ctxt, NULL, inst);
1406 xsltGenericError(xsltGenericErrorContext,
1407 "xsltExtElementTest: not initialized\n");
1412 xsltPrintErrorContext(ctxt, NULL, inst);
1413 xsltGenericError(xsltGenericErrorContext,
1414 "xsltExtElementTest: no transformation context\n");
1418 xsltPrintErrorContext(ctxt, NULL, inst);
1419 xsltGenericError(xsltGenericErrorContext,
1420 "xsltExtElementTest: no current node\n");
1424 xsltPrintErrorContext(ctxt, NULL, inst);
1425 xsltGenericError(xsltGenericErrorContext,
1426 "xsltExtElementTest: no instruction\n");
1429 if (ctxt->insert == NULL) {
1430 xsltPrintErrorContext(ctxt, NULL, inst);
1431 xsltGenericError(xsltGenericErrorContext,
1432 "xsltExtElementTest: no insertion point\n");
1436 xmlNewComment((const xmlChar *)
1437 "libxslt:test element test worked");
1438 xmlAddChild(ctxt->insert, commentNode);
1443 * @ctxt: an XSLT transformation context
1444 * @URI: the namespace URI for the extension
1446 * A function called at initialization time of an XSLT extension module
1448 * Returns a pointer to the module specific data for this transformation
1451 xsltExtInitTest(xsltTransformContextPtr ctxt, const xmlChar * URI) {
1452 if (testStyleData == NULL) {
1453 xsltGenericDebug(xsltGenericErrorContext,
1454 "xsltExtInitTest: not initialized,"
1455 " calling xsltStyleGetExtData\n");
1456 xsltStyleGetExtData(ctxt->style, URI);
1457 if (testStyleData == NULL) {
1458 xsltPrintErrorContext(ctxt, NULL, NULL);
1459 xsltGenericError(xsltGenericErrorContext,
1460 "xsltExtInitTest: not initialized\n");
1464 if (testData != NULL) {
1465 xsltPrintErrorContext(ctxt, NULL, NULL);
1466 xsltGenericError(xsltGenericErrorContext,
1467 "xsltExtInitTest: already initialized\n");
1470 testData = (void *) "test data";
1471 xsltGenericDebug(xsltGenericDebugContext,
1472 "Registered test module : %s\n", URI);
1478 * xsltExtShutdownTest:
1479 * @ctxt: an XSLT transformation context
1480 * @URI: the namespace URI for the extension
1481 * @data: the data associated to this module
1483 * A function called at shutdown time of an XSLT extension module
1486 xsltExtShutdownTest(xsltTransformContextPtr ctxt,
1487 const xmlChar * URI, void *data) {
1488 if (testData == NULL) {
1489 xsltPrintErrorContext(ctxt, NULL, NULL);
1490 xsltGenericError(xsltGenericErrorContext,
1491 "xsltExtShutdownTest: not initialized\n");
1494 if (data != testData) {
1495 xsltPrintErrorContext(ctxt, NULL, NULL);
1496 xsltGenericError(xsltGenericErrorContext,
1497 "xsltExtShutdownTest: wrong data\n");
1500 xsltGenericDebug(xsltGenericDebugContext,
1501 "Unregistered test module : %s\n", URI);
1504 * xsltExtStyleInitTest:
1505 * @style: an XSLT stylesheet
1506 * @URI: the namespace URI for the extension
1508 * A function called at initialization time of an XSLT extension module
1510 * Returns a pointer to the module specific data for this transformation
1513 xsltExtStyleInitTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED,
1514 const xmlChar * URI)
1516 if (testStyleData != NULL) {
1517 xsltPrintErrorContext(NULL, NULL, NULL);
1518 xsltGenericError(xsltGenericErrorContext,
1519 "xsltExtInitTest: already initialized\n");
1522 testStyleData = (void *) "test data";
1523 xsltGenericDebug(xsltGenericDebugContext,
1524 "Registered test module : %s\n", URI);
1525 return (testStyleData);
1530 * xsltExtStyleShutdownTest:
1531 * @style: an XSLT stylesheet
1532 * @URI: the namespace URI for the extension
1533 * @data: the data associated to this module
1535 * A function called at shutdown time of an XSLT extension module
1538 xsltExtStyleShutdownTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED,
1539 const xmlChar * URI, void *data) {
1540 if (testStyleData == NULL) {
1541 xsltGenericError(xsltGenericErrorContext,
1542 "xsltExtShutdownTest: not initialized\n");
1545 if (data != testStyleData) {
1546 xsltPrintErrorContext(NULL, NULL, NULL);
1547 xsltGenericError(xsltGenericErrorContext,
1548 "xsltExtShutdownTest: wrong data\n");
1550 testStyleData = NULL;
1551 xsltGenericDebug(xsltGenericDebugContext,
1552 "Unregistered test module : %s\n", URI);
1556 * xsltRegisterTestModule:
1558 * Registers the test module
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);
1576 * xsltCleanupGlobals:
1578 * Unregister all global variables set up by the XSLT library
1581 xsltCleanupGlobals(void)
1583 xsltUnregisterAllExtModules();
1584 xsltUnregisterAllExtModuleFunction();
1585 xsltUnregisterAllExtModuleElement();
1586 xsltUnregisterAllExtModuleTopLevel();