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.
18 #include <libxml/xmlmemory.h>
19 #include <libxml/tree.h>
20 #include <libxml/hash.h>
21 #include <libxml/xmlerror.h>
22 #include <libxml/parserInternals.h>
23 #include <libxml/xpathInternals.h>
25 #include <libxml/xmlmodule.h>
27 #include <libxml/list.h>
28 #include <libxml/xmlIO.h>
30 #include "xsltInternals.h"
31 #include "xsltutils.h"
33 #include "extensions.h"
36 #include <stdlib.h> /* for _MAX_PATH */
37 #define PATH_MAX _MAX_PATH
40 #ifdef WITH_XSLT_DEBUG
41 #define WITH_XSLT_DEBUG_EXTENSIONS
44 /************************************************************************
46 * Private Types and Globals *
48 ************************************************************************/
50 typedef struct _xsltExtDef xsltExtDef;
51 typedef xsltExtDef *xsltExtDefPtr;
53 struct _xsltExtDef *next;
59 typedef struct _xsltExtModule xsltExtModule;
60 typedef xsltExtModule *xsltExtModulePtr;
61 struct _xsltExtModule {
62 xsltExtInitFunction initFunc;
63 xsltExtShutdownFunction shutdownFunc;
64 xsltStyleExtInitFunction styleInitFunc;
65 xsltStyleExtShutdownFunction styleShutdownFunc;
68 typedef struct _xsltExtData xsltExtData;
69 typedef xsltExtData *xsltExtDataPtr;
71 xsltExtModulePtr extModule;
75 typedef struct _xsltExtElement xsltExtElement;
76 typedef xsltExtElement *xsltExtElementPtr;
77 struct _xsltExtElement {
78 xsltPreComputeFunction precomp;
79 xsltTransformFunction transform;
82 static xmlHashTablePtr xsltExtensionsHash = NULL;
83 static xmlHashTablePtr xsltFunctionsHash = NULL;
84 static xmlHashTablePtr xsltElementsHash = NULL;
85 static xmlHashTablePtr xsltTopLevelsHash = NULL;
86 static xmlHashTablePtr xsltModuleHash = NULL;
88 /************************************************************************
92 ************************************************************************/
96 * @prefix: the extension prefix
97 * @URI: the namespace URI
99 * Create a new XSLT ExtDef
101 * Returns the newly allocated xsltExtDefPtr or NULL in case of error
104 xsltNewExtDef(const xmlChar * prefix, const xmlChar * URI)
108 cur = (xsltExtDefPtr) xmlMalloc(sizeof(xsltExtDef));
110 xsltTransformError(NULL, NULL, NULL,
111 "xsltNewExtDef : malloc failed\n");
114 memset(cur, 0, sizeof(xsltExtDef));
116 cur->prefix = xmlStrdup(prefix);
118 cur->URI = xmlStrdup(URI);
124 * @extensiond: an XSLT extension definition
126 * Free up the memory allocated by @extensiond
129 xsltFreeExtDef(xsltExtDefPtr extensiond)
131 if (extensiond == NULL)
133 if (extensiond->prefix != NULL)
134 xmlFree(extensiond->prefix);
135 if (extensiond->URI != NULL)
136 xmlFree(extensiond->URI);
141 * xsltFreeExtDefList:
142 * @extensiond: an XSLT extension definition list
144 * Free up the memory allocated by all the elements of @extensiond
147 xsltFreeExtDefList(xsltExtDefPtr extensiond)
151 while (extensiond != NULL) {
153 extensiond = extensiond->next;
160 * @initFunc: the module initialization function
161 * @shutdownFunc: the module shutdown function
162 * @styleInitFunc: the stylesheet module data allocator function
163 * @styleShutdownFunc: the stylesheet module data free function
165 * Create a new XSLT extension module
167 * Returns the newly allocated xsltExtModulePtr or NULL in case of error
169 static xsltExtModulePtr
170 xsltNewExtModule(xsltExtInitFunction initFunc,
171 xsltExtShutdownFunction shutdownFunc,
172 xsltStyleExtInitFunction styleInitFunc,
173 xsltStyleExtShutdownFunction styleShutdownFunc)
175 xsltExtModulePtr cur;
177 cur = (xsltExtModulePtr) xmlMalloc(sizeof(xsltExtModule));
179 xsltTransformError(NULL, NULL, NULL,
180 "xsltNewExtModule : malloc failed\n");
183 cur->initFunc = initFunc;
184 cur->shutdownFunc = shutdownFunc;
185 cur->styleInitFunc = styleInitFunc;
186 cur->styleShutdownFunc = styleShutdownFunc;
192 * @ext: an XSLT extension module
194 * Free up the memory allocated by @ext
197 xsltFreeExtModule(xsltExtModulePtr ext)
206 * @extModule: the module
207 * @extData: the associated data
209 * Create a new XSLT extension module data wrapper
211 * Returns the newly allocated xsltExtDataPtr or NULL in case of error
213 static xsltExtDataPtr
214 xsltNewExtData(xsltExtModulePtr extModule, void *extData)
218 if (extModule == NULL)
220 cur = (xsltExtDataPtr) xmlMalloc(sizeof(xsltExtData));
222 xsltTransformError(NULL, NULL, NULL,
223 "xsltNewExtData : malloc failed\n");
226 cur->extModule = extModule;
227 cur->extData = extData;
233 * @ext: an XSLT extension module data wrapper
235 * Free up the memory allocated by @ext
238 xsltFreeExtData(xsltExtDataPtr ext)
247 * @precomp: the pre-computation function
248 * @transform: the transformation function
250 * Create a new XSLT extension element
252 * Returns the newly allocated xsltExtElementPtr or NULL in case of
255 static xsltExtElementPtr
256 xsltNewExtElement(xsltPreComputeFunction precomp,
257 xsltTransformFunction transform)
259 xsltExtElementPtr cur;
261 if (transform == NULL)
264 cur = (xsltExtElementPtr) xmlMalloc(sizeof(xsltExtElement));
266 xsltTransformError(NULL, NULL, NULL,
267 "xsltNewExtElement : malloc failed\n");
270 cur->precomp = precomp;
271 cur->transform = transform;
276 * xsltFreeExtElement:
277 * @ext: an XSLT extension element
279 * Frees up the memory allocated by @ext
282 xsltFreeExtElement(xsltExtElementPtr ext)
291 typedef void (*exsltRegisterFunction) (void);
294 #define PATH_MAX 4096
298 * xsltExtModuleRegisterDynamic:
299 * @URI: the function or element namespace URI
301 * Dynamically loads an extension plugin when available.
303 * The plugin name is derived from the URI by removing the
304 * initial protocol designation, e.g. "http://", then converting
305 * the characters ".", "-", "/", and "\" into "_", the removing
306 * any trailing "/", then concatenating LIBXML_MODULE_EXTENSION.
308 * Plugins are loaded from the directory specified by the
309 * environment variable LIBXSLT_PLUGINS_PATH, or if NULL,
310 * by LIBXSLT_DEFAULT_PLUGINS_PATH() which is determined at
313 * Returns 0 if successful, -1 in case of error.
317 xsltExtModuleRegisterDynamic(const xmlChar * URI)
321 exsltRegisterFunction regfunc;
323 char module_filename[PATH_MAX];
324 const xmlChar *ext_directory = NULL;
325 const xmlChar *protocol = NULL;
326 xmlChar *i, *regfunc_name;
329 /* check for bad inputs */
333 if (NULL == xsltModuleHash) {
334 xsltModuleHash = xmlHashCreate(5);
335 if (xsltModuleHash == NULL)
339 /* have we attempted to register this module already? */
340 seen_before = (int) xmlHashLookup(xsltModuleHash, URI);
341 if (0 != seen_before) {
345 /* transform extension namespace into a module name */
346 protocol = xmlStrstr(URI, BAD_CAST "://");
347 if (protocol == NULL) {
348 ext_name = xmlStrdup(URI);
350 ext_name = xmlStrdup(protocol + 3);
352 if (ext_name == NULL) {
358 if (('/' == *i) || ('\\' == *i) || ('.' == *i) || ('-' == *i))
366 /* determine module directory */
367 ext_directory = (xmlChar *) getenv("LIBXSLT_PLUGINS_PATH");
369 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
370 xsltGenericDebug(xsltGenericDebugContext,
371 "LIBXSLT_PLUGINS_PATH is %s\n", ext_directory);
374 if (NULL == ext_directory)
375 ext_directory = BAD_CAST LIBXSLT_DEFAULT_PLUGINS_PATH();
376 if (NULL == ext_directory)
379 /* build the module filename, and confirm the module exists */
380 xmlStrPrintf((xmlChar *) module_filename, sizeof(module_filename),
382 ext_directory, ext_name, LIBXML_MODULE_EXTENSION);
384 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
385 xsltGenericDebug(xsltGenericDebugContext,
386 "Attempting to load plugin: %s for URI: %s\n",
387 module_filename, URI);
390 if (1 != xmlCheckFilename(module_filename)) {
392 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
393 xsltGenericDebug(xsltGenericDebugContext,
394 "xmlCheckFilename failed for plugin: %s\n", module_filename);
401 /* attempt to open the module */
402 m = xmlModuleOpen(module_filename, 0);
405 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
406 xsltGenericDebug(xsltGenericDebugContext,
407 "xmlModuleOpen failed for plugin: %s\n", module_filename);
414 /* construct initialization func name */
415 regfunc_name = xmlStrdup(ext_name);
416 regfunc_name = xmlStrcat(regfunc_name, BAD_CAST "_init");
418 rc = xmlModuleSymbol(m, (const char *) regfunc_name, (void **) ®func);
420 /* call the module's init function */
423 /* register this module in our hash */
424 xmlHashAddEntry(xsltModuleHash, URI, (void *) m);
427 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
428 xsltGenericDebug(xsltGenericDebugContext,
429 "xmlModuleSymbol failed for plugin: %s, regfunc: %s\n",
430 module_filename, regfunc_name);
433 /* if regfunc not found unload the module immediately */
438 xmlFree(regfunc_name);
439 return (NULL == regfunc) ? -1 : 0;
443 xsltExtModuleRegisterDynamic(const xmlChar * ATTRIBUTE_UNUSED URI)
449 /************************************************************************
451 * The stylesheet extension prefixes handling *
453 ************************************************************************/
458 * @style: an XSLT stylesheet
460 * Free up the memory used by XSLT extensions in a stylesheet
463 xsltFreeExts(xsltStylesheetPtr style)
465 if (style->nsDefs != NULL)
466 xsltFreeExtDefList((xsltExtDefPtr) style->nsDefs);
470 * xsltRegisterExtPrefix:
471 * @style: an XSLT stylesheet
472 * @prefix: the prefix used (optional)
473 * @URI: the URI associated to the extension
475 * Registers an extension namespace
476 * This is called from xslt.c during compile-time.
477 * The given prefix is not needed.
479 * xsltParseExtElemPrefixes() (new function)
480 * xsltRegisterExtPrefix() (old function)
482 * Returns 0 in case of success, 1 if the @URI was already
483 * registered as an extension namespace and
484 * -1 in case of failure
487 xsltRegisterExtPrefix(xsltStylesheetPtr style,
488 const xmlChar * prefix, const xmlChar * URI)
490 xsltExtDefPtr def, ret;
492 if ((style == NULL) || (URI == NULL))
495 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
496 xsltGenericDebug(xsltGenericDebugContext,
497 "Registering extension prefix %s : %s\n", prefix,
500 def = (xsltExtDefPtr) style->nsDefs;
501 #ifdef XSLT_REFACTORED
503 * The extension is associated with a namespace name.
505 while (def != NULL) {
506 if (xmlStrEqual(URI, def->URI))
511 while (def != NULL) {
512 if (xmlStrEqual(prefix, def->prefix))
517 ret = xsltNewExtDef(prefix, URI);
520 ret->next = (xsltExtDefPtr) style->nsDefs;
524 * check wether there is an extension module with a stylesheet
525 * initialization function.
527 #ifdef XSLT_REFACTORED
529 * Don't initialize modules based on specified namespaced via
530 * the attribute "[xsl:]extension-element-prefixes".
533 if (xsltExtensionsHash != NULL) {
534 xsltExtModulePtr module;
536 module = xmlHashLookup(xsltExtensionsHash, URI);
537 if (NULL == module) {
538 if (!xsltExtModuleRegisterDynamic(URI)) {
539 module = xmlHashLookup(xsltExtensionsHash, URI);
542 if (module != NULL) {
543 xsltStyleGetExtData(style, URI);
550 /************************************************************************
552 * The extensions modules interfaces *
554 ************************************************************************/
557 * xsltRegisterExtFunction:
558 * @ctxt: an XSLT transformation context
559 * @name: the name of the element
560 * @URI: the URI associated to the element
561 * @function: the actual implementation which should be called
563 * Registers an extension function
565 * Returns 0 in case of success, -1 in case of failure
568 xsltRegisterExtFunction(xsltTransformContextPtr ctxt, const xmlChar * name,
569 const xmlChar * URI, xmlXPathFunction function)
571 if ((ctxt == NULL) || (name == NULL) ||
572 (URI == NULL) || (function == NULL))
574 if (ctxt->xpathCtxt != NULL) {
575 xmlXPathRegisterFuncNS(ctxt->xpathCtxt, name, URI, function);
577 if (ctxt->extFunctions == NULL)
578 ctxt->extFunctions = xmlHashCreate(10);
579 if (ctxt->extFunctions == NULL)
581 return (xmlHashAddEntry2
582 (ctxt->extFunctions, name, URI, XML_CAST_FPTR(function)));
586 * xsltRegisterExtElement:
587 * @ctxt: an XSLT transformation context
588 * @name: the name of the element
589 * @URI: the URI associated to the element
590 * @function: the actual implementation which should be called
592 * Registers an extension element
594 * Returns 0 in case of success, -1 in case of failure
597 xsltRegisterExtElement(xsltTransformContextPtr ctxt, const xmlChar * name,
598 const xmlChar * URI, xsltTransformFunction function)
600 if ((ctxt == NULL) || (name == NULL) ||
601 (URI == NULL) || (function == NULL))
603 if (ctxt->extElements == NULL)
604 ctxt->extElements = xmlHashCreate(10);
605 if (ctxt->extElements == NULL)
607 return (xmlHashAddEntry2
608 (ctxt->extElements, name, URI, XML_CAST_FPTR(function)));
613 * @ctxt: an XSLT transformation context
615 * Free the XSLT extension data
618 xsltFreeCtxtExts(xsltTransformContextPtr ctxt)
620 if (ctxt->extElements != NULL)
621 xmlHashFree(ctxt->extElements, NULL);
622 if (ctxt->extFunctions != NULL)
623 xmlHashFree(ctxt->extFunctions, NULL);
627 * xsltStyleGetStylesheetExtData:
628 * @style: an XSLT stylesheet
629 * @URI: the URI associated to the exension module
631 * Fires the compile-time initialization callback
632 * of an extension module and returns a container
633 * holding the user-data (retrieved via the callback).
635 * Returns the create module-data container
636 * or NULL if such a module was not registered.
638 static xsltExtDataPtr
639 xsltStyleInitializeStylesheetModule(xsltStylesheetPtr style,
642 xsltExtDataPtr dataContainer;
643 void *userData = NULL;
644 xsltExtModulePtr module;
646 if ((style == NULL) || (URI == NULL))
649 if (xsltExtensionsHash == NULL) {
650 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
651 xsltGenericDebug(xsltGenericDebugContext,
652 "Not registered extension module: %s\n", URI);
657 module = xmlHashLookup(xsltExtensionsHash, URI);
658 if (module == NULL) {
659 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
660 xsltGenericDebug(xsltGenericDebugContext,
661 "Not registered extension module: %s\n", URI);
666 * The specified module was registered so initialize it.
668 if (style->extInfos == NULL) {
669 style->extInfos = xmlHashCreate(10);
670 if (style->extInfos == NULL)
674 * Fire the initialization callback if available.
676 if (module->styleInitFunc == NULL) {
677 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
678 xsltGenericDebug(xsltGenericDebugContext,
679 "Initializing module with *no* callback: %s\n", URI);
682 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
683 xsltGenericDebug(xsltGenericDebugContext,
684 "Initializing module with callback: %s\n", URI);
687 * Fire the initialization callback.
689 userData = module->styleInitFunc(style, URI);
692 * Store the user-data in the context of the given stylesheet.
694 dataContainer = xsltNewExtData(module, userData);
695 if (dataContainer == NULL)
698 if (xmlHashAddEntry(style->extInfos, URI,
699 (void *) dataContainer) < 0)
701 xsltTransformError(NULL, style, NULL,
702 "Failed to register module '%s'.\n", URI);
704 if (module->styleShutdownFunc)
705 module->styleShutdownFunc(style, URI, userData);
706 xsltFreeExtData(dataContainer);
710 return(dataContainer);
714 * xsltStyleGetExtData:
715 * @style: an XSLT stylesheet
716 * @URI: the URI associated to the exension module
718 * Retrieve the data associated to the extension module
719 * in this given stylesheet.
721 * xsltRegisterExtPrefix(),
722 * ( xsltExtElementPreCompTest(), xsltExtInitTest )
724 * Returns the pointer or NULL if not present
727 xsltStyleGetExtData(xsltStylesheetPtr style, const xmlChar * URI)
729 xsltExtDataPtr dataContainer = NULL;
730 xsltStylesheetPtr tmpStyle;
732 if ((style == NULL) || (URI == NULL) ||
733 (xsltExtensionsHash == NULL))
737 #ifdef XSLT_REFACTORED
739 * This is intended for global storage, so only the main
740 * stylesheet will hold the data.
743 while (tmpStyle->parent != NULL)
744 tmpStyle = tmpStyle->parent;
745 if (tmpStyle->extInfos != NULL) {
747 (xsltExtDataPtr) xmlHashLookup(tmpStyle->extInfos, URI);
748 if (dataContainer != NULL) {
750 * The module was already initialized in the context
751 * of this stylesheet; just return the user-data that
754 return(dataContainer->extData);
762 while (tmpStyle != NULL) {
763 if (tmpStyle->extInfos != NULL) {
765 (xsltExtDataPtr) xmlHashLookup(tmpStyle->extInfos, URI);
766 if (dataContainer != NULL) {
767 return(dataContainer->extData);
770 tmpStyle = xsltNextImport(tmpStyle);
776 xsltStyleInitializeStylesheetModule(tmpStyle, URI);
777 if (dataContainer != NULL)
778 return (dataContainer->extData);
783 * xsltStyleGetExtDataPerStylesheetLevel:
784 * @style: an XSLT stylesheet
785 * @URI: the URI associated to the exension module
787 * Retrieve the data associated to the extension module in this given
790 * Returns the pointer or NULL if not present
793 xsltStyleStylesheetLevelGetExtData(xsltStylesheetPtr style,
796 xsltExtDataPtr dataContainer = NULL;
798 if ((style == NULL) || (URI == NULL) ||
799 (xsltExtensionsHash == NULL))
802 if (style->extInfos != NULL) {
803 dataContainer = (xsltExtDataPtr) xmlHashLookup(style->extInfos, URI);
805 * The module was already initialized in the context
806 * of this stylesheet; just return the user-data that
810 return(dataContainer->extData);
814 xsltStyleInitializeStylesheetModule(style, URI);
815 if (dataContainer != NULL)
816 return (dataContainer->extData);
822 * @ctxt: an XSLT transformation context
823 * @URI: the URI associated to the exension module
825 * Retrieve the data associated to the extension module in this given
828 * Returns the pointer or NULL if not present
831 xsltGetExtData(xsltTransformContextPtr ctxt, const xmlChar * URI)
835 if ((ctxt == NULL) || (URI == NULL))
837 if (ctxt->extInfos == NULL) {
838 ctxt->extInfos = xmlHashCreate(10);
839 if (ctxt->extInfos == NULL)
843 data = (xsltExtDataPtr) xmlHashLookup(ctxt->extInfos, URI);
847 xsltExtModulePtr module;
849 module = xmlHashLookup(xsltExtensionsHash, URI);
850 if (module == NULL) {
851 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
852 xsltGenericDebug(xsltGenericDebugContext,
853 "Not registered extension module: %s\n", URI);
857 if (module->initFunc == NULL)
860 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
861 xsltGenericDebug(xsltGenericDebugContext,
862 "Initializing module: %s\n", URI);
865 extData = module->initFunc(ctxt, URI);
869 data = xsltNewExtData(module, extData);
872 if (xmlHashAddEntry(ctxt->extInfos, URI, (void *) data) < 0) {
873 xsltTransformError(ctxt, NULL, NULL,
874 "Failed to register module data: %s\n",
876 if (module->shutdownFunc)
877 module->shutdownFunc(ctxt, URI, extData);
878 xsltFreeExtData(data);
883 return (data->extData);
886 typedef struct _xsltInitExtCtxt xsltInitExtCtxt;
887 struct _xsltInitExtCtxt {
888 xsltTransformContextPtr ctxt;
894 * @styleData: the registered stylesheet data for the module
895 * @ctxt: the XSLT transformation context + the return value
896 * @URI: the extension URI
898 * Initializes an extension module
901 xsltInitCtxtExt(xsltExtDataPtr styleData, xsltInitExtCtxt * ctxt,
904 xsltExtModulePtr module;
905 xsltExtDataPtr ctxtData;
908 if ((styleData == NULL) || (ctxt == NULL) || (URI == NULL) ||
910 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
911 xsltGenericDebug(xsltGenericDebugContext,
912 "xsltInitCtxtExt: NULL param or error\n");
916 module = styleData->extModule;
917 if ((module == NULL) || (module->initFunc == NULL)) {
918 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
919 xsltGenericDebug(xsltGenericDebugContext,
920 "xsltInitCtxtExt: no module or no initFunc\n");
925 ctxtData = (xsltExtDataPtr) xmlHashLookup(ctxt->ctxt->extInfos, URI);
926 if (ctxtData != NULL) {
927 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
928 xsltGenericDebug(xsltGenericDebugContext,
929 "xsltInitCtxtExt: already initialized\n");
934 extData = module->initFunc(ctxt->ctxt, URI);
935 if (extData == NULL) {
936 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
937 xsltGenericDebug(xsltGenericDebugContext,
938 "xsltInitCtxtExt: no extData\n");
941 ctxtData = xsltNewExtData(module, extData);
942 if (ctxtData == NULL) {
947 if (ctxt->ctxt->extInfos == NULL)
948 ctxt->ctxt->extInfos = xmlHashCreate(10);
949 if (ctxt->ctxt->extInfos == NULL) {
954 if (xmlHashAddEntry(ctxt->ctxt->extInfos, URI, ctxtData) < 0) {
955 xsltGenericError(xsltGenericErrorContext,
956 "Failed to register module data: %s\n", URI);
957 if (module->shutdownFunc)
958 module->shutdownFunc(ctxt->ctxt, URI, extData);
959 xsltFreeExtData(ctxtData);
963 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
964 xsltGenericDebug(xsltGenericDebugContext, "Registered module %s\n",
972 * @ctxt: an XSLT transformation context
974 * Initialize the set of modules with registered stylesheet data
976 * Returns the number of modules initialized or -1 in case of error
979 xsltInitCtxtExts(xsltTransformContextPtr ctxt)
981 xsltStylesheetPtr style;
994 while (style != NULL) {
995 if (style->extInfos != NULL) {
996 xmlHashScan(style->extInfos,
997 (xmlHashScanner) xsltInitCtxtExt, &ctx);
1001 style = xsltNextImport(style);
1003 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
1004 xsltGenericDebug(xsltGenericDebugContext, "Registered %d modules\n",
1011 * xsltShutdownCtxtExt:
1012 * @data: the registered data for the module
1013 * @ctxt: the XSLT transformation context
1014 * @URI: the extension URI
1016 * Shutdown an extension module loaded
1019 xsltShutdownCtxtExt(xsltExtDataPtr data, xsltTransformContextPtr ctxt,
1020 const xmlChar * URI)
1022 xsltExtModulePtr module;
1024 if ((data == NULL) || (ctxt == NULL) || (URI == NULL))
1026 module = data->extModule;
1027 if ((module == NULL) || (module->shutdownFunc == NULL))
1030 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
1031 xsltGenericDebug(xsltGenericDebugContext,
1032 "Shutting down module : %s\n", URI);
1034 module->shutdownFunc(ctxt, URI, data->extData);
1038 * xsltShutdownCtxtExts:
1039 * @ctxt: an XSLT transformation context
1041 * Shutdown the set of modules loaded
1044 xsltShutdownCtxtExts(xsltTransformContextPtr ctxt)
1048 if (ctxt->extInfos == NULL)
1050 xmlHashScan(ctxt->extInfos, (xmlHashScanner) xsltShutdownCtxtExt,
1052 xmlHashFree(ctxt->extInfos, (xmlHashDeallocator) xsltFreeExtData);
1053 ctxt->extInfos = NULL;
1058 * @data: the registered data for the module
1059 * @ctxt: the XSLT stylesheet
1060 * @URI: the extension URI
1062 * Shutdown an extension module loaded
1065 xsltShutdownExt(xsltExtDataPtr data, xsltStylesheetPtr style,
1066 const xmlChar * URI)
1068 xsltExtModulePtr module;
1070 if ((data == NULL) || (style == NULL) || (URI == NULL))
1072 module = data->extModule;
1073 if ((module == NULL) || (module->styleShutdownFunc == NULL))
1076 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
1077 xsltGenericDebug(xsltGenericDebugContext,
1078 "Shutting down module : %s\n", URI);
1080 module->styleShutdownFunc(style, URI, data->extData);
1082 * Don't remove the entry from the hash table here, since
1083 * this will produce segfaults - this fixes bug #340624.
1085 * xmlHashRemoveEntry(style->extInfos, URI,
1086 * (xmlHashDeallocator) xsltFreeExtData);
1092 * @style: an XSLT stylesheet
1094 * Shutdown the set of modules loaded
1097 xsltShutdownExts(xsltStylesheetPtr style)
1101 if (style->extInfos == NULL)
1103 xmlHashScan(style->extInfos, (xmlHashScanner) xsltShutdownExt, style);
1104 xmlHashFree(style->extInfos, (xmlHashDeallocator) xsltFreeExtData);
1105 style->extInfos = NULL;
1109 * xsltCheckExtPrefix:
1110 * @style: the stylesheet
1111 * @URI: the namespace URI (possibly NULL)
1113 * Check if the given prefix is one of the declared extensions.
1114 * This is intended to be called only at compile-time.
1116 * xsltGetInheritedNsList() (xslt.c)
1117 * xsltParseTemplateContent (xslt.c)
1119 * Returns 1 if this is an extension, 0 otherwise
1122 xsltCheckExtPrefix(xsltStylesheetPtr style, const xmlChar * URI)
1124 #ifdef XSLT_REFACTORED
1125 if ((style == NULL) || (style->compCtxt == NULL) ||
1126 (XSLT_CCTXT(style)->inode == NULL) ||
1127 (XSLT_CCTXT(style)->inode->extElemNs == NULL))
1130 * Lookup the extension namespaces registered
1131 * at the current node in the stylesheet's tree.
1133 if (XSLT_CCTXT(style)->inode->extElemNs != NULL) {
1135 xsltPointerListPtr list = XSLT_CCTXT(style)->inode->extElemNs;
1137 for (i = 0; i < list->number; i++) {
1138 if (xmlStrEqual((const xmlChar *) list->items[i],
1148 if ((style == NULL) || (style->nsDefs == NULL))
1151 URI = BAD_CAST "#default";
1152 cur = (xsltExtDefPtr) style->nsDefs;
1153 while (cur != NULL) {
1155 * NOTE: This was change to work on namespace names rather
1156 * than namespace prefixes. This fixes bug #339583.
1157 * TODO: Consider renaming the field "prefix" of xsltExtDef
1160 if (xmlStrEqual(URI, cur->prefix))
1169 * xsltRegisterExtModuleFull:
1170 * @URI: URI associated to this module
1171 * @initFunc: the module initialization function
1172 * @shutdownFunc: the module shutdown function
1173 * @styleInitFunc: the module initialization function
1174 * @styleShutdownFunc: the module shutdown function
1176 * Register an XSLT extension module to the library.
1178 * Returns 0 if sucessful, -1 in case of error
1181 xsltRegisterExtModuleFull(const xmlChar * URI,
1182 xsltExtInitFunction initFunc,
1183 xsltExtShutdownFunction shutdownFunc,
1184 xsltStyleExtInitFunction styleInitFunc,
1185 xsltStyleExtShutdownFunction styleShutdownFunc)
1188 xsltExtModulePtr module;
1190 if ((URI == NULL) || (initFunc == NULL))
1192 if (xsltExtensionsHash == NULL)
1193 xsltExtensionsHash = xmlHashCreate(10);
1195 if (xsltExtensionsHash == NULL)
1198 module = xmlHashLookup(xsltExtensionsHash, URI);
1199 if (module != NULL) {
1200 if ((module->initFunc == initFunc) &&
1201 (module->shutdownFunc == shutdownFunc))
1205 module = xsltNewExtModule(initFunc, shutdownFunc,
1206 styleInitFunc, styleShutdownFunc);
1209 ret = xmlHashAddEntry(xsltExtensionsHash, URI, (void *) module);
1214 * xsltRegisterExtModule:
1215 * @URI: URI associated to this module
1216 * @initFunc: the module initialization function
1217 * @shutdownFunc: the module shutdown function
1219 * Register an XSLT extension module to the library.
1221 * Returns 0 if sucessful, -1 in case of error
1224 xsltRegisterExtModule(const xmlChar * URI,
1225 xsltExtInitFunction initFunc,
1226 xsltExtShutdownFunction shutdownFunc)
1228 return xsltRegisterExtModuleFull(URI, initFunc, shutdownFunc,
1233 * xsltUnregisterExtModule:
1234 * @URI: URI associated to this module
1236 * Unregister an XSLT extension module from the library.
1238 * Returns 0 if sucessful, -1 in case of error
1241 xsltUnregisterExtModule(const xmlChar * URI)
1247 if (xsltExtensionsHash == NULL)
1251 xmlHashRemoveEntry(xsltExtensionsHash, URI,
1252 (xmlHashDeallocator) xsltFreeExtModule);
1257 * xsltUnregisterAllExtModules:
1259 * Unregister all the XSLT extension module from the library.
1262 xsltUnregisterAllExtModules(void)
1264 if (xsltExtensionsHash == NULL)
1267 xmlHashFree(xsltExtensionsHash,
1268 (xmlHashDeallocator) xsltFreeExtModule);
1269 xsltExtensionsHash = NULL;
1273 * xsltXPathGetTransformContext:
1274 * @ctxt: an XPath transformation context
1276 * Provides the XSLT transformation context from the XPath transformation
1277 * context. This is useful when an XPath function in the extension module
1278 * is called by the XPath interpreter and that the XSLT context is needed
1279 * for example to retrieve the associated data pertaining to this XSLT
1282 * Returns the XSLT transformation context or NULL in case of error.
1284 xsltTransformContextPtr
1285 xsltXPathGetTransformContext(xmlXPathParserContextPtr ctxt)
1287 if ((ctxt == NULL) || (ctxt->context == NULL))
1289 return (ctxt->context->extra);
1293 * xsltRegisterExtModuleFunction:
1294 * @name: the function name
1295 * @URI: the function namespace URI
1296 * @function: the function callback
1298 * Registers an extension module function.
1300 * Returns 0 if successful, -1 in case of error.
1303 xsltRegisterExtModuleFunction(const xmlChar * name, const xmlChar * URI,
1304 xmlXPathFunction function)
1306 if ((name == NULL) || (URI == NULL) || (function == NULL))
1309 if (xsltFunctionsHash == NULL)
1310 xsltFunctionsHash = xmlHashCreate(10);
1311 if (xsltFunctionsHash == NULL)
1314 xmlHashUpdateEntry2(xsltFunctionsHash, name, URI,
1315 XML_CAST_FPTR(function), NULL);
1321 * xsltExtModuleFunctionLookup:
1322 * @name: the function name
1323 * @URI: the function namespace URI
1325 * Looks up an extension module function
1327 * Returns the function if found, NULL otherwise.
1330 xsltExtModuleFunctionLookup(const xmlChar * name, const xmlChar * URI)
1332 xmlXPathFunction ret;
1334 if ((xsltFunctionsHash == NULL) || (name == NULL) || (URI == NULL))
1337 XML_CAST_FPTR(ret) = xmlHashLookup2(xsltFunctionsHash, name, URI);
1339 /* if lookup fails, attempt a dynamic load on supported platforms */
1341 if (!xsltExtModuleRegisterDynamic(URI)) {
1342 XML_CAST_FPTR(ret) =
1343 xmlHashLookup2(xsltFunctionsHash, name, URI);
1351 * xsltUnregisterExtModuleFunction:
1352 * @name: the function name
1353 * @URI: the function namespace URI
1355 * Unregisters an extension module function
1357 * Returns 0 if successful, -1 in case of error.
1360 xsltUnregisterExtModuleFunction(const xmlChar * name, const xmlChar * URI)
1362 if ((xsltFunctionsHash == NULL) || (name == NULL) || (URI == NULL))
1365 return xmlHashRemoveEntry2(xsltFunctionsHash, name, URI, NULL);
1369 * xsltUnregisterAllExtModuleFunction:
1371 * Unregisters all extension module function
1374 xsltUnregisterAllExtModuleFunction(void)
1376 xmlHashFree(xsltFunctionsHash, NULL);
1377 xsltFunctionsHash = NULL;
1382 * xsltNewElemPreComp:
1383 * @style: the XSLT stylesheet
1384 * @inst: the element node
1385 * @function: the transform function
1387 * Creates and initializes an #xsltElemPreComp
1389 * Returns the new and initialized #xsltElemPreComp
1392 xsltNewElemPreComp(xsltStylesheetPtr style, xmlNodePtr inst,
1393 xsltTransformFunction function)
1395 xsltElemPreCompPtr cur;
1397 cur = (xsltElemPreCompPtr) xmlMalloc(sizeof(xsltElemPreComp));
1399 xsltTransformError(NULL, style, NULL,
1400 "xsltNewExtElement : malloc failed\n");
1403 memset(cur, 0, sizeof(xsltElemPreComp));
1405 xsltInitElemPreComp(cur, style, inst, function,
1406 (xsltElemPreCompDeallocator) xmlFree);
1412 * xsltInitElemPreComp:
1413 * @comp: an #xsltElemPreComp (or generally a derived structure)
1414 * @style: the XSLT stylesheet
1415 * @inst: the element node
1416 * @function: the transform function
1417 * @freeFunc: the @comp deallocator
1419 * Initializes an existing #xsltElemPreComp structure. This is usefull
1420 * when extending an #xsltElemPreComp to store precomputed data.
1421 * This function MUST be called on any extension element precomputed
1425 xsltInitElemPreComp(xsltElemPreCompPtr comp, xsltStylesheetPtr style,
1426 xmlNodePtr inst, xsltTransformFunction function,
1427 xsltElemPreCompDeallocator freeFunc)
1429 comp->type = XSLT_FUNC_EXTENSION;
1430 comp->func = function;
1432 comp->free = freeFunc;
1434 comp->next = style->preComps;
1435 style->preComps = comp;
1439 * xsltPreComputeExtModuleElement:
1440 * @style: the stylesheet
1441 * @inst: the element node
1443 * Precomputes an extension module element
1445 * Returns the precomputed data
1448 xsltPreComputeExtModuleElement(xsltStylesheetPtr style, xmlNodePtr inst)
1450 xsltExtElementPtr ext;
1451 xsltElemPreCompPtr comp = NULL;
1453 if ((style == NULL) || (inst == NULL) ||
1454 (inst->type != XML_ELEMENT_NODE) || (inst->ns == NULL))
1457 ext = (xsltExtElementPtr)
1458 xmlHashLookup2(xsltElementsHash, inst->name, inst->ns->href);
1460 * EXT TODO: Now what?
1465 if (ext->precomp != NULL) {
1467 * REVISIT TODO: Check if the text below is correct.
1468 * This will return a xsltElemPreComp structure or NULL.
1469 * 1) If the the author of the extension needs a
1470 * custom structure to hold the specific values of
1471 * this extension, he will derive a structure based on
1472 * xsltElemPreComp; thus we obviously *cannot* refactor
1473 * the xsltElemPreComp structure, since all already derived
1474 * user-defined strucures will break.
1475 * Example: For the extension xsl:document,
1476 * in xsltDocumentComp() (preproc.c), the structure
1477 * xsltStyleItemDocument is allocated, filled with
1478 * specific values and returned.
1479 * 2) If the author needs no values to be stored in
1480 * this structure, then he'll return NULL;
1482 comp = ext->precomp(style, inst, ext->transform);
1486 * Default creation of a xsltElemPreComp structure, if
1487 * the author of this extension did not create a custom
1490 comp = xsltNewElemPreComp(style, inst, ext->transform);
1497 * xsltRegisterExtModuleElement:
1498 * @name: the element name
1499 * @URI: the element namespace URI
1500 * @precomp: the pre-computation callback
1501 * @transform: the transformation callback
1503 * Registers an extension module element.
1505 * Returns 0 if successful, -1 in case of error.
1508 xsltRegisterExtModuleElement(const xmlChar * name, const xmlChar * URI,
1509 xsltPreComputeFunction precomp,
1510 xsltTransformFunction transform)
1512 xsltExtElementPtr ext;
1514 if ((name == NULL) || (URI == NULL) || (transform == NULL))
1517 if (xsltElementsHash == NULL)
1518 xsltElementsHash = xmlHashCreate(10);
1519 if (xsltElementsHash == NULL)
1522 ext = xsltNewExtElement(precomp, transform);
1526 xmlHashUpdateEntry2(xsltElementsHash, name, URI, (void *) ext,
1527 (xmlHashDeallocator) xsltFreeExtElement);
1533 * xsltExtElementLookup:
1534 * @ctxt: an XSLT process context
1535 * @name: the element name
1536 * @URI: the element namespace URI
1538 * Looks up an extension element. @ctxt can be NULL to search only in
1541 * Returns the element callback or NULL if not found
1543 xsltTransformFunction
1544 xsltExtElementLookup(xsltTransformContextPtr ctxt,
1545 const xmlChar * name, const xmlChar * URI)
1547 xsltTransformFunction ret;
1549 if ((name == NULL) || (URI == NULL))
1552 if ((ctxt != NULL) && (ctxt->extElements != NULL)) {
1553 XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->extElements, name, URI);
1557 return xsltExtModuleElementLookup(name, URI);
1561 * xsltExtModuleElementLookup:
1562 * @name: the element name
1563 * @URI: the element namespace URI
1565 * Looks up an extension module element
1567 * Returns the callback function if found, NULL otherwise.
1569 xsltTransformFunction
1570 xsltExtModuleElementLookup(const xmlChar * name, const xmlChar * URI)
1572 xsltExtElementPtr ext;
1574 if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL))
1577 ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
1579 /* if function lookup fails, attempt a dynamic load on supported platforms */
1580 ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
1582 if (!xsltExtModuleRegisterDynamic(URI)) {
1583 ext = (xsltExtElementPtr)
1584 xmlHashLookup2(xsltElementsHash, name, URI);
1590 return (ext->transform);
1594 * xsltExtModuleElementPreComputeLookup:
1595 * @name: the element name
1596 * @URI: the element namespace URI
1598 * Looks up an extension module element pre-computation function
1600 * Returns the callback function if found, NULL otherwise.
1602 xsltPreComputeFunction
1603 xsltExtModuleElementPreComputeLookup(const xmlChar * name,
1604 const xmlChar * URI)
1606 xsltExtElementPtr ext;
1608 if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL))
1611 ext = (xsltExtElementPtr) xmlHashLookup2(xsltElementsHash, name, URI);
1614 if (!xsltExtModuleRegisterDynamic(URI)) {
1615 ext = (xsltExtElementPtr)
1616 xmlHashLookup2(xsltElementsHash, name, URI);
1622 return (ext->precomp);
1626 * xsltUnregisterExtModuleElement:
1627 * @name: the element name
1628 * @URI: the element namespace URI
1630 * Unregisters an extension module element
1632 * Returns 0 if successful, -1 in case of error.
1635 xsltUnregisterExtModuleElement(const xmlChar * name, const xmlChar * URI)
1637 if ((xsltElementsHash == NULL) || (name == NULL) || (URI == NULL))
1640 return xmlHashRemoveEntry2(xsltElementsHash, name, URI,
1641 (xmlHashDeallocator) xsltFreeExtElement);
1645 * xsltUnregisterAllExtModuleElement:
1647 * Unregisters all extension module element
1650 xsltUnregisterAllExtModuleElement(void)
1652 xmlHashFree(xsltElementsHash, (xmlHashDeallocator) xsltFreeExtElement);
1653 xsltElementsHash = NULL;
1657 * xsltRegisterExtModuleTopLevel:
1658 * @name: the top-level element name
1659 * @URI: the top-level element namespace URI
1660 * @function: the top-level element callback
1662 * Registers an extension module top-level element.
1664 * Returns 0 if successful, -1 in case of error.
1667 xsltRegisterExtModuleTopLevel(const xmlChar * name, const xmlChar * URI,
1668 xsltTopLevelFunction function)
1670 if ((name == NULL) || (URI == NULL) || (function == NULL))
1673 if (xsltTopLevelsHash == NULL)
1674 xsltTopLevelsHash = xmlHashCreate(10);
1675 if (xsltTopLevelsHash == NULL)
1678 xmlHashUpdateEntry2(xsltTopLevelsHash, name, URI,
1679 XML_CAST_FPTR(function), NULL);
1685 * xsltExtModuleTopLevelLookup:
1686 * @name: the top-level element name
1687 * @URI: the top-level element namespace URI
1689 * Looks up an extension module top-level element
1691 * Returns the callback function if found, NULL otherwise.
1693 xsltTopLevelFunction
1694 xsltExtModuleTopLevelLookup(const xmlChar * name, const xmlChar * URI)
1696 xsltTopLevelFunction ret;
1698 if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL))
1701 XML_CAST_FPTR(ret) = xmlHashLookup2(xsltTopLevelsHash, name, URI);
1703 /* if lookup fails, attempt a dynamic load on supported platforms */
1705 if (!xsltExtModuleRegisterDynamic(URI)) {
1706 XML_CAST_FPTR(ret) = xmlHashLookup2(xsltTopLevelsHash, name, URI);
1714 * xsltUnregisterExtModuleTopLevel:
1715 * @name: the top-level element name
1716 * @URI: the top-level element namespace URI
1718 * Unregisters an extension module top-level element
1720 * Returns 0 if successful, -1 in case of error.
1723 xsltUnregisterExtModuleTopLevel(const xmlChar * name, const xmlChar * URI)
1725 if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL))
1728 return xmlHashRemoveEntry2(xsltTopLevelsHash, name, URI, NULL);
1732 * xsltUnregisterAllExtModuleTopLevel:
1734 * Unregisters all extension module function
1737 xsltUnregisterAllExtModuleTopLevel(void)
1739 xmlHashFree(xsltTopLevelsHash, NULL);
1740 xsltTopLevelsHash = NULL;
1745 * @style: pointer to a stylesheet
1746 * @URI: the namespace URI desired
1748 * looks up URI in extInfos of the stylesheet
1750 * returns a pointer to the hash table if found, else NULL
1753 xsltGetExtInfo(xsltStylesheetPtr style, const xmlChar * URI)
1755 xsltExtDataPtr data;
1758 * TODO: Why do we have a return type of xmlHashTablePtr?
1759 * Is the user-allocated data for extension modules expected
1760 * to be a xmlHashTablePtr only? Or is this intended for
1761 * the EXSLT module only?
1764 if (style != NULL && style->extInfos != NULL) {
1765 data = xmlHashLookup(style->extInfos, URI);
1766 if (data != NULL && data->extData != NULL)
1767 return data->extData;
1772 /************************************************************************
1774 * Test module http://xmlsoft.org/XSLT/ *
1776 ************************************************************************/
1778 /************************************************************************
1780 * Test of the extension module API *
1782 ************************************************************************/
1784 static xmlChar *testData = NULL;
1785 static xmlChar *testStyleData = NULL;
1788 * xsltExtFunctionTest:
1789 * @ctxt: the XPath Parser context
1790 * @nargs: the number of arguments
1792 * function libxslt:test() for testing the extensions support.
1795 xsltExtFunctionTest(xmlXPathParserContextPtr ctxt,
1796 int nargs ATTRIBUTE_UNUSED)
1798 xsltTransformContextPtr tctxt;
1801 tctxt = xsltXPathGetTransformContext(ctxt);
1803 if (testData == NULL) {
1804 xsltGenericDebug(xsltGenericDebugContext,
1805 "xsltExtFunctionTest: not initialized,"
1806 " calling xsltGetExtData\n");
1807 data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
1809 xsltTransformError(tctxt, NULL, NULL,
1810 "xsltExtElementTest: not initialized\n");
1814 if (tctxt == NULL) {
1815 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
1816 "xsltExtFunctionTest: failed to get the transformation context\n");
1820 data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
1822 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
1823 "xsltExtFunctionTest: failed to get module data\n");
1826 if (data != testData) {
1827 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
1828 "xsltExtFunctionTest: got wrong module data\n");
1831 #ifdef WITH_XSLT_DEBUG_FUNCTION
1832 xsltGenericDebug(xsltGenericDebugContext,
1833 "libxslt:test() called with %d args\n", nargs);
1838 * xsltExtElementPreCompTest:
1839 * @style: the stylesheet
1840 * @inst: the instruction in the stylesheet
1842 * Process a libxslt:test node
1844 static xsltElemPreCompPtr
1845 xsltExtElementPreCompTest(xsltStylesheetPtr style, xmlNodePtr inst,
1846 xsltTransformFunction function)
1848 xsltElemPreCompPtr ret;
1850 if (style == NULL) {
1851 xsltTransformError(NULL, NULL, inst,
1852 "xsltExtElementTest: no transformation context\n");
1855 if (testStyleData == NULL) {
1856 xsltGenericDebug(xsltGenericDebugContext,
1857 "xsltExtElementPreCompTest: not initialized,"
1858 " calling xsltStyleGetExtData\n");
1859 xsltStyleGetExtData(style, (const xmlChar *) XSLT_DEFAULT_URL);
1860 if (testStyleData == NULL) {
1861 xsltTransformError(NULL, style, inst,
1862 "xsltExtElementPreCompTest: not initialized\n");
1869 xsltTransformError(NULL, style, inst,
1870 "xsltExtElementPreCompTest: no instruction\n");
1875 ret = xsltNewElemPreComp(style, inst, function);
1880 * xsltExtElementTest:
1881 * @ctxt: an XSLT processing context
1882 * @node: The current node
1883 * @inst: the instruction in the stylesheet
1884 * @comp: precomputed informations
1886 * Process a libxslt:test node
1889 xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node,
1891 xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
1893 xmlNodePtr commentNode;
1895 if (testData == NULL) {
1896 xsltGenericDebug(xsltGenericDebugContext,
1897 "xsltExtElementTest: not initialized,"
1898 " calling xsltGetExtData\n");
1899 xsltGetExtData(ctxt, (const xmlChar *) XSLT_DEFAULT_URL);
1900 if (testData == NULL) {
1901 xsltTransformError(ctxt, NULL, inst,
1902 "xsltExtElementTest: not initialized\n");
1907 xsltTransformError(ctxt, NULL, inst,
1908 "xsltExtElementTest: no transformation context\n");
1912 xsltTransformError(ctxt, NULL, inst,
1913 "xsltExtElementTest: no current node\n");
1917 xsltTransformError(ctxt, NULL, inst,
1918 "xsltExtElementTest: no instruction\n");
1921 if (ctxt->insert == NULL) {
1922 xsltTransformError(ctxt, NULL, inst,
1923 "xsltExtElementTest: no insertion point\n");
1926 commentNode = xmlNewComment((const xmlChar *)
1927 "libxslt:test element test worked");
1928 xmlAddChild(ctxt->insert, commentNode);
1933 * @ctxt: an XSLT transformation context
1934 * @URI: the namespace URI for the extension
1936 * A function called at initialization time of an XSLT extension module
1938 * Returns a pointer to the module specific data for this transformation
1941 xsltExtInitTest(xsltTransformContextPtr ctxt, const xmlChar * URI)
1943 if (testStyleData == NULL) {
1944 xsltGenericDebug(xsltGenericErrorContext,
1945 "xsltExtInitTest: not initialized,"
1946 " calling xsltStyleGetExtData\n");
1947 xsltStyleGetExtData(ctxt->style, URI);
1948 if (testStyleData == NULL) {
1949 xsltTransformError(ctxt, NULL, NULL,
1950 "xsltExtInitTest: not initialized\n");
1954 if (testData != NULL) {
1955 xsltTransformError(ctxt, NULL, NULL,
1956 "xsltExtInitTest: already initialized\n");
1959 testData = (void *) "test data";
1960 xsltGenericDebug(xsltGenericDebugContext,
1961 "Registered test module : %s\n", URI);
1967 * xsltExtShutdownTest:
1968 * @ctxt: an XSLT transformation context
1969 * @URI: the namespace URI for the extension
1970 * @data: the data associated to this module
1972 * A function called at shutdown time of an XSLT extension module
1975 xsltExtShutdownTest(xsltTransformContextPtr ctxt,
1976 const xmlChar * URI, void *data)
1978 if (testData == NULL) {
1979 xsltTransformError(ctxt, NULL, NULL,
1980 "xsltExtShutdownTest: not initialized\n");
1983 if (data != testData) {
1984 xsltTransformError(ctxt, NULL, NULL,
1985 "xsltExtShutdownTest: wrong data\n");
1988 xsltGenericDebug(xsltGenericDebugContext,
1989 "Unregistered test module : %s\n", URI);
1993 * xsltExtStyleInitTest:
1994 * @style: an XSLT stylesheet
1995 * @URI: the namespace URI for the extension
1997 * A function called at initialization time of an XSLT extension module
1999 * Returns a pointer to the module specific data for this transformation
2002 xsltExtStyleInitTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED,
2003 const xmlChar * URI)
2005 if (testStyleData != NULL) {
2006 xsltTransformError(NULL, NULL, NULL,
2007 "xsltExtInitTest: already initialized\n");
2010 testStyleData = (void *) "test data";
2011 xsltGenericDebug(xsltGenericDebugContext,
2012 "Registered test module : %s\n", URI);
2013 return (testStyleData);
2018 * xsltExtStyleShutdownTest:
2019 * @style: an XSLT stylesheet
2020 * @URI: the namespace URI for the extension
2021 * @data: the data associated to this module
2023 * A function called at shutdown time of an XSLT extension module
2026 xsltExtStyleShutdownTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED,
2027 const xmlChar * URI, void *data)
2029 if (testStyleData == NULL) {
2030 xsltGenericError(xsltGenericErrorContext,
2031 "xsltExtShutdownTest: not initialized\n");
2034 if (data != testStyleData) {
2035 xsltTransformError(NULL, NULL, NULL,
2036 "xsltExtShutdownTest: wrong data\n");
2038 testStyleData = NULL;
2039 xsltGenericDebug(xsltGenericDebugContext,
2040 "Unregistered test module : %s\n", URI);
2044 * xsltRegisterTestModule:
2046 * Registers the test module
2049 xsltRegisterTestModule(void)
2051 xsltRegisterExtModuleFull((const xmlChar *) XSLT_DEFAULT_URL,
2052 xsltExtInitTest, xsltExtShutdownTest,
2053 xsltExtStyleInitTest,
2054 xsltExtStyleShutdownTest);
2055 xsltRegisterExtModuleFunction((const xmlChar *) "test",
2056 (const xmlChar *) XSLT_DEFAULT_URL,
2057 xsltExtFunctionTest);
2058 xsltRegisterExtModuleElement((const xmlChar *) "test",
2059 (const xmlChar *) XSLT_DEFAULT_URL,
2060 xsltExtElementPreCompTest,
2061 xsltExtElementTest);
2065 xsltHashScannerModuleFree(void *payload, void *data ATTRIBUTE_UNUSED,
2066 xmlChar * name ATTRIBUTE_UNUSED)
2069 xmlModuleClose(payload);
2074 * xsltCleanupGlobals:
2076 * Unregister all global variables set up by the XSLT library
2079 xsltCleanupGlobals(void)
2081 xsltUnregisterAllExtModules();
2082 xsltUnregisterAllExtModuleFunction();
2083 xsltUnregisterAllExtModuleElement();
2084 xsltUnregisterAllExtModuleTopLevel();
2086 /* cleanup dynamic module hash */
2087 if (NULL != xsltModuleHash) {
2088 xmlHashScan(xsltModuleHash, xsltHashScannerModuleFree, 0);
2089 xmlHashFree(xsltModuleHash, NULL);
2090 xsltModuleHash = NULL;
2097 xsltDebugDumpExtensionsCallback(void *function ATTRIBUTE_UNUSED,
2098 FILE * output, const xmlChar * name,
2099 const xmlChar * URI,
2100 const xmlChar * not_used ATTRIBUTE_UNUSED)
2104 fprintf(output, "{%s}%s\n", URI, name);
2108 xsltDebugDumpExtModulesCallback(void *function ATTRIBUTE_UNUSED,
2109 FILE * output, const xmlChar * URI,
2110 const xmlChar * not_used ATTRIBUTE_UNUSED,
2111 const xmlChar * not_used2 ATTRIBUTE_UNUSED)
2115 fprintf(output, "%s\n", URI);
2119 * xsltDebugDumpExtensions:
2120 * @output: the FILE * for the output, if NULL stdout is used
2122 * Dumps a list of the registered XSLT extension functions and elements
2125 xsltDebugDumpExtensions(FILE * output)
2130 "Registered XSLT Extensions\n--------------------------\n");
2131 if (!xsltFunctionsHash)
2132 fprintf(output, "No registered extension functions\n");
2134 fprintf(output, "Registered Extension Functions:\n");
2135 xmlHashScanFull(xsltFunctionsHash,
2136 (xmlHashScannerFull)
2137 xsltDebugDumpExtensionsCallback, output);
2139 if (!xsltElementsHash)
2140 fprintf(output, "\nNo registered extension elements\n");
2142 fprintf(output, "\nRegistered Extension Elements:\n");
2143 xmlHashScanFull(xsltElementsHash,
2144 (xmlHashScannerFull)
2145 xsltDebugDumpExtensionsCallback, output);
2147 if (!xsltExtensionsHash)
2148 fprintf(output, "\nNo registered extension modules\n");
2150 fprintf(output, "\nRegistered Extension Modules:\n");
2151 xmlHashScanFull(xsltExtensionsHash,
2152 (xmlHashScannerFull)
2153 xsltDebugDumpExtModulesCallback, output);