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 */
38 #define PATH_MAX _MAX_PATH
42 #ifdef WITH_XSLT_DEBUG
43 #define WITH_XSLT_DEBUG_EXTENSIONS
46 /************************************************************************
48 * Private Types and Globals *
50 ************************************************************************/
52 typedef struct _xsltExtDef xsltExtDef
;
53 typedef xsltExtDef
*xsltExtDefPtr
;
55 struct _xsltExtDef
*next
;
61 typedef struct _xsltExtModule xsltExtModule
;
62 typedef xsltExtModule
*xsltExtModulePtr
;
63 struct _xsltExtModule
{
64 xsltExtInitFunction initFunc
;
65 xsltExtShutdownFunction shutdownFunc
;
66 xsltStyleExtInitFunction styleInitFunc
;
67 xsltStyleExtShutdownFunction styleShutdownFunc
;
70 typedef struct _xsltExtData xsltExtData
;
71 typedef xsltExtData
*xsltExtDataPtr
;
73 xsltExtModulePtr extModule
;
77 typedef struct _xsltExtElement xsltExtElement
;
78 typedef xsltExtElement
*xsltExtElementPtr
;
79 struct _xsltExtElement
{
80 xsltPreComputeFunction precomp
;
81 xsltTransformFunction transform
;
84 static xmlHashTablePtr xsltExtensionsHash
= NULL
;
85 static xmlHashTablePtr xsltFunctionsHash
= NULL
;
86 static xmlHashTablePtr xsltElementsHash
= NULL
;
87 static xmlHashTablePtr xsltTopLevelsHash
= NULL
;
88 static xmlHashTablePtr xsltModuleHash
= NULL
;
89 static xmlMutexPtr xsltExtMutex
= NULL
;
91 /************************************************************************
95 ************************************************************************/
99 * @prefix: the extension prefix
100 * @URI: the namespace URI
102 * Create a new XSLT ExtDef
104 * Returns the newly allocated xsltExtDefPtr or NULL in case of error
107 xsltNewExtDef(const xmlChar
* prefix
, const xmlChar
* URI
)
111 cur
= (xsltExtDefPtr
) xmlMalloc(sizeof(xsltExtDef
));
113 xsltTransformError(NULL
, NULL
, NULL
,
114 "xsltNewExtDef : malloc failed\n");
117 memset(cur
, 0, sizeof(xsltExtDef
));
119 cur
->prefix
= xmlStrdup(prefix
);
121 cur
->URI
= xmlStrdup(URI
);
127 * @extensiond: an XSLT extension definition
129 * Free up the memory allocated by @extensiond
132 xsltFreeExtDef(xsltExtDefPtr extensiond
)
134 if (extensiond
== NULL
)
136 if (extensiond
->prefix
!= NULL
)
137 xmlFree(extensiond
->prefix
);
138 if (extensiond
->URI
!= NULL
)
139 xmlFree(extensiond
->URI
);
144 * xsltFreeExtDefList:
145 * @extensiond: an XSLT extension definition list
147 * Free up the memory allocated by all the elements of @extensiond
150 xsltFreeExtDefList(xsltExtDefPtr extensiond
)
154 while (extensiond
!= NULL
) {
156 extensiond
= extensiond
->next
;
163 * @initFunc: the module initialization function
164 * @shutdownFunc: the module shutdown function
165 * @styleInitFunc: the stylesheet module data allocator function
166 * @styleShutdownFunc: the stylesheet module data free function
168 * Create a new XSLT extension module
170 * Returns the newly allocated xsltExtModulePtr or NULL in case of error
172 static xsltExtModulePtr
173 xsltNewExtModule(xsltExtInitFunction initFunc
,
174 xsltExtShutdownFunction shutdownFunc
,
175 xsltStyleExtInitFunction styleInitFunc
,
176 xsltStyleExtShutdownFunction styleShutdownFunc
)
178 xsltExtModulePtr cur
;
180 cur
= (xsltExtModulePtr
) xmlMalloc(sizeof(xsltExtModule
));
182 xsltTransformError(NULL
, NULL
, NULL
,
183 "xsltNewExtModule : malloc failed\n");
186 cur
->initFunc
= initFunc
;
187 cur
->shutdownFunc
= shutdownFunc
;
188 cur
->styleInitFunc
= styleInitFunc
;
189 cur
->styleShutdownFunc
= styleShutdownFunc
;
195 * @ext: an XSLT extension module
197 * Free up the memory allocated by @ext
200 xsltFreeExtModule(xsltExtModulePtr ext
)
209 * @extModule: the module
210 * @extData: the associated data
212 * Create a new XSLT extension module data wrapper
214 * Returns the newly allocated xsltExtDataPtr or NULL in case of error
216 static xsltExtDataPtr
217 xsltNewExtData(xsltExtModulePtr extModule
, void *extData
)
221 if (extModule
== NULL
)
223 cur
= (xsltExtDataPtr
) xmlMalloc(sizeof(xsltExtData
));
225 xsltTransformError(NULL
, NULL
, NULL
,
226 "xsltNewExtData : malloc failed\n");
229 cur
->extModule
= extModule
;
230 cur
->extData
= extData
;
236 * @ext: an XSLT extension module data wrapper
238 * Free up the memory allocated by @ext
241 xsltFreeExtData(xsltExtDataPtr ext
)
250 * @precomp: the pre-computation function
251 * @transform: the transformation function
253 * Create a new XSLT extension element
255 * Returns the newly allocated xsltExtElementPtr or NULL in case of
258 static xsltExtElementPtr
259 xsltNewExtElement(xsltPreComputeFunction precomp
,
260 xsltTransformFunction transform
)
262 xsltExtElementPtr cur
;
264 if (transform
== NULL
)
267 cur
= (xsltExtElementPtr
) xmlMalloc(sizeof(xsltExtElement
));
269 xsltTransformError(NULL
, NULL
, NULL
,
270 "xsltNewExtElement : malloc failed\n");
273 cur
->precomp
= precomp
;
274 cur
->transform
= transform
;
279 * xsltFreeExtElement:
280 * @ext: an XSLT extension element
282 * Frees up the memory allocated by @ext
285 xsltFreeExtElement(xsltExtElementPtr ext
)
294 typedef void (*exsltRegisterFunction
) (void);
297 #define PATH_MAX 4096
301 * xsltExtModuleRegisterDynamic:
302 * @URI: the function or element namespace URI
304 * Dynamically loads an extension plugin when available.
306 * The plugin name is derived from the URI by removing the
307 * initial protocol designation, e.g. "http://", then converting
308 * the characters ".", "-", "/", and "\" into "_", the removing
309 * any trailing "/", then concatenating LIBXML_MODULE_EXTENSION.
311 * Plugins are loaded from the directory specified by the
312 * environment variable LIBXSLT_PLUGINS_PATH, or if NULL,
313 * by LIBXSLT_DEFAULT_PLUGINS_PATH() which is determined at
316 * Returns 0 if successful, -1 in case of error.
320 xsltExtModuleRegisterDynamic(const xmlChar
* URI
)
324 exsltRegisterFunction regfunc
;
326 char module_filename
[PATH_MAX
];
327 const xmlChar
*ext_directory
= NULL
;
328 const xmlChar
*protocol
= NULL
;
329 xmlChar
*i
, *regfunc_name
;
333 /* check for bad inputs */
337 if (NULL
== xsltModuleHash
) {
338 xsltModuleHash
= xmlHashCreate(5);
339 if (xsltModuleHash
== NULL
)
343 xmlMutexLock(xsltExtMutex
);
345 /* have we attempted to register this module already? */
346 if (xmlHashLookup(xsltModuleHash
, URI
) != NULL
) {
347 xmlMutexUnlock(xsltExtMutex
);
350 xmlMutexUnlock(xsltExtMutex
);
352 /* transform extension namespace into a module name */
353 protocol
= xmlStrstr(URI
, BAD_CAST
"://");
354 if (protocol
== NULL
) {
355 ext_name
= xmlStrdup(URI
);
357 ext_name
= xmlStrdup(protocol
+ 3);
359 if (ext_name
== NULL
) {
365 if (('/' == *i
) || ('\\' == *i
) || ('.' == *i
) || ('-' == *i
))
373 /* determine module directory */
374 ext_directory
= (xmlChar
*) getenv("LIBXSLT_PLUGINS_PATH");
376 if (NULL
== ext_directory
) {
377 ext_directory
= BAD_CAST
LIBXSLT_DEFAULT_PLUGINS_PATH();
378 if (NULL
== ext_directory
)
381 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
383 xsltGenericDebug(xsltGenericDebugContext
,
384 "LIBXSLT_PLUGINS_PATH is %s\n", ext_directory
);
387 /* build the module filename, and confirm the module exists */
388 xmlStrPrintf((xmlChar
*) module_filename
, sizeof(module_filename
),
390 ext_directory
, ext_name
, LIBXML_MODULE_EXTENSION
);
392 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
393 xsltGenericDebug(xsltGenericDebugContext
,
394 "Attempting to load plugin: %s for URI: %s\n",
395 module_filename
, URI
);
398 if (1 != xmlCheckFilename(module_filename
)) {
400 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
401 xsltGenericDebug(xsltGenericDebugContext
,
402 "xmlCheckFilename failed for plugin: %s\n", module_filename
);
409 /* attempt to open the module */
410 m
= xmlModuleOpen(module_filename
, 0);
413 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
414 xsltGenericDebug(xsltGenericDebugContext
,
415 "xmlModuleOpen failed for plugin: %s\n", module_filename
);
422 /* construct initialization func name */
423 regfunc_name
= xmlStrdup(ext_name
);
424 regfunc_name
= xmlStrcat(regfunc_name
, BAD_CAST
"_init");
427 rc
= xmlModuleSymbol(m
, (const char *) regfunc_name
, &vregfunc
);
431 * Call the module's init function. Note that this function
432 * calls xsltRegisterExtModuleFull which will add the module
433 * to xsltExtensionsHash (together with it's entry points).
437 /* register this module in our hash */
438 xmlMutexLock(xsltExtMutex
);
439 xmlHashAddEntry(xsltModuleHash
, URI
, (void *) m
);
440 xmlMutexUnlock(xsltExtMutex
);
443 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
444 xsltGenericDebug(xsltGenericDebugContext
,
445 "xmlModuleSymbol failed for plugin: %s, regfunc: %s\n",
446 module_filename
, regfunc_name
);
449 /* if regfunc not found unload the module immediately */
454 xmlFree(regfunc_name
);
455 return (NULL
== regfunc
) ? -1 : 0;
459 xsltExtModuleRegisterDynamic(const xmlChar
* URI ATTRIBUTE_UNUSED
)
465 /************************************************************************
467 * The stylesheet extension prefixes handling *
469 ************************************************************************/
474 * @style: an XSLT stylesheet
476 * Free up the memory used by XSLT extensions in a stylesheet
479 xsltFreeExts(xsltStylesheetPtr style
)
481 if (style
->nsDefs
!= NULL
)
482 xsltFreeExtDefList((xsltExtDefPtr
) style
->nsDefs
);
486 * xsltRegisterExtPrefix:
487 * @style: an XSLT stylesheet
488 * @prefix: the prefix used (optional)
489 * @URI: the URI associated to the extension
491 * Registers an extension namespace
492 * This is called from xslt.c during compile-time.
493 * The given prefix is not needed.
495 * xsltParseExtElemPrefixes() (new function)
496 * xsltRegisterExtPrefix() (old function)
498 * Returns 0 in case of success, 1 if the @URI was already
499 * registered as an extension namespace and
500 * -1 in case of failure
503 xsltRegisterExtPrefix(xsltStylesheetPtr style
,
504 const xmlChar
* prefix
, const xmlChar
* URI
)
506 xsltExtDefPtr def
, ret
;
508 if ((style
== NULL
) || (URI
== NULL
))
511 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
512 xsltGenericDebug(xsltGenericDebugContext
,
513 "Registering extension namespace '%s'.\n", URI
);
515 def
= (xsltExtDefPtr
) style
->nsDefs
;
516 #ifdef XSLT_REFACTORED
518 * The extension is associated with a namespace name.
520 while (def
!= NULL
) {
521 if (xmlStrEqual(URI
, def
->URI
))
526 while (def
!= NULL
) {
527 if (xmlStrEqual(prefix
, def
->prefix
))
532 ret
= xsltNewExtDef(prefix
, URI
);
535 ret
->next
= (xsltExtDefPtr
) style
->nsDefs
;
539 * check whether there is an extension module with a stylesheet
540 * initialization function.
542 #ifdef XSLT_REFACTORED
544 * Don't initialize modules based on specified namespaces via
545 * the attribute "[xsl:]extension-element-prefixes".
548 if (xsltExtensionsHash
!= NULL
) {
549 xsltExtModulePtr module
;
551 xmlMutexLock(xsltExtMutex
);
552 module
= xmlHashLookup(xsltExtensionsHash
, URI
);
553 xmlMutexUnlock(xsltExtMutex
);
554 if (NULL
== module
) {
555 if (!xsltExtModuleRegisterDynamic(URI
)) {
556 xmlMutexLock(xsltExtMutex
);
557 module
= xmlHashLookup(xsltExtensionsHash
, URI
);
558 xmlMutexUnlock(xsltExtMutex
);
561 if (module
!= NULL
) {
562 xsltStyleGetExtData(style
, URI
);
569 /************************************************************************
571 * The extensions modules interfaces *
573 ************************************************************************/
576 * xsltRegisterExtFunction:
577 * @ctxt: an XSLT transformation context
578 * @name: the name of the element
579 * @URI: the URI associated to the element
580 * @function: the actual implementation which should be called
582 * Registers an extension function
584 * Returns 0 in case of success, -1 in case of failure
587 xsltRegisterExtFunction(xsltTransformContextPtr ctxt
, const xmlChar
* name
,
588 const xmlChar
* URI
, xmlXPathFunction function
)
592 if ((ctxt
== NULL
) || (name
== NULL
) ||
593 (URI
== NULL
) || (function
== NULL
))
595 if (ctxt
->xpathCtxt
!= NULL
) {
596 xmlXPathRegisterFuncNS(ctxt
->xpathCtxt
, name
, URI
, function
);
598 if (ctxt
->extFunctions
== NULL
)
599 ctxt
->extFunctions
= xmlHashCreate(10);
600 if (ctxt
->extFunctions
== NULL
)
603 ret
= xmlHashAddEntry2(ctxt
->extFunctions
, name
, URI
,
604 XML_CAST_FPTR(function
));
610 * xsltRegisterExtElement:
611 * @ctxt: an XSLT transformation context
612 * @name: the name of the element
613 * @URI: the URI associated to the element
614 * @function: the actual implementation which should be called
616 * Registers an extension element
618 * Returns 0 in case of success, -1 in case of failure
621 xsltRegisterExtElement(xsltTransformContextPtr ctxt
, const xmlChar
* name
,
622 const xmlChar
* URI
, xsltTransformFunction function
)
624 if ((ctxt
== NULL
) || (name
== NULL
) ||
625 (URI
== NULL
) || (function
== NULL
))
627 if (ctxt
->extElements
== NULL
)
628 ctxt
->extElements
= xmlHashCreate(10);
629 if (ctxt
->extElements
== NULL
)
631 return (xmlHashAddEntry2
632 (ctxt
->extElements
, name
, URI
, XML_CAST_FPTR(function
)));
637 * @ctxt: an XSLT transformation context
639 * Free the XSLT extension data
642 xsltFreeCtxtExts(xsltTransformContextPtr ctxt
)
644 if (ctxt
->extElements
!= NULL
)
645 xmlHashFree(ctxt
->extElements
, NULL
);
646 if (ctxt
->extFunctions
!= NULL
)
647 xmlHashFree(ctxt
->extFunctions
, NULL
);
651 * xsltStyleGetStylesheetExtData:
652 * @style: an XSLT stylesheet
653 * @URI: the URI associated to the exension module
655 * Fires the compile-time initialization callback
656 * of an extension module and returns a container
657 * holding the user-data (retrieved via the callback).
659 * Returns the create module-data container
660 * or NULL if such a module was not registered.
662 static xsltExtDataPtr
663 xsltStyleInitializeStylesheetModule(xsltStylesheetPtr style
,
666 xsltExtDataPtr dataContainer
;
667 void *userData
= NULL
;
668 xsltExtModulePtr module
;
670 if ((style
== NULL
) || (URI
== NULL
))
673 if (xsltExtensionsHash
== NULL
) {
674 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
675 xsltGenericDebug(xsltGenericDebugContext
,
676 "Not registered extension module: %s\n", URI
);
681 xmlMutexLock(xsltExtMutex
);
683 module
= xmlHashLookup(xsltExtensionsHash
, URI
);
685 xmlMutexUnlock(xsltExtMutex
);
687 if (module
== NULL
) {
688 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
689 xsltGenericDebug(xsltGenericDebugContext
,
690 "Not registered extension module: %s\n", URI
);
695 * The specified module was registered so initialize it.
697 if (style
->extInfos
== NULL
) {
698 style
->extInfos
= xmlHashCreate(10);
699 if (style
->extInfos
== NULL
)
703 * Fire the initialization callback if available.
705 if (module
->styleInitFunc
== NULL
) {
706 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
707 xsltGenericDebug(xsltGenericDebugContext
,
708 "Initializing module with *no* callback: %s\n", URI
);
711 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
712 xsltGenericDebug(xsltGenericDebugContext
,
713 "Initializing module with callback: %s\n", URI
);
716 * Fire the initialization callback.
718 userData
= module
->styleInitFunc(style
, URI
);
721 * Store the user-data in the context of the given stylesheet.
723 dataContainer
= xsltNewExtData(module
, userData
);
724 if (dataContainer
== NULL
)
727 if (xmlHashAddEntry(style
->extInfos
, URI
,
728 (void *) dataContainer
) < 0)
730 xsltTransformError(NULL
, style
, NULL
,
731 "Failed to register module '%s'.\n", URI
);
733 if (module
->styleShutdownFunc
)
734 module
->styleShutdownFunc(style
, URI
, userData
);
735 xsltFreeExtData(dataContainer
);
739 return(dataContainer
);
743 * xsltStyleGetExtData:
744 * @style: an XSLT stylesheet
745 * @URI: the URI associated to the exension module
747 * Retrieve the data associated to the extension module
748 * in this given stylesheet.
750 * xsltRegisterExtPrefix(),
751 * ( xsltExtElementPreCompTest(), xsltExtInitTest )
753 * Returns the pointer or NULL if not present
756 xsltStyleGetExtData(xsltStylesheetPtr style
, const xmlChar
* URI
)
758 xsltExtDataPtr dataContainer
= NULL
;
759 xsltStylesheetPtr tmpStyle
;
761 if ((style
== NULL
) || (URI
== NULL
) ||
762 (xsltExtensionsHash
== NULL
))
766 #ifdef XSLT_REFACTORED
768 * This is intended for global storage, so only the main
769 * stylesheet will hold the data.
772 while (tmpStyle
->parent
!= NULL
)
773 tmpStyle
= tmpStyle
->parent
;
774 if (tmpStyle
->extInfos
!= NULL
) {
776 (xsltExtDataPtr
) xmlHashLookup(tmpStyle
->extInfos
, URI
);
777 if (dataContainer
!= NULL
) {
779 * The module was already initialized in the context
780 * of this stylesheet; just return the user-data that
783 return(dataContainer
->extData
);
791 while (tmpStyle
!= NULL
) {
792 if (tmpStyle
->extInfos
!= NULL
) {
794 (xsltExtDataPtr
) xmlHashLookup(tmpStyle
->extInfos
, URI
);
795 if (dataContainer
!= NULL
) {
796 return(dataContainer
->extData
);
799 tmpStyle
= xsltNextImport(tmpStyle
);
805 xsltStyleInitializeStylesheetModule(tmpStyle
, URI
);
806 if (dataContainer
!= NULL
)
807 return (dataContainer
->extData
);
811 #ifdef XSLT_REFACTORED
813 * xsltStyleStylesheetLevelGetExtData:
814 * @style: an XSLT stylesheet
815 * @URI: the URI associated to the exension module
817 * Retrieve the data associated to the extension module in this given
820 * Returns the pointer or NULL if not present
823 xsltStyleStylesheetLevelGetExtData(xsltStylesheetPtr style
,
826 xsltExtDataPtr dataContainer
= NULL
;
828 if ((style
== NULL
) || (URI
== NULL
) ||
829 (xsltExtensionsHash
== NULL
))
832 if (style
->extInfos
!= NULL
) {
833 dataContainer
= (xsltExtDataPtr
) xmlHashLookup(style
->extInfos
, URI
);
835 * The module was already initialized in the context
836 * of this stylesheet; just return the user-data that
840 return(dataContainer
->extData
);
844 xsltStyleInitializeStylesheetModule(style
, URI
);
845 if (dataContainer
!= NULL
)
846 return (dataContainer
->extData
);
853 * @ctxt: an XSLT transformation context
854 * @URI: the URI associated to the exension module
856 * Retrieve the data associated to the extension module in this given
859 * Returns the pointer or NULL if not present
862 xsltGetExtData(xsltTransformContextPtr ctxt
, const xmlChar
* URI
)
866 if ((ctxt
== NULL
) || (URI
== NULL
))
868 if (ctxt
->extInfos
== NULL
) {
869 ctxt
->extInfos
= xmlHashCreate(10);
870 if (ctxt
->extInfos
== NULL
)
874 data
= (xsltExtDataPtr
) xmlHashLookup(ctxt
->extInfos
, URI
);
878 xsltExtModulePtr module
;
880 xmlMutexLock(xsltExtMutex
);
882 module
= xmlHashLookup(xsltExtensionsHash
, URI
);
884 xmlMutexUnlock(xsltExtMutex
);
886 if (module
== NULL
) {
887 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
888 xsltGenericDebug(xsltGenericDebugContext
,
889 "Not registered extension module: %s\n", URI
);
893 if (module
->initFunc
== NULL
)
896 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
897 xsltGenericDebug(xsltGenericDebugContext
,
898 "Initializing module: %s\n", URI
);
901 extData
= module
->initFunc(ctxt
, URI
);
905 data
= xsltNewExtData(module
, extData
);
908 if (xmlHashAddEntry(ctxt
->extInfos
, URI
, (void *) data
) < 0) {
909 xsltTransformError(ctxt
, NULL
, NULL
,
910 "Failed to register module data: %s\n",
912 if (module
->shutdownFunc
)
913 module
->shutdownFunc(ctxt
, URI
, extData
);
914 xsltFreeExtData(data
);
919 return (data
->extData
);
922 typedef struct _xsltInitExtCtxt xsltInitExtCtxt
;
923 struct _xsltInitExtCtxt
{
924 xsltTransformContextPtr ctxt
;
930 * @styleData: the registered stylesheet data for the module
931 * @ctxt: the XSLT transformation context + the return value
932 * @URI: the extension URI
934 * Initializes an extension module
937 xsltInitCtxtExt(xsltExtDataPtr styleData
, xsltInitExtCtxt
* ctxt
,
940 xsltExtModulePtr module
;
941 xsltExtDataPtr ctxtData
;
944 if ((styleData
== NULL
) || (ctxt
== NULL
) || (URI
== NULL
) ||
946 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
947 xsltGenericDebug(xsltGenericDebugContext
,
948 "xsltInitCtxtExt: NULL param or error\n");
952 module
= styleData
->extModule
;
953 if ((module
== NULL
) || (module
->initFunc
== NULL
)) {
954 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
955 xsltGenericDebug(xsltGenericDebugContext
,
956 "xsltInitCtxtExt: no module or no initFunc\n");
961 ctxtData
= (xsltExtDataPtr
) xmlHashLookup(ctxt
->ctxt
->extInfos
, URI
);
962 if (ctxtData
!= NULL
) {
963 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
964 xsltGenericDebug(xsltGenericDebugContext
,
965 "xsltInitCtxtExt: already initialized\n");
970 extData
= module
->initFunc(ctxt
->ctxt
, URI
);
971 if (extData
== NULL
) {
972 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
973 xsltGenericDebug(xsltGenericDebugContext
,
974 "xsltInitCtxtExt: no extData\n");
977 ctxtData
= xsltNewExtData(module
, extData
);
978 if (ctxtData
== NULL
) {
983 if (ctxt
->ctxt
->extInfos
== NULL
)
984 ctxt
->ctxt
->extInfos
= xmlHashCreate(10);
985 if (ctxt
->ctxt
->extInfos
== NULL
) {
990 if (xmlHashAddEntry(ctxt
->ctxt
->extInfos
, URI
, ctxtData
) < 0) {
991 xsltGenericError(xsltGenericErrorContext
,
992 "Failed to register module data: %s\n", URI
);
993 if (module
->shutdownFunc
)
994 module
->shutdownFunc(ctxt
->ctxt
, URI
, extData
);
995 xsltFreeExtData(ctxtData
);
999 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
1000 xsltGenericDebug(xsltGenericDebugContext
, "Registered module %s\n",
1008 * @ctxt: an XSLT transformation context
1010 * Initialize the set of modules with registered stylesheet data
1012 * Returns the number of modules initialized or -1 in case of error
1015 xsltInitCtxtExts(xsltTransformContextPtr ctxt
)
1017 xsltStylesheetPtr style
;
1018 xsltInitExtCtxt ctx
;
1023 style
= ctxt
->style
;
1030 while (style
!= NULL
) {
1031 if (style
->extInfos
!= NULL
) {
1032 xmlHashScan(style
->extInfos
,
1033 (xmlHashScanner
) xsltInitCtxtExt
, &ctx
);
1037 style
= xsltNextImport(style
);
1039 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
1040 xsltGenericDebug(xsltGenericDebugContext
, "Registered %d modules\n",
1047 * xsltShutdownCtxtExt:
1048 * @data: the registered data for the module
1049 * @ctxt: the XSLT transformation context
1050 * @URI: the extension URI
1052 * Shutdown an extension module loaded
1055 xsltShutdownCtxtExt(xsltExtDataPtr data
, xsltTransformContextPtr ctxt
,
1056 const xmlChar
* URI
)
1058 xsltExtModulePtr module
;
1060 if ((data
== NULL
) || (ctxt
== NULL
) || (URI
== NULL
))
1062 module
= data
->extModule
;
1063 if ((module
== NULL
) || (module
->shutdownFunc
== NULL
))
1066 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
1067 xsltGenericDebug(xsltGenericDebugContext
,
1068 "Shutting down module : %s\n", URI
);
1070 module
->shutdownFunc(ctxt
, URI
, data
->extData
);
1074 * xsltShutdownCtxtExts:
1075 * @ctxt: an XSLT transformation context
1077 * Shutdown the set of modules loaded
1080 xsltShutdownCtxtExts(xsltTransformContextPtr ctxt
)
1084 if (ctxt
->extInfos
== NULL
)
1086 xmlHashScan(ctxt
->extInfos
, (xmlHashScanner
) xsltShutdownCtxtExt
,
1088 xmlHashFree(ctxt
->extInfos
, (xmlHashDeallocator
) xsltFreeExtData
);
1089 ctxt
->extInfos
= NULL
;
1094 * @data: the registered data for the module
1095 * @ctxt: the XSLT stylesheet
1096 * @URI: the extension URI
1098 * Shutdown an extension module loaded
1101 xsltShutdownExt(xsltExtDataPtr data
, xsltStylesheetPtr style
,
1102 const xmlChar
* URI
)
1104 xsltExtModulePtr module
;
1106 if ((data
== NULL
) || (style
== NULL
) || (URI
== NULL
))
1108 module
= data
->extModule
;
1109 if ((module
== NULL
) || (module
->styleShutdownFunc
== NULL
))
1112 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
1113 xsltGenericDebug(xsltGenericDebugContext
,
1114 "Shutting down module : %s\n", URI
);
1116 module
->styleShutdownFunc(style
, URI
, data
->extData
);
1118 * Don't remove the entry from the hash table here, since
1119 * this will produce segfaults - this fixes bug #340624.
1121 * xmlHashRemoveEntry(style->extInfos, URI,
1122 * (xmlHashDeallocator) xsltFreeExtData);
1128 * @style: an XSLT stylesheet
1130 * Shutdown the set of modules loaded
1133 xsltShutdownExts(xsltStylesheetPtr style
)
1137 if (style
->extInfos
== NULL
)
1139 xmlHashScan(style
->extInfos
, (xmlHashScanner
) xsltShutdownExt
, style
);
1140 xmlHashFree(style
->extInfos
, (xmlHashDeallocator
) xsltFreeExtData
);
1141 style
->extInfos
= NULL
;
1145 * xsltCheckExtPrefix:
1146 * @style: the stylesheet
1147 * @URI: the namespace prefix (possibly NULL)
1149 * Check if the given prefix is one of the declared extensions.
1150 * This is intended to be called only at compile-time.
1152 * xsltGetInheritedNsList() (xslt.c)
1153 * xsltParseTemplateContent (xslt.c)
1155 * Returns 1 if this is an extension, 0 otherwise
1158 xsltCheckExtPrefix(xsltStylesheetPtr style
, const xmlChar
* URI
)
1160 #ifdef XSLT_REFACTORED
1161 if ((style
== NULL
) || (style
->compCtxt
== NULL
) ||
1162 (XSLT_CCTXT(style
)->inode
== NULL
) ||
1163 (XSLT_CCTXT(style
)->inode
->extElemNs
== NULL
))
1166 * Lookup the extension namespaces registered
1167 * at the current node in the stylesheet's tree.
1169 if (XSLT_CCTXT(style
)->inode
->extElemNs
!= NULL
) {
1171 xsltPointerListPtr list
= XSLT_CCTXT(style
)->inode
->extElemNs
;
1173 for (i
= 0; i
< list
->number
; i
++) {
1174 if (xmlStrEqual((const xmlChar
*) list
->items
[i
],
1184 if ((style
== NULL
) || (style
->nsDefs
== NULL
))
1187 URI
= BAD_CAST
"#default";
1188 cur
= (xsltExtDefPtr
) style
->nsDefs
;
1189 while (cur
!= NULL
) {
1191 * NOTE: This was change to work on namespace names rather
1192 * than namespace prefixes. This fixes bug #339583.
1193 * TODO: Consider renaming the field "prefix" of xsltExtDef
1196 if (xmlStrEqual(URI
, cur
->prefix
))
1206 * @style: the stylesheet
1207 * @URI: the namespace URI (possibly NULL)
1209 * Check if the given prefix is one of the declared extensions.
1210 * This is intended to be called only at compile-time.
1212 * xsltPrecomputeStylesheet() (xslt.c)
1213 * xsltParseTemplateContent (xslt.c)
1215 * Returns 1 if this is an extension, 0 otherwise
1218 xsltCheckExtURI(xsltStylesheetPtr style
, const xmlChar
* URI
)
1222 if ((style
== NULL
) || (style
->nsDefs
== NULL
))
1226 cur
= (xsltExtDefPtr
) style
->nsDefs
;
1227 while (cur
!= NULL
) {
1228 if (xmlStrEqual(URI
, cur
->URI
))
1236 * xsltRegisterExtModuleFull:
1237 * @URI: URI associated to this module
1238 * @initFunc: the module initialization function
1239 * @shutdownFunc: the module shutdown function
1240 * @styleInitFunc: the module initialization function
1241 * @styleShutdownFunc: the module shutdown function
1243 * Register an XSLT extension module to the library.
1245 * Returns 0 if sucessful, -1 in case of error
1248 xsltRegisterExtModuleFull(const xmlChar
* URI
,
1249 xsltExtInitFunction initFunc
,
1250 xsltExtShutdownFunction shutdownFunc
,
1251 xsltStyleExtInitFunction styleInitFunc
,
1252 xsltStyleExtShutdownFunction styleShutdownFunc
)
1255 xsltExtModulePtr module
;
1257 if ((URI
== NULL
) || (initFunc
== NULL
))
1259 if (xsltExtensionsHash
== NULL
)
1260 xsltExtensionsHash
= xmlHashCreate(10);
1262 if (xsltExtensionsHash
== NULL
)
1265 xmlMutexLock(xsltExtMutex
);
1267 module
= xmlHashLookup(xsltExtensionsHash
, URI
);
1268 if (module
!= NULL
) {
1269 if ((module
->initFunc
== initFunc
) &&
1270 (module
->shutdownFunc
== shutdownFunc
))
1276 module
= xsltNewExtModule(initFunc
, shutdownFunc
,
1277 styleInitFunc
, styleShutdownFunc
);
1278 if (module
== NULL
) {
1282 ret
= xmlHashAddEntry(xsltExtensionsHash
, URI
, (void *) module
);
1285 xmlMutexUnlock(xsltExtMutex
);
1290 * xsltRegisterExtModule:
1291 * @URI: URI associated to this module
1292 * @initFunc: the module initialization function
1293 * @shutdownFunc: the module shutdown function
1295 * Register an XSLT extension module to the library.
1297 * Returns 0 if sucessful, -1 in case of error
1300 xsltRegisterExtModule(const xmlChar
* URI
,
1301 xsltExtInitFunction initFunc
,
1302 xsltExtShutdownFunction shutdownFunc
)
1304 return xsltRegisterExtModuleFull(URI
, initFunc
, shutdownFunc
,
1309 * xsltUnregisterExtModule:
1310 * @URI: URI associated to this module
1312 * Unregister an XSLT extension module from the library.
1314 * Returns 0 if sucessful, -1 in case of error
1317 xsltUnregisterExtModule(const xmlChar
* URI
)
1323 if (xsltExtensionsHash
== NULL
)
1326 xmlMutexLock(xsltExtMutex
);
1328 ret
= xmlHashRemoveEntry(xsltExtensionsHash
, URI
,
1329 (xmlHashDeallocator
) xsltFreeExtModule
);
1331 xmlMutexUnlock(xsltExtMutex
);
1337 * xsltUnregisterAllExtModules:
1339 * Unregister all the XSLT extension module from the library.
1342 xsltUnregisterAllExtModules(void)
1344 if (xsltExtensionsHash
== NULL
)
1347 xmlMutexLock(xsltExtMutex
);
1349 xmlHashFree(xsltExtensionsHash
,
1350 (xmlHashDeallocator
) xsltFreeExtModule
);
1351 xsltExtensionsHash
= NULL
;
1353 xmlMutexUnlock(xsltExtMutex
);
1357 * xsltXPathGetTransformContext:
1358 * @ctxt: an XPath transformation context
1360 * Provides the XSLT transformation context from the XPath transformation
1361 * context. This is useful when an XPath function in the extension module
1362 * is called by the XPath interpreter and that the XSLT context is needed
1363 * for example to retrieve the associated data pertaining to this XSLT
1366 * Returns the XSLT transformation context or NULL in case of error.
1368 xsltTransformContextPtr
1369 xsltXPathGetTransformContext(xmlXPathParserContextPtr ctxt
)
1371 if ((ctxt
== NULL
) || (ctxt
->context
== NULL
))
1373 return (ctxt
->context
->extra
);
1377 * xsltRegisterExtModuleFunction:
1378 * @name: the function name
1379 * @URI: the function namespace URI
1380 * @function: the function callback
1382 * Registers an extension module function.
1384 * Returns 0 if successful, -1 in case of error.
1387 xsltRegisterExtModuleFunction(const xmlChar
* name
, const xmlChar
* URI
,
1388 xmlXPathFunction function
)
1390 if ((name
== NULL
) || (URI
== NULL
) || (function
== NULL
))
1393 if (xsltFunctionsHash
== NULL
)
1394 xsltFunctionsHash
= xmlHashCreate(10);
1395 if (xsltFunctionsHash
== NULL
)
1398 xmlMutexLock(xsltExtMutex
);
1400 xmlHashUpdateEntry2(xsltFunctionsHash
, name
, URI
,
1401 XML_CAST_FPTR(function
), NULL
);
1403 xmlMutexUnlock(xsltExtMutex
);
1409 * xsltExtModuleFunctionLookup:
1410 * @name: the function name
1411 * @URI: the function namespace URI
1413 * Looks up an extension module function
1415 * Returns the function if found, NULL otherwise.
1418 xsltExtModuleFunctionLookup(const xmlChar
* name
, const xmlChar
* URI
)
1420 xmlXPathFunction ret
;
1422 if ((xsltFunctionsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1425 xmlMutexLock(xsltExtMutex
);
1427 XML_CAST_FPTR(ret
) = xmlHashLookup2(xsltFunctionsHash
, name
, URI
);
1429 xmlMutexUnlock(xsltExtMutex
);
1431 /* if lookup fails, attempt a dynamic load on supported platforms */
1433 if (!xsltExtModuleRegisterDynamic(URI
)) {
1434 xmlMutexLock(xsltExtMutex
);
1436 XML_CAST_FPTR(ret
) =
1437 xmlHashLookup2(xsltFunctionsHash
, name
, URI
);
1439 xmlMutexUnlock(xsltExtMutex
);
1447 * xsltUnregisterExtModuleFunction:
1448 * @name: the function name
1449 * @URI: the function namespace URI
1451 * Unregisters an extension module function
1453 * Returns 0 if successful, -1 in case of error.
1456 xsltUnregisterExtModuleFunction(const xmlChar
* name
, const xmlChar
* URI
)
1460 if ((xsltFunctionsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1463 xmlMutexLock(xsltExtMutex
);
1465 ret
= xmlHashRemoveEntry2(xsltFunctionsHash
, name
, URI
, NULL
);
1467 xmlMutexUnlock(xsltExtMutex
);
1473 * xsltUnregisterAllExtModuleFunction:
1475 * Unregisters all extension module function
1478 xsltUnregisterAllExtModuleFunction(void)
1480 xmlMutexLock(xsltExtMutex
);
1482 xmlHashFree(xsltFunctionsHash
, NULL
);
1483 xsltFunctionsHash
= NULL
;
1485 xmlMutexUnlock(xsltExtMutex
);
1490 * xsltNewElemPreComp:
1491 * @style: the XSLT stylesheet
1492 * @inst: the element node
1493 * @function: the transform function
1495 * Creates and initializes an #xsltElemPreComp
1497 * Returns the new and initialized #xsltElemPreComp
1500 xsltNewElemPreComp(xsltStylesheetPtr style
, xmlNodePtr inst
,
1501 xsltTransformFunction function
)
1503 xsltElemPreCompPtr cur
;
1505 cur
= (xsltElemPreCompPtr
) xmlMalloc(sizeof(xsltElemPreComp
));
1507 xsltTransformError(NULL
, style
, NULL
,
1508 "xsltNewExtElement : malloc failed\n");
1511 memset(cur
, 0, sizeof(xsltElemPreComp
));
1513 xsltInitElemPreComp(cur
, style
, inst
, function
,
1514 (xsltElemPreCompDeallocator
) xmlFree
);
1520 * xsltInitElemPreComp:
1521 * @comp: an #xsltElemPreComp (or generally a derived structure)
1522 * @style: the XSLT stylesheet
1523 * @inst: the element node
1524 * @function: the transform function
1525 * @freeFunc: the @comp deallocator
1527 * Initializes an existing #xsltElemPreComp structure. This is usefull
1528 * when extending an #xsltElemPreComp to store precomputed data.
1529 * This function MUST be called on any extension element precomputed
1533 xsltInitElemPreComp(xsltElemPreCompPtr comp
, xsltStylesheetPtr style
,
1534 xmlNodePtr inst
, xsltTransformFunction function
,
1535 xsltElemPreCompDeallocator freeFunc
)
1537 comp
->type
= XSLT_FUNC_EXTENSION
;
1538 comp
->func
= function
;
1540 comp
->free
= freeFunc
;
1542 comp
->next
= style
->preComps
;
1543 style
->preComps
= comp
;
1547 * xsltPreComputeExtModuleElement:
1548 * @style: the stylesheet
1549 * @inst: the element node
1551 * Precomputes an extension module element
1553 * Returns the precomputed data
1556 xsltPreComputeExtModuleElement(xsltStylesheetPtr style
, xmlNodePtr inst
)
1558 xsltExtElementPtr ext
;
1559 xsltElemPreCompPtr comp
= NULL
;
1561 if ((style
== NULL
) || (inst
== NULL
) ||
1562 (inst
->type
!= XML_ELEMENT_NODE
) || (inst
->ns
== NULL
))
1565 xmlMutexLock(xsltExtMutex
);
1567 ext
= (xsltExtElementPtr
)
1568 xmlHashLookup2(xsltElementsHash
, inst
->name
, inst
->ns
->href
);
1570 xmlMutexUnlock(xsltExtMutex
);
1573 * EXT TODO: Now what?
1578 if (ext
->precomp
!= NULL
) {
1580 * REVISIT TODO: Check if the text below is correct.
1581 * This will return a xsltElemPreComp structure or NULL.
1582 * 1) If the the author of the extension needs a
1583 * custom structure to hold the specific values of
1584 * this extension, he will derive a structure based on
1585 * xsltElemPreComp; thus we obviously *cannot* refactor
1586 * the xsltElemPreComp structure, since all already derived
1587 * user-defined strucures will break.
1588 * Example: For the extension xsl:document,
1589 * in xsltDocumentComp() (preproc.c), the structure
1590 * xsltStyleItemDocument is allocated, filled with
1591 * specific values and returned.
1592 * 2) If the author needs no values to be stored in
1593 * this structure, then he'll return NULL;
1595 comp
= ext
->precomp(style
, inst
, ext
->transform
);
1599 * Default creation of a xsltElemPreComp structure, if
1600 * the author of this extension did not create a custom
1603 comp
= xsltNewElemPreComp(style
, inst
, ext
->transform
);
1610 * xsltRegisterExtModuleElement:
1611 * @name: the element name
1612 * @URI: the element namespace URI
1613 * @precomp: the pre-computation callback
1614 * @transform: the transformation callback
1616 * Registers an extension module element.
1618 * Returns 0 if successful, -1 in case of error.
1621 xsltRegisterExtModuleElement(const xmlChar
* name
, const xmlChar
* URI
,
1622 xsltPreComputeFunction precomp
,
1623 xsltTransformFunction transform
)
1627 xsltExtElementPtr ext
;
1629 if ((name
== NULL
) || (URI
== NULL
) || (transform
== NULL
))
1632 if (xsltElementsHash
== NULL
)
1633 xsltElementsHash
= xmlHashCreate(10);
1634 if (xsltElementsHash
== NULL
)
1637 xmlMutexLock(xsltExtMutex
);
1639 ext
= xsltNewExtElement(precomp
, transform
);
1645 xmlHashUpdateEntry2(xsltElementsHash
, name
, URI
, (void *) ext
,
1646 (xmlHashDeallocator
) xsltFreeExtElement
);
1649 xmlMutexUnlock(xsltExtMutex
);
1655 * xsltExtElementLookup:
1656 * @ctxt: an XSLT process context
1657 * @name: the element name
1658 * @URI: the element namespace URI
1660 * Looks up an extension element. @ctxt can be NULL to search only in
1663 * Returns the element callback or NULL if not found
1665 xsltTransformFunction
1666 xsltExtElementLookup(xsltTransformContextPtr ctxt
,
1667 const xmlChar
* name
, const xmlChar
* URI
)
1669 xsltTransformFunction ret
;
1671 if ((name
== NULL
) || (URI
== NULL
))
1674 if ((ctxt
!= NULL
) && (ctxt
->extElements
!= NULL
)) {
1675 XML_CAST_FPTR(ret
) = xmlHashLookup2(ctxt
->extElements
, name
, URI
);
1681 ret
= xsltExtModuleElementLookup(name
, URI
);
1687 * xsltExtModuleElementLookup:
1688 * @name: the element name
1689 * @URI: the element namespace URI
1691 * Looks up an extension module element
1693 * Returns the callback function if found, NULL otherwise.
1695 xsltTransformFunction
1696 xsltExtModuleElementLookup(const xmlChar
* name
, const xmlChar
* URI
)
1698 xsltExtElementPtr ext
;
1700 if ((xsltElementsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1703 xmlMutexLock(xsltExtMutex
);
1705 ext
= (xsltExtElementPtr
) xmlHashLookup2(xsltElementsHash
, name
, URI
);
1707 xmlMutexUnlock(xsltExtMutex
);
1710 * if function lookup fails, attempt a dynamic load on
1711 * supported platforms
1714 if (!xsltExtModuleRegisterDynamic(URI
)) {
1715 xmlMutexLock(xsltExtMutex
);
1717 ext
= (xsltExtElementPtr
)
1718 xmlHashLookup2(xsltElementsHash
, name
, URI
);
1720 xmlMutexUnlock(xsltExtMutex
);
1726 return (ext
->transform
);
1730 * xsltExtModuleElementPreComputeLookup:
1731 * @name: the element name
1732 * @URI: the element namespace URI
1734 * Looks up an extension module element pre-computation function
1736 * Returns the callback function if found, NULL otherwise.
1738 xsltPreComputeFunction
1739 xsltExtModuleElementPreComputeLookup(const xmlChar
* name
,
1740 const xmlChar
* URI
)
1742 xsltExtElementPtr ext
;
1744 if ((xsltElementsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1747 xmlMutexLock(xsltExtMutex
);
1749 ext
= (xsltExtElementPtr
) xmlHashLookup2(xsltElementsHash
, name
, URI
);
1751 xmlMutexUnlock(xsltExtMutex
);
1754 if (!xsltExtModuleRegisterDynamic(URI
)) {
1755 xmlMutexLock(xsltExtMutex
);
1757 ext
= (xsltExtElementPtr
)
1758 xmlHashLookup2(xsltElementsHash
, name
, URI
);
1760 xmlMutexUnlock(xsltExtMutex
);
1766 return (ext
->precomp
);
1770 * xsltUnregisterExtModuleElement:
1771 * @name: the element name
1772 * @URI: the element namespace URI
1774 * Unregisters an extension module element
1776 * Returns 0 if successful, -1 in case of error.
1779 xsltUnregisterExtModuleElement(const xmlChar
* name
, const xmlChar
* URI
)
1783 if ((xsltElementsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1786 xmlMutexLock(xsltExtMutex
);
1788 ret
= xmlHashRemoveEntry2(xsltElementsHash
, name
, URI
,
1789 (xmlHashDeallocator
) xsltFreeExtElement
);
1791 xmlMutexUnlock(xsltExtMutex
);
1797 * xsltUnregisterAllExtModuleElement:
1799 * Unregisters all extension module element
1802 xsltUnregisterAllExtModuleElement(void)
1804 xmlMutexLock(xsltExtMutex
);
1806 xmlHashFree(xsltElementsHash
, (xmlHashDeallocator
) xsltFreeExtElement
);
1807 xsltElementsHash
= NULL
;
1809 xmlMutexUnlock(xsltExtMutex
);
1813 * xsltRegisterExtModuleTopLevel:
1814 * @name: the top-level element name
1815 * @URI: the top-level element namespace URI
1816 * @function: the top-level element callback
1818 * Registers an extension module top-level element.
1820 * Returns 0 if successful, -1 in case of error.
1823 xsltRegisterExtModuleTopLevel(const xmlChar
* name
, const xmlChar
* URI
,
1824 xsltTopLevelFunction function
)
1826 if ((name
== NULL
) || (URI
== NULL
) || (function
== NULL
))
1829 if (xsltTopLevelsHash
== NULL
)
1830 xsltTopLevelsHash
= xmlHashCreate(10);
1831 if (xsltTopLevelsHash
== NULL
)
1834 xmlMutexLock(xsltExtMutex
);
1836 xmlHashUpdateEntry2(xsltTopLevelsHash
, name
, URI
,
1837 XML_CAST_FPTR(function
), NULL
);
1839 xmlMutexUnlock(xsltExtMutex
);
1845 * xsltExtModuleTopLevelLookup:
1846 * @name: the top-level element name
1847 * @URI: the top-level element namespace URI
1849 * Looks up an extension module top-level element
1851 * Returns the callback function if found, NULL otherwise.
1853 xsltTopLevelFunction
1854 xsltExtModuleTopLevelLookup(const xmlChar
* name
, const xmlChar
* URI
)
1856 xsltTopLevelFunction ret
;
1858 if ((xsltTopLevelsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1861 xmlMutexLock(xsltExtMutex
);
1863 XML_CAST_FPTR(ret
) = xmlHashLookup2(xsltTopLevelsHash
, name
, URI
);
1865 xmlMutexUnlock(xsltExtMutex
);
1867 /* if lookup fails, attempt a dynamic load on supported platforms */
1869 if (!xsltExtModuleRegisterDynamic(URI
)) {
1870 xmlMutexLock(xsltExtMutex
);
1872 XML_CAST_FPTR(ret
) = xmlHashLookup2(xsltTopLevelsHash
, name
, URI
);
1874 xmlMutexUnlock(xsltExtMutex
);
1882 * xsltUnregisterExtModuleTopLevel:
1883 * @name: the top-level element name
1884 * @URI: the top-level element namespace URI
1886 * Unregisters an extension module top-level element
1888 * Returns 0 if successful, -1 in case of error.
1891 xsltUnregisterExtModuleTopLevel(const xmlChar
* name
, const xmlChar
* URI
)
1895 if ((xsltTopLevelsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1898 xmlMutexLock(xsltExtMutex
);
1900 ret
= xmlHashRemoveEntry2(xsltTopLevelsHash
, name
, URI
, NULL
);
1902 xmlMutexUnlock(xsltExtMutex
);
1908 * xsltUnregisterAllExtModuleTopLevel:
1910 * Unregisters all extension module function
1913 xsltUnregisterAllExtModuleTopLevel(void)
1915 xmlMutexLock(xsltExtMutex
);
1917 xmlHashFree(xsltTopLevelsHash
, NULL
);
1918 xsltTopLevelsHash
= NULL
;
1920 xmlMutexUnlock(xsltExtMutex
);
1925 * @style: pointer to a stylesheet
1926 * @URI: the namespace URI desired
1928 * looks up URI in extInfos of the stylesheet
1930 * returns a pointer to the hash table if found, else NULL
1933 xsltGetExtInfo(xsltStylesheetPtr style
, const xmlChar
* URI
)
1935 xsltExtDataPtr data
;
1938 * TODO: Why do we have a return type of xmlHashTablePtr?
1939 * Is the user-allocated data for extension modules expected
1940 * to be a xmlHashTablePtr only? Or is this intended for
1941 * the EXSLT module only?
1944 if (style
!= NULL
&& style
->extInfos
!= NULL
) {
1945 data
= xmlHashLookup(style
->extInfos
, URI
);
1946 if (data
!= NULL
&& data
->extData
!= NULL
)
1947 return data
->extData
;
1952 /************************************************************************
1954 * Test module http://xmlsoft.org/XSLT/ *
1956 ************************************************************************/
1958 /************************************************************************
1960 * Test of the extension module API *
1962 ************************************************************************/
1964 static xmlChar
*testData
= NULL
;
1965 static xmlChar
*testStyleData
= NULL
;
1968 * xsltExtFunctionTest:
1969 * @ctxt: the XPath Parser context
1970 * @nargs: the number of arguments
1972 * function libxslt:test() for testing the extensions support.
1975 xsltExtFunctionTest(xmlXPathParserContextPtr ctxt
,
1976 int nargs ATTRIBUTE_UNUSED
)
1978 xsltTransformContextPtr tctxt
;
1981 tctxt
= xsltXPathGetTransformContext(ctxt
);
1983 if (testData
== NULL
) {
1984 xsltGenericDebug(xsltGenericDebugContext
,
1985 "xsltExtFunctionTest: not initialized,"
1986 " calling xsltGetExtData\n");
1987 data
= xsltGetExtData(tctxt
, (const xmlChar
*) XSLT_DEFAULT_URL
);
1989 xsltTransformError(tctxt
, NULL
, NULL
,
1990 "xsltExtElementTest: not initialized\n");
1994 if (tctxt
== NULL
) {
1995 xsltTransformError(xsltXPathGetTransformContext(ctxt
), NULL
, NULL
,
1996 "xsltExtFunctionTest: failed to get the transformation context\n");
2000 data
= xsltGetExtData(tctxt
, (const xmlChar
*) XSLT_DEFAULT_URL
);
2002 xsltTransformError(xsltXPathGetTransformContext(ctxt
), NULL
, NULL
,
2003 "xsltExtFunctionTest: failed to get module data\n");
2006 if (data
!= testData
) {
2007 xsltTransformError(xsltXPathGetTransformContext(ctxt
), NULL
, NULL
,
2008 "xsltExtFunctionTest: got wrong module data\n");
2011 #ifdef WITH_XSLT_DEBUG_FUNCTION
2012 xsltGenericDebug(xsltGenericDebugContext
,
2013 "libxslt:test() called with %d args\n", nargs
);
2018 * xsltExtElementPreCompTest:
2019 * @style: the stylesheet
2020 * @inst: the instruction in the stylesheet
2022 * Process a libxslt:test node
2024 static xsltElemPreCompPtr
2025 xsltExtElementPreCompTest(xsltStylesheetPtr style
, xmlNodePtr inst
,
2026 xsltTransformFunction function
)
2028 xsltElemPreCompPtr ret
;
2030 if (style
== NULL
) {
2031 xsltTransformError(NULL
, NULL
, inst
,
2032 "xsltExtElementTest: no transformation context\n");
2035 if (testStyleData
== NULL
) {
2036 xsltGenericDebug(xsltGenericDebugContext
,
2037 "xsltExtElementPreCompTest: not initialized,"
2038 " calling xsltStyleGetExtData\n");
2039 xsltStyleGetExtData(style
, (const xmlChar
*) XSLT_DEFAULT_URL
);
2040 if (testStyleData
== NULL
) {
2041 xsltTransformError(NULL
, style
, inst
,
2042 "xsltExtElementPreCompTest: not initialized\n");
2049 xsltTransformError(NULL
, style
, inst
,
2050 "xsltExtElementPreCompTest: no instruction\n");
2055 ret
= xsltNewElemPreComp(style
, inst
, function
);
2060 * xsltExtElementTest:
2061 * @ctxt: an XSLT processing context
2062 * @node: The current node
2063 * @inst: the instruction in the stylesheet
2064 * @comp: precomputed informations
2066 * Process a libxslt:test node
2069 xsltExtElementTest(xsltTransformContextPtr ctxt
, xmlNodePtr node
,
2071 xsltElemPreCompPtr comp ATTRIBUTE_UNUSED
)
2073 xmlNodePtr commentNode
;
2075 if (testData
== NULL
) {
2076 xsltGenericDebug(xsltGenericDebugContext
,
2077 "xsltExtElementTest: not initialized,"
2078 " calling xsltGetExtData\n");
2079 xsltGetExtData(ctxt
, (const xmlChar
*) XSLT_DEFAULT_URL
);
2080 if (testData
== NULL
) {
2081 xsltTransformError(ctxt
, NULL
, inst
,
2082 "xsltExtElementTest: not initialized\n");
2087 xsltTransformError(ctxt
, NULL
, inst
,
2088 "xsltExtElementTest: no transformation context\n");
2092 xsltTransformError(ctxt
, NULL
, inst
,
2093 "xsltExtElementTest: no current node\n");
2097 xsltTransformError(ctxt
, NULL
, inst
,
2098 "xsltExtElementTest: no instruction\n");
2101 if (ctxt
->insert
== NULL
) {
2102 xsltTransformError(ctxt
, NULL
, inst
,
2103 "xsltExtElementTest: no insertion point\n");
2106 commentNode
= xmlNewComment((const xmlChar
*)
2107 "libxslt:test element test worked");
2108 xmlAddChild(ctxt
->insert
, commentNode
);
2113 * @ctxt: an XSLT transformation context
2114 * @URI: the namespace URI for the extension
2116 * A function called at initialization time of an XSLT extension module
2118 * Returns a pointer to the module specific data for this transformation
2121 xsltExtInitTest(xsltTransformContextPtr ctxt
, const xmlChar
* URI
)
2123 if (testStyleData
== NULL
) {
2124 xsltGenericDebug(xsltGenericErrorContext
,
2125 "xsltExtInitTest: not initialized,"
2126 " calling xsltStyleGetExtData\n");
2127 testStyleData
= xsltStyleGetExtData(ctxt
->style
, URI
);
2128 if (testStyleData
== NULL
) {
2129 xsltTransformError(ctxt
, NULL
, NULL
,
2130 "xsltExtInitTest: not initialized\n");
2134 if (testData
!= NULL
) {
2135 xsltTransformError(ctxt
, NULL
, NULL
,
2136 "xsltExtInitTest: already initialized\n");
2139 testData
= (void *) "test data";
2140 xsltGenericDebug(xsltGenericDebugContext
,
2141 "Registered test module : %s\n", URI
);
2147 * xsltExtShutdownTest:
2148 * @ctxt: an XSLT transformation context
2149 * @URI: the namespace URI for the extension
2150 * @data: the data associated to this module
2152 * A function called at shutdown time of an XSLT extension module
2155 xsltExtShutdownTest(xsltTransformContextPtr ctxt
,
2156 const xmlChar
* URI
, void *data
)
2158 if (testData
== NULL
) {
2159 xsltTransformError(ctxt
, NULL
, NULL
,
2160 "xsltExtShutdownTest: not initialized\n");
2163 if (data
!= testData
) {
2164 xsltTransformError(ctxt
, NULL
, NULL
,
2165 "xsltExtShutdownTest: wrong data\n");
2168 xsltGenericDebug(xsltGenericDebugContext
,
2169 "Unregistered test module : %s\n", URI
);
2173 * xsltExtStyleInitTest:
2174 * @style: an XSLT stylesheet
2175 * @URI: the namespace URI for the extension
2177 * A function called at initialization time of an XSLT extension module
2179 * Returns a pointer to the module specific data for this transformation
2182 xsltExtStyleInitTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED
,
2183 const xmlChar
* URI
)
2185 if (testStyleData
!= NULL
) {
2186 xsltTransformError(NULL
, NULL
, NULL
,
2187 "xsltExtInitTest: already initialized\n");
2190 testStyleData
= (void *) "test data";
2191 xsltGenericDebug(xsltGenericDebugContext
,
2192 "Registered test module : %s\n", URI
);
2193 return (testStyleData
);
2198 * xsltExtStyleShutdownTest:
2199 * @style: an XSLT stylesheet
2200 * @URI: the namespace URI for the extension
2201 * @data: the data associated to this module
2203 * A function called at shutdown time of an XSLT extension module
2206 xsltExtStyleShutdownTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED
,
2207 const xmlChar
* URI
, void *data
)
2209 if (testStyleData
== NULL
) {
2210 xsltGenericError(xsltGenericErrorContext
,
2211 "xsltExtShutdownTest: not initialized\n");
2214 if (data
!= testStyleData
) {
2215 xsltTransformError(NULL
, NULL
, NULL
,
2216 "xsltExtShutdownTest: wrong data\n");
2218 testStyleData
= NULL
;
2219 xsltGenericDebug(xsltGenericDebugContext
,
2220 "Unregistered test module : %s\n", URI
);
2224 * xsltRegisterTestModule:
2226 * Registers the test module
2229 xsltRegisterTestModule(void)
2232 xsltRegisterExtModuleFull((const xmlChar
*) XSLT_DEFAULT_URL
,
2233 xsltExtInitTest
, xsltExtShutdownTest
,
2234 xsltExtStyleInitTest
,
2235 xsltExtStyleShutdownTest
);
2236 xsltRegisterExtModuleFunction((const xmlChar
*) "test",
2237 (const xmlChar
*) XSLT_DEFAULT_URL
,
2238 xsltExtFunctionTest
);
2239 xsltRegisterExtModuleElement((const xmlChar
*) "test",
2240 (const xmlChar
*) XSLT_DEFAULT_URL
,
2241 xsltExtElementPreCompTest
,
2242 xsltExtElementTest
);
2246 xsltHashScannerModuleFree(void *payload ATTRIBUTE_UNUSED
,
2247 void *data ATTRIBUTE_UNUSED
,
2248 xmlChar
* name ATTRIBUTE_UNUSED
)
2251 xmlModuleClose(payload
);
2258 * Initialize the global variables for extensions
2261 xsltInitGlobals(void)
2263 if (xsltExtMutex
== NULL
) {
2264 xsltExtMutex
= xmlNewMutex();
2269 * xsltCleanupGlobals:
2271 * Unregister all global variables set up by the XSLT library
2274 xsltCleanupGlobals(void)
2276 xsltUnregisterAllExtModules();
2277 xsltUnregisterAllExtModuleFunction();
2278 xsltUnregisterAllExtModuleElement();
2279 xsltUnregisterAllExtModuleTopLevel();
2281 xmlMutexLock(xsltExtMutex
);
2282 /* cleanup dynamic module hash */
2283 if (NULL
!= xsltModuleHash
) {
2284 xmlHashScan(xsltModuleHash
, xsltHashScannerModuleFree
, 0);
2285 xmlHashFree(xsltModuleHash
, NULL
);
2286 xsltModuleHash
= NULL
;
2288 xmlMutexUnlock(xsltExtMutex
);
2290 xmlFreeMutex(xsltExtMutex
);
2291 xsltExtMutex
= NULL
;
2297 xsltDebugDumpExtensionsCallback(void *function ATTRIBUTE_UNUSED
,
2298 FILE * output
, const xmlChar
* name
,
2299 const xmlChar
* URI
,
2300 const xmlChar
* not_used ATTRIBUTE_UNUSED
)
2304 fprintf(output
, "{%s}%s\n", URI
, name
);
2308 xsltDebugDumpExtModulesCallback(void *function ATTRIBUTE_UNUSED
,
2309 FILE * output
, const xmlChar
* URI
,
2310 const xmlChar
* not_used ATTRIBUTE_UNUSED
,
2311 const xmlChar
* not_used2 ATTRIBUTE_UNUSED
)
2315 fprintf(output
, "%s\n", URI
);
2319 * xsltDebugDumpExtensions:
2320 * @output: the FILE * for the output, if NULL stdout is used
2322 * Dumps a list of the registered XSLT extension functions and elements
2325 xsltDebugDumpExtensions(FILE * output
)
2330 "Registered XSLT Extensions\n--------------------------\n");
2331 if (!xsltFunctionsHash
)
2332 fprintf(output
, "No registered extension functions\n");
2334 fprintf(output
, "Registered Extension Functions:\n");
2335 xmlMutexLock(xsltExtMutex
);
2336 xmlHashScanFull(xsltFunctionsHash
,
2337 (xmlHashScannerFull
)
2338 xsltDebugDumpExtensionsCallback
, output
);
2339 xmlMutexUnlock(xsltExtMutex
);
2341 if (!xsltElementsHash
)
2342 fprintf(output
, "\nNo registered extension elements\n");
2344 fprintf(output
, "\nRegistered Extension Elements:\n");
2345 xmlMutexLock(xsltExtMutex
);
2346 xmlHashScanFull(xsltElementsHash
,
2347 (xmlHashScannerFull
)
2348 xsltDebugDumpExtensionsCallback
, output
);
2349 xmlMutexUnlock(xsltExtMutex
);
2351 if (!xsltExtensionsHash
)
2352 fprintf(output
, "\nNo registered extension modules\n");
2354 fprintf(output
, "\nRegistered Extension Modules:\n");
2355 xmlMutexLock(xsltExtMutex
);
2356 xmlHashScanFull(xsltExtensionsHash
,
2357 (xmlHashScannerFull
)
2358 xsltDebugDumpExtModulesCallback
, output
);
2359 xmlMutexUnlock(xsltExtMutex
);