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.
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>
24 #include "xsltInternals.h"
25 #include "xsltutils.h"
27 #include "extensions.h"
29 #ifdef WITH_XSLT_DEBUG
30 #define WITH_XSLT_DEBUG_EXTENSIONS
33 /************************************************************************
35 * Private Types and Globals *
37 ************************************************************************/
39 typedef struct _xsltExtDef xsltExtDef;
40 typedef xsltExtDef *xsltExtDefPtr;
42 struct _xsltExtDef *next;
48 typedef struct _xsltExtModule xsltExtModule;
49 typedef xsltExtModule *xsltExtModulePtr;
50 struct _xsltExtModule {
51 xsltExtInitFunction initFunc;
52 xsltExtShutdownFunction shutdownFunc;
53 xsltStyleExtInitFunction styleInitFunc;
54 xsltStyleExtShutdownFunction styleShutdownFunc;
57 typedef struct _xsltExtData xsltExtData;
58 typedef xsltExtData *xsltExtDataPtr;
60 xsltExtModulePtr extModule;
64 typedef struct _xsltExtElement xsltExtElement;
65 typedef xsltExtElement *xsltExtElementPtr;
66 struct _xsltExtElement {
67 xsltPreComputeFunction precomp;
68 xsltTransformFunction transform;
71 static xmlHashTablePtr xsltExtensionsHash = NULL;
72 static xmlHashTablePtr xsltFunctionsHash = NULL;
73 static xmlHashTablePtr xsltElementsHash = NULL;
74 static xmlHashTablePtr xsltTopLevelsHash = NULL;
76 /************************************************************************
80 ************************************************************************/
84 * @prefix: the extension prefix
85 * @URI: the namespace URI
87 * Create a new XSLT ExtDef
89 * Returns the newly allocated xsltExtDefPtr or NULL in case of error
92 xsltNewExtDef(const xmlChar * prefix, const xmlChar * URI)
96 cur = (xsltExtDefPtr) xmlMalloc(sizeof(xsltExtDef));
98 xsltTransformError(NULL, NULL, NULL,
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 xsltTransformError(NULL, NULL, NULL,
166 "xsltNewExtModule : malloc failed\n");
169 cur->initFunc = initFunc;
170 cur->shutdownFunc = shutdownFunc;
171 cur->styleInitFunc = styleInitFunc;
172 cur->styleShutdownFunc = styleShutdownFunc;
178 * @ext: an XSLT extension module
180 * Free up the memory allocated by @ext
183 xsltFreeExtModule(xsltExtModulePtr ext) {
191 * @extModule: the module
192 * @extData: the associated data
194 * Create a new XSLT extension module data wrapper
196 * Returns the newly allocated xsltExtDataPtr or NULL in case of error
198 static xsltExtDataPtr
199 xsltNewExtData(xsltExtModulePtr extModule, void *extData)
203 if (extModule == NULL)
205 cur = (xsltExtDataPtr) xmlMalloc(sizeof(xsltExtData));
207 xsltTransformError(NULL, NULL, NULL,
208 "xsltNewExtData : malloc failed\n");
211 cur->extModule = extModule;
212 cur->extData = extData;
218 * @ext: an XSLT extension module data wrapper
220 * Free up the memory allocated by @ext
223 xsltFreeExtData(xsltExtDataPtr ext) {
231 * @precomp: the pre-computation function
232 * @transform: the transformation function
234 * Create a new XSLT extension element
236 * Returns the newly allocated xsltExtElementPtr or NULL in case of
239 static xsltExtElementPtr
240 xsltNewExtElement (xsltPreComputeFunction precomp,
241 xsltTransformFunction transform) {
242 xsltExtElementPtr cur;
244 if (transform == NULL)
247 cur = (xsltExtElementPtr) xmlMalloc(sizeof(xsltExtElement));
249 xsltTransformError(NULL, NULL, NULL,
250 "xsltNewExtElement : malloc failed\n");
253 cur->precomp = precomp;
254 cur->transform = transform;
259 * xsltFreeExtElement:
260 * @ext: an XSLT extension element
262 * Frees up the memory allocated by @ext
265 xsltFreeExtElement (xsltExtElementPtr ext) {
272 /************************************************************************
274 * The stylesheet extension prefixes handling *
276 ************************************************************************/
281 * @style: an XSLT stylesheet
283 * Free up the memory used by XSLT extensions in a stylesheet
286 xsltFreeExts(xsltStylesheetPtr style) {
287 if (style->nsDefs != NULL)
288 xsltFreeExtDefList((xsltExtDefPtr) style->nsDefs);
292 * xsltRegisterExtPrefix:
293 * @style: an XSLT stylesheet
294 * @prefix: the prefix used
295 * @URI: the URI associated to the extension
297 * Registers an extension namespace
299 * Returns 0 in case of success, -1 in case of failure
302 xsltRegisterExtPrefix(xsltStylesheetPtr style,
303 const xmlChar *prefix, const xmlChar *URI) {
304 xsltExtDefPtr def, ret;
306 if ((style == NULL) || (prefix == NULL) | (URI == NULL))
309 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
310 xsltGenericDebug(xsltGenericDebugContext,
311 "Registering extension prefix %s : %s\n", prefix, URI);
313 def = (xsltExtDefPtr) style->nsDefs;
314 while (def != NULL) {
315 if (xmlStrEqual(prefix, def->prefix))
319 ret = xsltNewExtDef(prefix, URI);
322 ret->next = (xsltExtDefPtr) style->nsDefs;
326 * check wether there is an extension module with a stylesheet
327 * initialization function.
329 if (xsltExtensionsHash != NULL) {
330 xsltExtModulePtr module;
332 module = xmlHashLookup(xsltExtensionsHash, URI);
333 if (module != NULL) {
336 data = xsltStyleGetExtData(style, URI);
342 /************************************************************************
344 * The extensions modules interfaces *
346 ************************************************************************/
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
355 * Registers an extension function
357 * Returns 0 in case of success, -1 in case of failure
360 xsltRegisterExtFunction(xsltTransformContextPtr ctxt, const xmlChar *name,
361 const xmlChar *URI, xmlXPathFunction function) {
362 if ((ctxt == NULL) || (name == NULL) ||
363 (URI == NULL) || (function == NULL))
365 if (ctxt->xpathCtxt != NULL) {
366 xmlXPathRegisterFuncNS(ctxt->xpathCtxt, name, URI, function);
368 if (ctxt->extFunctions == NULL)
369 ctxt->extFunctions = xmlHashCreate(10);
370 if (ctxt->extFunctions == NULL)
372 return(xmlHashAddEntry2(ctxt->extFunctions, name, URI, (void *) function));
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
382 * Registers an extension element
384 * Returns 0 in case of success, -1 in case of failure
387 xsltRegisterExtElement(xsltTransformContextPtr ctxt, const xmlChar *name,
388 const xmlChar *URI, xsltTransformFunction function) {
389 if ((ctxt == NULL) || (name == NULL) ||
390 (URI == NULL) || (function == NULL))
392 if (ctxt->extElements == NULL)
393 ctxt->extElements = xmlHashCreate(10);
394 if (ctxt->extElements == NULL)
396 return(xmlHashAddEntry2(ctxt->extElements, name, URI, (void *) function));
401 * @ctxt: an XSLT transformation context
403 * Free the XSLT extension data
406 xsltFreeCtxtExts(xsltTransformContextPtr ctxt) {
407 if (ctxt->extElements != NULL)
408 xmlHashFree(ctxt->extElements, NULL);
409 if (ctxt->extFunctions != NULL)
410 xmlHashFree(ctxt->extFunctions, NULL);
414 * xsltStyleGetExtData:
415 * @style: an XSLT stylesheet
416 * @URI: the URI associated to the exension module
418 * Retrieve the data associated to the extension module in this given
421 * Returns the pointer or NULL if not present
424 xsltStyleGetExtData(xsltStylesheetPtr style, const xmlChar * URI) {
425 xsltExtDataPtr data = NULL;
426 xsltStylesheetPtr tmp;
429 if ((style == NULL) || (URI == NULL))
433 while (tmp != NULL) {
434 if (tmp->extInfos != NULL) {
435 data = (xsltExtDataPtr) xmlHashLookup(tmp->extInfos, URI);
439 tmp = xsltNextImport(tmp);
442 if (style->extInfos == NULL) {
443 style->extInfos = xmlHashCreate(10);
444 if (style->extInfos == NULL)
450 xsltExtModulePtr module;
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);
460 if (module->styleInitFunc == NULL) {
461 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
462 xsltGenericDebug(xsltGenericDebugContext,
463 "Registering style module: %s\n", URI);
467 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
468 xsltGenericDebug(xsltGenericDebugContext,
469 "Initializing module: %s\n", URI);
471 extData = module->styleInitFunc(style, URI);
474 data = xsltNewExtData(module, extData);
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);
488 return (data->extData);
493 * @ctxt: an XSLT transformation context
494 * @URI: the URI associated to the exension module
496 * Retrieve the data associated to the extension module in this given
499 * Returns the pointer or NULL if not present
502 xsltGetExtData(xsltTransformContextPtr ctxt, const xmlChar * URI) {
505 if ((ctxt == NULL) || (URI == NULL))
507 if (ctxt->extInfos == NULL) {
508 ctxt->extInfos = xmlHashCreate(10);
509 if (ctxt->extInfos == NULL)
513 data = (xsltExtDataPtr) xmlHashLookup(ctxt->extInfos, URI);
517 xsltExtModulePtr module;
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);
527 if (module->initFunc == NULL)
530 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
531 xsltGenericDebug(xsltGenericDebugContext,
532 "Initializing module: %s\n", URI);
535 extData = module->initFunc(ctxt, URI);
539 data = xsltNewExtData(module, extData);
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);
553 return (data->extData);
556 typedef struct _xsltInitExtCtxt xsltInitExtCtxt;
557 struct _xsltInitExtCtxt {
558 xsltTransformContextPtr ctxt;
564 * @styleData: the registered stylesheet data for the module
565 * @ctxt: the XSLT transformation context + the return value
566 * @URI: the extension URI
568 * Initializes an extension module
571 xsltInitCtxtExt (xsltExtDataPtr styleData, xsltInitExtCtxt *ctxt,
572 const xmlChar *URI) {
573 xsltExtModulePtr module;
574 xsltExtDataPtr ctxtData;
577 if ((styleData == NULL) || (ctxt == NULL) || (URI == NULL) ||
579 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
580 xsltGenericDebug(xsltGenericDebugContext,
581 "xsltInitCtxtExt: NULL param or error\n");
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");
594 ctxtData = (xsltExtDataPtr) xmlHashLookup(ctxt->ctxt->extInfos, URI);
595 if (ctxtData != NULL) {
596 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
597 xsltGenericDebug(xsltGenericDebugContext,
598 "xsltInitCtxtExt: already initialized\n");
603 extData = module->initFunc(ctxt->ctxt, URI);
604 if (extData == NULL) {
605 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
606 xsltGenericDebug(xsltGenericDebugContext,
607 "xsltInitCtxtExt: no extData\n");
610 ctxtData = xsltNewExtData(module, extData);
611 if (ctxtData == NULL) {
616 if (ctxt->ctxt->extInfos == NULL)
617 ctxt->ctxt->extInfos = xmlHashCreate(10);
618 if (ctxt->ctxt->extInfos == NULL) {
623 if (xmlHashAddEntry(ctxt->ctxt->extInfos, URI, ctxtData) < 0) {
624 xsltGenericError(xsltGenericErrorContext,
625 "Failed to register module data: %s\n", URI);
626 if (module->shutdownFunc)
627 module->shutdownFunc(ctxt->ctxt, URI, extData);
628 xsltFreeExtData(ctxtData);
632 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
633 xsltGenericDebug(xsltGenericDebugContext, "Registered module %s\n",
641 * @ctxt: an XSLT transformation context
643 * Initialize the set of modules with registered stylesheet data
645 * Returns the number of modules initialized or -1 in case of error
648 xsltInitCtxtExts(xsltTransformContextPtr ctxt)
650 xsltStylesheetPtr style;
663 while (style != NULL) {
664 if (style->extInfos != NULL) {
665 xmlHashScan(style->extInfos,
666 (xmlHashScanner) xsltInitCtxtExt, &ctx);
670 style = xsltNextImport(style);
672 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
673 xsltGenericDebug(xsltGenericDebugContext, "Registered %d modules\n",
680 * xsltShutdownCtxtExt:
681 * @data: the registered data for the module
682 * @ctxt: the XSLT transformation context
683 * @URI: the extension URI
685 * Shutdown an extension module loaded
688 xsltShutdownCtxtExt(xsltExtDataPtr data, xsltTransformContextPtr ctxt,
691 xsltExtModulePtr module;
693 if ((data == NULL) || (ctxt == NULL) || (URI == NULL))
695 module = data->extModule;
696 if ((module == NULL) || (module->shutdownFunc == NULL))
699 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
700 xsltGenericDebug(xsltGenericDebugContext,
701 "Shutting down module : %s\n", URI);
703 module->shutdownFunc(ctxt, URI, data->extData);
707 * xsltShutdownCtxtExts:
708 * @ctxt: an XSLT transformation context
710 * Shutdown the set of modules loaded
713 xsltShutdownCtxtExts(xsltTransformContextPtr ctxt)
717 if (ctxt->extInfos == NULL)
719 xmlHashScan(ctxt->extInfos, (xmlHashScanner) xsltShutdownCtxtExt, ctxt);
720 xmlHashFree(ctxt->extInfos, (xmlHashDeallocator) xsltFreeExtData);
721 ctxt->extInfos = NULL;
726 * @data: the registered data for the module
727 * @ctxt: the XSLT stylesheet
728 * @URI: the extension URI
730 * Shutdown an extension module loaded
733 xsltShutdownExt(xsltExtDataPtr data, xsltStylesheetPtr style,
736 xsltExtModulePtr module;
738 if ((data == NULL) || (style == NULL) || (URI == NULL))
740 module = data->extModule;
741 if ((module == NULL) || (module->styleShutdownFunc == NULL))
744 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
745 xsltGenericDebug(xsltGenericDebugContext,
746 "Shutting down module : %s\n", URI);
748 module->styleShutdownFunc(style, URI, data->extData);
749 xmlHashRemoveEntry(style->extInfos, URI,
750 (xmlHashDeallocator) xsltFreeExtData);
755 * @style: an XSLT stylesheet
757 * Shutdown the set of modules loaded
760 xsltShutdownExts(xsltStylesheetPtr style)
764 if (style->extInfos == NULL)
766 xmlHashScan(style->extInfos, (xmlHashScanner) xsltShutdownExt, style);
767 xmlHashFree(style->extInfos, (xmlHashDeallocator) xsltFreeExtData);
768 style->extInfos = NULL;
772 * xsltCheckExtPrefix:
773 * @style: the stylesheet
774 * @prefix: the namespace prefix (possibly NULL)
776 * Check if the given prefix is one of the declared extensions
778 * Returns 1 if this is an extension, 0 otherwise
781 xsltCheckExtPrefix(xsltStylesheetPtr style, const xmlChar *prefix) {
784 if ((style == NULL) || (style->nsDefs == NULL))
788 prefix = BAD_CAST "#default";
790 cur = (xsltExtDefPtr) style->nsDefs;
791 while (cur != NULL) {
792 if (xmlStrEqual(prefix, cur->prefix))
800 * xsltRegisterExtModuleFull:
801 * @URI: URI associated to this module
802 * @initFunc: the module initialization function
803 * @shutdownFunc: the module shutdown function
804 * @styleInitFunc: the module initialization function
805 * @styleShutdownFunc: the module shutdown function
807 * Register an XSLT extension module to the library.
809 * Returns 0 if sucessful, -1 in case of error
812 xsltRegisterExtModuleFull(const xmlChar * URI,
813 xsltExtInitFunction initFunc,
814 xsltExtShutdownFunction shutdownFunc,
815 xsltStyleExtInitFunction styleInitFunc,
816 xsltStyleExtShutdownFunction styleShutdownFunc)
819 xsltExtModulePtr module;
821 if ((URI == NULL) || (initFunc == NULL))
823 if (xsltExtensionsHash == NULL)
824 xsltExtensionsHash = xmlHashCreate(10);
826 if (xsltExtensionsHash == NULL)
829 module = xmlHashLookup(xsltExtensionsHash, URI);
830 if (module != NULL) {
831 if ((module->initFunc == initFunc) &&
832 (module->shutdownFunc == shutdownFunc))
836 module = xsltNewExtModule(initFunc, shutdownFunc,
837 styleInitFunc, styleShutdownFunc);
840 ret = xmlHashAddEntry(xsltExtensionsHash, URI, (void *) module);
845 * xsltRegisterExtModule:
846 * @URI: URI associated to this module
847 * @initFunc: the module initialization function
848 * @shutdownFunc: the module shutdown function
850 * Register an XSLT extension module to the library.
852 * Returns 0 if sucessful, -1 in case of error
855 xsltRegisterExtModule(const xmlChar * URI,
856 xsltExtInitFunction initFunc,
857 xsltExtShutdownFunction shutdownFunc) {
858 return xsltRegisterExtModuleFull(URI, initFunc, shutdownFunc,
863 * xsltUnregisterExtModule:
864 * @URI: URI associated to this module
866 * Unregister an XSLT extension module from the library.
868 * Returns 0 if sucessful, -1 in case of error
871 xsltUnregisterExtModule(const xmlChar * URI)
877 if (xsltExtensionsHash == NULL)
881 xmlHashRemoveEntry(xsltExtensionsHash, URI,
882 (xmlHashDeallocator) xsltFreeExtModule);
887 * xsltUnregisterAllExtModules:
889 * Unregister all the XSLT extension module from the library.
892 xsltUnregisterAllExtModules(void)
894 if (xsltExtensionsHash == NULL)
897 xmlHashFree(xsltExtensionsHash, (xmlHashDeallocator) xsltFreeExtModule);
898 xsltExtensionsHash = NULL;
902 * xsltXPathGetTransformContext:
903 * @ctxt: an XPath transformation context
905 * Provides the XSLT transformation context from the XPath transformation
906 * context. This is useful when an XPath function in the extension module
907 * is called by the XPath interpreter and that the XSLT context is needed
908 * for example to retrieve the associated data pertaining to this XSLT
911 * Returns the XSLT transformation context or NULL in case of error.
913 xsltTransformContextPtr
914 xsltXPathGetTransformContext(xmlXPathParserContextPtr ctxt)
916 if ((ctxt == NULL) || (ctxt->context == NULL))
918 return(ctxt->context->extra);
922 * xsltRegisterExtModuleFunction:
923 * @name: the function name
924 * @URI: the function namespace URI
925 * @function: the function callback
927 * Registers an extension module function.
929 * Returns 0 if successful, -1 in case of error.
932 xsltRegisterExtModuleFunction (const xmlChar *name, const xmlChar *URI,
933 xmlXPathFunction function) {
934 if ((name == NULL) || (URI == NULL) || (function == NULL))
937 if (xsltFunctionsHash == NULL)
938 xsltFunctionsHash = xmlHashCreate(10);
939 if (xsltFunctionsHash == NULL)
942 xmlHashUpdateEntry2(xsltFunctionsHash, name, URI,
943 (void *) function, NULL);
949 * xsltExtModuleFunctionLookup:
950 * @name: the function name
951 * @URI: the function namespace URI
953 * Looks up an extension module function
955 * Returns the function if found, NULL otherwise.
958 xsltExtModuleFunctionLookup (const xmlChar *name, const xmlChar *URI) {
959 if ((xsltFunctionsHash == NULL) || (name == NULL) || (URI == NULL))
962 return (xmlXPathFunction) xmlHashLookup2(xsltFunctionsHash, name, URI);
966 * xsltUnregisterExtModuleFunction:
967 * @name: the function name
968 * @URI: the function namespace URI
970 * Unregisters an extension module function
972 * Returns 0 if successful, -1 in case of error.
975 xsltUnregisterExtModuleFunction (const xmlChar *name,
976 const xmlChar *URI) {
977 if ((xsltFunctionsHash == NULL) || (name == NULL) || (URI == NULL))
980 return xmlHashRemoveEntry2 (xsltFunctionsHash, name, URI, NULL);
984 * xsltUnregisterAllExtModuleFunction:
986 * Unregisters all extension module function
989 xsltUnregisterAllExtModuleFunction (void) {
990 xmlHashFree(xsltFunctionsHash, NULL);
991 xsltFunctionsHash = NULL;
996 * xsltNewElemPreComp:
997 * @style: the XSLT stylesheet
998 * @inst: the element node
999 * @function: the transform function
1001 * Creates and initializes an #xsltElemPreComp
1003 * Returns the new and initialized #xsltElemPreComp
1006 xsltNewElemPreComp (xsltStylesheetPtr style, xmlNodePtr inst,
1007 xsltTransformFunction function) {
1008 xsltElemPreCompPtr cur;
1010 cur = (xsltElemPreCompPtr) xmlMalloc (sizeof(xsltElemPreComp));
1012 xsltTransformError(NULL, style, NULL,
1013 "xsltNewExtElement : malloc failed\n");
1016 memset(cur, 0, sizeof(xsltElemPreComp));
1018 xsltInitElemPreComp (cur, style, inst, function,
1019 (xsltElemPreCompDeallocator) xmlFree);
1025 * xsltInitElemPreComp:
1026 * @comp: an #xsltElemPreComp (or generally a derived structure)
1027 * @style: the XSLT stylesheet
1028 * @inst: the element node
1029 * @function: the transform function
1030 * @freeFunc: the @comp deallocator
1032 * Initializes an existing #xsltElemPreComp structure. This is usefull
1033 * when extending an #xsltElemPreComp to store precomputed data.
1034 * This function MUST be called on any extension element precomputed
1038 xsltInitElemPreComp (xsltElemPreCompPtr comp, xsltStylesheetPtr style,
1039 xmlNodePtr inst, xsltTransformFunction function,
1040 xsltElemPreCompDeallocator freeFunc) {
1041 comp->type = XSLT_FUNC_EXTENSION;
1042 comp->func = function;
1044 comp->free = freeFunc;
1046 comp->next = style->preComps;
1047 style->preComps = comp;
1051 * xsltPreComputeExtModuleElement:
1052 * @style: the stylesheet
1053 * @inst: the element node
1055 * Precomputes an extension module element
1057 * Returns the precomputed data
1060 xsltPreComputeExtModuleElement (xsltStylesheetPtr style,
1062 xsltExtElementPtr ext;
1063 xsltElemPreCompPtr comp = NULL;
1065 if ((style == NULL) || (inst == NULL) ||
1066 (inst->type != XML_ELEMENT_NODE) || (inst->ns == NULL))
1069 ext = (xsltExtElementPtr)
1070 xmlHashLookup2 (xsltElementsHash, inst->name,
1075 if (ext->precomp != NULL)
1076 comp = ext->precomp(style, inst, ext->transform);
1078 comp = xsltNewElemPreComp (style, inst, ext->transform);
1084 * xsltRegisterExtModuleElement:
1085 * @name: the element name
1086 * @URI: the element namespace URI
1087 * @precomp: the pre-computation callback
1088 * @transform: the transformation callback
1090 * Registers an extension module element.
1092 * Returns 0 if successful, -1 in case of error.
1095 xsltRegisterExtModuleElement (const xmlChar *name, const xmlChar *URI,
1096 xsltPreComputeFunction precomp,
1097 xsltTransformFunction transform) {
1098 xsltExtElementPtr ext;
1100 if ((name == NULL) || (URI == NULL) || (transform == NULL))
1103 if (xsltElementsHash == NULL)
1104 xsltElementsHash = xmlHashCreate(10);
1105 if (xsltElementsHash == NULL)
1108 ext = xsltNewExtElement(precomp, transform);
1112 xmlHashUpdateEntry2(xsltElementsHash, name, URI, (void *) ext,
1113 (xmlHashDeallocator) xsltFreeExtElement);
1119 * xsltExtElementLookup:
1120 * @ctxt: an XSLT process context
1121 * @name: the element name
1122 * @URI: the element namespace URI
1124 * Looks up an extension element. @ctxt can be NULL to search only in
1127 * Returns the element callback or NULL if not found
1129 xsltTransformFunction
1130 xsltExtElementLookup (xsltTransformContextPtr ctxt,
1131 const xmlChar *name, const xmlChar *URI) {
1132 xsltTransformFunction ret;
1134 if ((name == NULL) || (URI == NULL))
1137 if ((ctxt != NULL) && (ctxt->extElements != NULL)) {
1138 ret = (xsltTransformFunction)
1139 xmlHashLookup2(ctxt->extElements, name, URI);
1143 return xsltExtModuleElementLookup(name, URI);
1147 * xsltExtModuleElementLookup:
1148 * @name: the element name
1149 * @URI: the element namespace URI
1151 * Looks up an extension module element
1153 * Returns the callback function if found, NULL otherwise.
1155 xsltTransformFunction
1156 xsltExtModuleElementLookup (const xmlChar *name, const xmlChar *URI) {
1157 xsltExtElementPtr ext;
1159 if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL))
1162 ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
1166 return(ext->transform);
1170 * xsltExtModuleElementPreComputeLookup:
1171 * @name: the element name
1172 * @URI: the element namespace URI
1174 * Looks up an extension module element pre-computation function
1176 * Returns the callback function if found, NULL otherwise.
1178 xsltPreComputeFunction
1179 xsltExtModuleElementPreComputeLookup (const xmlChar *name,
1180 const xmlChar *URI) {
1181 xsltExtElementPtr ext;
1183 if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL))
1186 ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
1190 return(ext->precomp);
1194 * xsltUnregisterExtModuleElement:
1195 * @name: the element name
1196 * @URI: the element namespace URI
1198 * Unregisters an extension module element
1200 * Returns 0 if successful, -1 in case of error.
1203 xsltUnregisterExtModuleElement (const xmlChar *name,
1204 const xmlChar *URI) {
1205 if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL))
1208 return xmlHashRemoveEntry2 (xsltElementsHash, name, URI,
1209 (xmlHashDeallocator) xsltFreeExtElement);
1213 * xsltUnregisterAllExtModuleElement:
1215 * Unregisters all extension module element
1218 xsltUnregisterAllExtModuleElement (void) {
1219 xmlHashFree(xsltElementsHash, (xmlHashDeallocator) xsltFreeExtElement);
1220 xsltElementsHash = NULL;
1224 * xsltRegisterExtModuleTopLevel:
1225 * @name: the top-level element name
1226 * @URI: the top-level element namespace URI
1227 * @function: the top-level element callback
1229 * Registers an extension module top-level element.
1231 * Returns 0 if successful, -1 in case of error.
1234 xsltRegisterExtModuleTopLevel (const xmlChar *name, const xmlChar *URI,
1235 xsltTopLevelFunction function) {
1236 if ((name == NULL) || (URI == NULL) || (function == NULL))
1239 if (xsltTopLevelsHash == NULL)
1240 xsltTopLevelsHash = xmlHashCreate(10);
1241 if (xsltTopLevelsHash == NULL)
1244 xmlHashUpdateEntry2(xsltTopLevelsHash, name, URI,
1245 (void *) function, NULL);
1251 * xsltExtModuleTopLevelLookup:
1252 * @name: the top-level element name
1253 * @URI: the top-level element namespace URI
1255 * Looks up an extension module top-level element
1257 * Returns the callback function if found, NULL otherwise.
1259 xsltTopLevelFunction
1260 xsltExtModuleTopLevelLookup (const xmlChar *name, const xmlChar *URI) {
1261 if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL))
1264 return((xsltTopLevelFunction)
1265 xmlHashLookup2(xsltTopLevelsHash, name, URI));
1269 * xsltUnregisterExtModuleTopLevel:
1270 * @name: the top-level element name
1271 * @URI: the top-level element namespace URI
1273 * Unregisters an extension module top-level element
1275 * Returns 0 if successful, -1 in case of error.
1278 xsltUnregisterExtModuleTopLevel (const xmlChar *name,
1279 const xmlChar *URI) {
1280 if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL))
1283 return xmlHashRemoveEntry2 (xsltTopLevelsHash, name, URI, NULL);
1287 * xsltUnregisterAllExtModuleTopLevel:
1289 * Unregisters all extension module function
1292 xsltUnregisterAllExtModuleTopLevel (void) {
1293 xmlHashFree(xsltTopLevelsHash, NULL);
1294 xsltTopLevelsHash = NULL;
1299 * @style: pointer to a stylesheet
1300 * @URI: the namespace URI desired
1302 * looks up URI in extInfos of the stylesheet
1304 * returns a pointer to the hash table if found, else NULL
1307 xsltGetExtInfo (xsltStylesheetPtr style, const xmlChar *URI) {
1308 xsltExtDataPtr data;
1310 if (style != NULL && style->extInfos != NULL) {
1311 data = xmlHashLookup(style->extInfos, URI);
1312 if (data != NULL && data->extData != NULL)
1313 return data->extData;
1318 /************************************************************************
1320 * Test module http://xmlsoft.org/XSLT/ *
1322 ************************************************************************/
1324 /************************************************************************
1326 * Test of the extension module API *
1328 ************************************************************************/
1330 static xmlChar *testData = NULL;
1331 static xmlChar *testStyleData = NULL;
1334 * xsltExtFunctionTest:
1335 * @ctxt: the XPath Parser context
1336 * @nargs: the number of arguments
1338 * function libxslt:test() for testing the extensions support.
1341 xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, int nargs ATTRIBUTE_UNUSED)
1343 xsltTransformContextPtr tctxt;
1346 tctxt = xsltXPathGetTransformContext(ctxt);
1348 if (testData == NULL) {
1349 xsltGenericDebug(xsltGenericDebugContext,
1350 "xsltExtFunctionTest: not initialized,"
1351 " calling xsltGetExtData\n");
1352 data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
1354 xsltTransformError(tctxt, NULL, NULL,
1355 "xsltExtElementTest: not initialized\n");
1359 if (tctxt == NULL) {
1360 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
1361 "xsltExtFunctionTest: failed to get the transformation context\n");
1365 data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
1367 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
1368 "xsltExtFunctionTest: failed to get module data\n");
1371 if (data != testData) {
1372 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
1373 "xsltExtFunctionTest: got wrong module data\n");
1376 #ifdef WITH_XSLT_DEBUG_FUNCTION
1377 xsltGenericDebug(xsltGenericDebugContext,
1378 "libxslt:test() called with %d args\n", nargs);
1383 * xsltExtElementPreCompTest:
1384 * @style: the stylesheet
1385 * @inst: the instruction in the stylesheet
1387 * Process a libxslt:test node
1389 static xsltElemPreCompPtr
1390 xsltExtElementPreCompTest(xsltStylesheetPtr style, xmlNodePtr inst,
1391 xsltTransformFunction function) {
1392 xsltElemPreCompPtr ret;
1394 if (style == NULL) {
1395 xsltTransformError(NULL, NULL, inst,
1396 "xsltExtElementTest: no transformation context\n");
1399 if (testStyleData == NULL) {
1400 xsltGenericDebug(xsltGenericDebugContext,
1401 "xsltExtElementPreCompTest: not initialized,"
1402 " calling xsltStyleGetExtData\n");
1403 xsltStyleGetExtData(style, (const xmlChar *) XSLT_DEFAULT_URL);
1404 if (testStyleData == NULL) {
1405 xsltTransformError(NULL, style, inst,
1406 "xsltExtElementPreCompTest: not initialized\n");
1407 if (style != NULL) style->errors++;
1412 xsltTransformError(NULL, style, inst,
1413 "xsltExtElementPreCompTest: no instruction\n");
1414 if (style != NULL) style->errors++;
1417 ret = xsltNewElemPreComp (style, inst, function);
1422 * xsltExtElementTest:
1423 * @ctxt: an XSLT processing context
1424 * @node: The current node
1425 * @inst: the instruction in the stylesheet
1426 * @comp: precomputed informations
1428 * Process a libxslt:test node
1431 xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node,
1433 xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
1435 xmlNodePtr commentNode;
1437 if (testData == NULL) {
1438 xsltGenericDebug(xsltGenericDebugContext,
1439 "xsltExtElementTest: not initialized,"
1440 " calling xsltGetExtData\n");
1441 xsltGetExtData(ctxt, (const xmlChar *) XSLT_DEFAULT_URL);
1442 if (testData == NULL) {
1443 xsltTransformError(ctxt, NULL, inst,
1444 "xsltExtElementTest: not initialized\n");
1449 xsltTransformError(ctxt, NULL, inst,
1450 "xsltExtElementTest: no transformation context\n");
1454 xsltTransformError(ctxt, NULL, inst,
1455 "xsltExtElementTest: no current node\n");
1459 xsltTransformError(ctxt, NULL, inst,
1460 "xsltExtElementTest: no instruction\n");
1463 if (ctxt->insert == NULL) {
1464 xsltTransformError(ctxt, NULL, inst,
1465 "xsltExtElementTest: no insertion point\n");
1469 xmlNewComment((const xmlChar *)
1470 "libxslt:test element test worked");
1471 xmlAddChild(ctxt->insert, commentNode);
1476 * @ctxt: an XSLT transformation context
1477 * @URI: the namespace URI for the extension
1479 * A function called at initialization time of an XSLT extension module
1481 * Returns a pointer to the module specific data for this transformation
1484 xsltExtInitTest(xsltTransformContextPtr ctxt, const xmlChar * URI) {
1485 if (testStyleData == NULL) {
1486 xsltGenericDebug(xsltGenericErrorContext,
1487 "xsltExtInitTest: not initialized,"
1488 " calling xsltStyleGetExtData\n");
1489 xsltStyleGetExtData(ctxt->style, URI);
1490 if (testStyleData == NULL) {
1491 xsltTransformError(ctxt, NULL, NULL,
1492 "xsltExtInitTest: not initialized\n");
1496 if (testData != NULL) {
1497 xsltTransformError(ctxt, NULL, NULL,
1498 "xsltExtInitTest: already initialized\n");
1501 testData = (void *) "test data";
1502 xsltGenericDebug(xsltGenericDebugContext,
1503 "Registered test module : %s\n", URI);
1509 * xsltExtShutdownTest:
1510 * @ctxt: an XSLT transformation context
1511 * @URI: the namespace URI for the extension
1512 * @data: the data associated to this module
1514 * A function called at shutdown time of an XSLT extension module
1517 xsltExtShutdownTest(xsltTransformContextPtr ctxt,
1518 const xmlChar * URI, void *data) {
1519 if (testData == NULL) {
1520 xsltTransformError(ctxt, NULL, NULL,
1521 "xsltExtShutdownTest: not initialized\n");
1524 if (data != testData) {
1525 xsltTransformError(ctxt, NULL, NULL,
1526 "xsltExtShutdownTest: wrong data\n");
1529 xsltGenericDebug(xsltGenericDebugContext,
1530 "Unregistered test module : %s\n", URI);
1533 * xsltExtStyleInitTest:
1534 * @style: an XSLT stylesheet
1535 * @URI: the namespace URI for the extension
1537 * A function called at initialization time of an XSLT extension module
1539 * Returns a pointer to the module specific data for this transformation
1542 xsltExtStyleInitTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED,
1543 const xmlChar * URI)
1545 if (testStyleData != NULL) {
1546 xsltTransformError(NULL, NULL, NULL,
1547 "xsltExtInitTest: already initialized\n");
1550 testStyleData = (void *) "test data";
1551 xsltGenericDebug(xsltGenericDebugContext,
1552 "Registered test module : %s\n", URI);
1553 return (testStyleData);
1558 * xsltExtStyleShutdownTest:
1559 * @style: an XSLT stylesheet
1560 * @URI: the namespace URI for the extension
1561 * @data: the data associated to this module
1563 * A function called at shutdown time of an XSLT extension module
1566 xsltExtStyleShutdownTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED,
1567 const xmlChar * URI, void *data) {
1568 if (testStyleData == NULL) {
1569 xsltGenericError(xsltGenericErrorContext,
1570 "xsltExtShutdownTest: not initialized\n");
1573 if (data != testStyleData) {
1574 xsltTransformError(NULL, NULL, NULL,
1575 "xsltExtShutdownTest: wrong data\n");
1577 testStyleData = NULL;
1578 xsltGenericDebug(xsltGenericDebugContext,
1579 "Unregistered test module : %s\n", URI);
1583 * xsltRegisterTestModule:
1585 * Registers the test module
1588 xsltRegisterTestModule (void) {
1589 xsltRegisterExtModuleFull((const xmlChar *) XSLT_DEFAULT_URL,
1590 xsltExtInitTest, xsltExtShutdownTest,
1591 xsltExtStyleInitTest,
1592 xsltExtStyleShutdownTest);
1593 xsltRegisterExtModuleFunction((const xmlChar *) "test",
1594 (const xmlChar *) XSLT_DEFAULT_URL,
1595 xsltExtFunctionTest);
1596 xsltRegisterExtModuleElement((const xmlChar *) "test",
1597 (const xmlChar *) XSLT_DEFAULT_URL,
1598 xsltExtElementPreCompTest ,
1599 xsltExtElementTest);
1603 * xsltCleanupGlobals:
1605 * Unregister all global variables set up by the XSLT library
1608 xsltCleanupGlobals(void)
1610 xsltUnregisterAllExtModules();
1611 xsltUnregisterAllExtModuleFunction();
1612 xsltUnregisterAllExtModuleElement();
1613 xsltUnregisterAllExtModuleTopLevel();
1617 xsltDebugDumpExtensionsCallback(void* function ATTRIBUTE_UNUSED,
1618 FILE *output, const xmlChar* name,
1620 const xmlChar* not_used ATTRIBUTE_UNUSED) {
1623 fprintf(output,"{%s}%s\n",URI,name);
1627 * xsltDebugDumpExtensions:
1628 * @output: the FILE * for the output, if NULL stdout is used
1630 * Dumps a list of the registered XSLT extension functions and elements
1633 xsltDebugDumpExtensions(FILE * output)
1637 fprintf(output,"Registered XSLT Extensions\n--------------------------\n");
1638 if (!xsltFunctionsHash)
1639 fprintf(output,"No registered extension functions\n");
1641 fprintf(output,"Registered Extension Functions:\n");
1642 xmlHashScanFull(xsltFunctionsHash,(xmlHashScannerFull)xsltDebugDumpExtensionsCallback,output);
1644 if (!xsltElementsHash)
1645 fprintf(output,"\nNo registered extension elements\n");
1647 fprintf(output,"\nRegistered Extension Elements:\n");
1648 xmlHashScanFull(xsltElementsHash,(xmlHashScannerFull)xsltDebugDumpExtensionsCallback,output);