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 "xsltlocale.h"
32 #include "xsltutils.h"
34 #include "extensions.h"
37 #include <stdlib.h> /* for _MAX_PATH */
39 #define PATH_MAX _MAX_PATH
43 #ifdef WITH_XSLT_DEBUG
44 #define WITH_XSLT_DEBUG_EXTENSIONS
47 /************************************************************************
49 * Private Types and Globals *
51 ************************************************************************/
53 typedef struct _xsltExtDef xsltExtDef
;
54 typedef xsltExtDef
*xsltExtDefPtr
;
56 struct _xsltExtDef
*next
;
62 typedef struct _xsltExtModule xsltExtModule
;
63 typedef xsltExtModule
*xsltExtModulePtr
;
64 struct _xsltExtModule
{
65 xsltExtInitFunction initFunc
;
66 xsltExtShutdownFunction shutdownFunc
;
67 xsltStyleExtInitFunction styleInitFunc
;
68 xsltStyleExtShutdownFunction styleShutdownFunc
;
71 typedef struct _xsltExtData xsltExtData
;
72 typedef xsltExtData
*xsltExtDataPtr
;
74 xsltExtModulePtr extModule
;
78 typedef struct _xsltExtElement xsltExtElement
;
79 typedef xsltExtElement
*xsltExtElementPtr
;
80 struct _xsltExtElement
{
81 xsltPreComputeFunction precomp
;
82 xsltTransformFunction transform
;
85 static xmlHashTablePtr xsltExtensionsHash
= NULL
;
86 static xmlHashTablePtr xsltFunctionsHash
= NULL
;
87 static xmlHashTablePtr xsltElementsHash
= NULL
;
88 static xmlHashTablePtr xsltTopLevelsHash
= NULL
;
89 static xmlHashTablePtr xsltModuleHash
= NULL
;
90 static xmlMutexPtr xsltExtMutex
= NULL
;
92 /************************************************************************
96 ************************************************************************/
100 * @prefix: the extension prefix
101 * @URI: the namespace URI
103 * Create a new XSLT ExtDef
105 * Returns the newly allocated xsltExtDefPtr or NULL in case of error
108 xsltNewExtDef(const xmlChar
* prefix
, const xmlChar
* URI
)
112 cur
= (xsltExtDefPtr
) xmlMalloc(sizeof(xsltExtDef
));
114 xsltTransformError(NULL
, NULL
, NULL
,
115 "xsltNewExtDef : malloc failed\n");
118 memset(cur
, 0, sizeof(xsltExtDef
));
120 cur
->prefix
= xmlStrdup(prefix
);
122 cur
->URI
= xmlStrdup(URI
);
128 * @extensiond: an XSLT extension definition
130 * Free up the memory allocated by @extensiond
133 xsltFreeExtDef(xsltExtDefPtr extensiond
)
135 if (extensiond
== NULL
)
137 if (extensiond
->prefix
!= NULL
)
138 xmlFree(extensiond
->prefix
);
139 if (extensiond
->URI
!= NULL
)
140 xmlFree(extensiond
->URI
);
145 * xsltFreeExtDefList:
146 * @extensiond: an XSLT extension definition list
148 * Free up the memory allocated by all the elements of @extensiond
151 xsltFreeExtDefList(xsltExtDefPtr extensiond
)
155 while (extensiond
!= NULL
) {
157 extensiond
= extensiond
->next
;
164 * @initFunc: the module initialization function
165 * @shutdownFunc: the module shutdown function
166 * @styleInitFunc: the stylesheet module data allocator function
167 * @styleShutdownFunc: the stylesheet module data free function
169 * Create a new XSLT extension module
171 * Returns the newly allocated xsltExtModulePtr or NULL in case of error
173 static xsltExtModulePtr
174 xsltNewExtModule(xsltExtInitFunction initFunc
,
175 xsltExtShutdownFunction shutdownFunc
,
176 xsltStyleExtInitFunction styleInitFunc
,
177 xsltStyleExtShutdownFunction styleShutdownFunc
)
179 xsltExtModulePtr cur
;
181 cur
= (xsltExtModulePtr
) xmlMalloc(sizeof(xsltExtModule
));
183 xsltTransformError(NULL
, NULL
, NULL
,
184 "xsltNewExtModule : malloc failed\n");
187 cur
->initFunc
= initFunc
;
188 cur
->shutdownFunc
= shutdownFunc
;
189 cur
->styleInitFunc
= styleInitFunc
;
190 cur
->styleShutdownFunc
= styleShutdownFunc
;
196 * @ext: an XSLT extension module
198 * Free up the memory allocated by @ext
201 xsltFreeExtModule(xsltExtModulePtr ext
)
209 xsltFreeExtModuleEntry(void *payload
, const xmlChar
*name ATTRIBUTE_UNUSED
) {
210 xsltFreeExtModule((xsltExtModulePtr
) payload
);
215 * @extModule: the module
216 * @extData: the associated data
218 * Create a new XSLT extension module data wrapper
220 * Returns the newly allocated xsltExtDataPtr or NULL in case of error
222 static xsltExtDataPtr
223 xsltNewExtData(xsltExtModulePtr extModule
, void *extData
)
227 if (extModule
== NULL
)
229 cur
= (xsltExtDataPtr
) xmlMalloc(sizeof(xsltExtData
));
231 xsltTransformError(NULL
, NULL
, NULL
,
232 "xsltNewExtData : malloc failed\n");
235 cur
->extModule
= extModule
;
236 cur
->extData
= extData
;
242 * @ext: an XSLT extension module data wrapper
244 * Free up the memory allocated by @ext
247 xsltFreeExtData(xsltExtDataPtr ext
)
255 xsltFreeExtDataEntry(void *payload
, const xmlChar
*name ATTRIBUTE_UNUSED
) {
256 xsltFreeExtData((xsltExtDataPtr
) payload
);
261 * @precomp: the pre-computation function
262 * @transform: the transformation function
264 * Create a new XSLT extension element
266 * Returns the newly allocated xsltExtElementPtr or NULL in case of
269 static xsltExtElementPtr
270 xsltNewExtElement(xsltPreComputeFunction precomp
,
271 xsltTransformFunction transform
)
273 xsltExtElementPtr cur
;
275 if (transform
== NULL
)
278 cur
= (xsltExtElementPtr
) xmlMalloc(sizeof(xsltExtElement
));
280 xsltTransformError(NULL
, NULL
, NULL
,
281 "xsltNewExtElement : malloc failed\n");
284 cur
->precomp
= precomp
;
285 cur
->transform
= transform
;
290 * xsltFreeExtElement:
291 * @ext: an XSLT extension element
293 * Frees up the memory allocated by @ext
296 xsltFreeExtElement(xsltExtElementPtr ext
)
304 xsltFreeExtElementEntry(void *payload
, const xmlChar
*name ATTRIBUTE_UNUSED
) {
305 xsltFreeExtElement((xsltExtElementPtr
) payload
);
310 typedef void (*exsltRegisterFunction
) (void);
313 #define PATH_MAX 4096
317 * xsltExtModuleRegisterDynamic:
318 * @URI: the function or element namespace URI
320 * Dynamically loads an extension plugin when available.
322 * The plugin name is derived from the URI by removing the
323 * initial protocol designation, e.g. "http://", then converting
324 * the characters ".", "-", "/", and "\" into "_", the removing
325 * any trailing "/", then concatenating LIBXML_MODULE_EXTENSION.
327 * Plugins are loaded from the directory specified by the
328 * environment variable LIBXSLT_PLUGINS_PATH, or if NULL,
329 * by LIBXSLT_DEFAULT_PLUGINS_PATH() which is determined at
332 * Returns 0 if successful, -1 in case of error.
336 xsltExtModuleRegisterDynamic(const xmlChar
* URI
)
340 exsltRegisterFunction regfunc
;
342 char module_filename
[PATH_MAX
];
343 const xmlChar
*ext_directory
= NULL
;
344 const xmlChar
*protocol
= NULL
;
345 xmlChar
*i
, *regfunc_name
;
349 /* check for bad inputs */
353 if (NULL
== xsltModuleHash
) {
354 xsltModuleHash
= xmlHashCreate(5);
355 if (xsltModuleHash
== NULL
)
359 xmlMutexLock(xsltExtMutex
);
361 /* have we attempted to register this module already? */
362 if (xmlHashLookup(xsltModuleHash
, URI
) != NULL
) {
363 xmlMutexUnlock(xsltExtMutex
);
366 xmlMutexUnlock(xsltExtMutex
);
368 /* transform extension namespace into a module name */
369 protocol
= xmlStrstr(URI
, BAD_CAST
"://");
370 if (protocol
== NULL
) {
371 ext_name
= xmlStrdup(URI
);
373 ext_name
= xmlStrdup(protocol
+ 3);
375 if (ext_name
== NULL
) {
381 if (('/' == *i
) || ('\\' == *i
) || ('.' == *i
) || ('-' == *i
))
386 /* Strip underscores from end of string. */
387 while (i
> ext_name
&& *(i
- 1) == '_') {
392 /* determine module directory */
393 ext_directory
= (xmlChar
*) getenv("LIBXSLT_PLUGINS_PATH");
395 if (NULL
== ext_directory
) {
396 ext_directory
= BAD_CAST
LIBXSLT_DEFAULT_PLUGINS_PATH();
397 if (NULL
== ext_directory
)
400 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
402 xsltGenericDebug(xsltGenericDebugContext
,
403 "LIBXSLT_PLUGINS_PATH is %s\n", ext_directory
);
406 /* build the module filename, and confirm the module exists */
407 xmlStrPrintf((xmlChar
*) module_filename
, sizeof(module_filename
),
408 "%s/%s%s", ext_directory
, ext_name
, LIBXML_MODULE_EXTENSION
);
410 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
411 xsltGenericDebug(xsltGenericDebugContext
,
412 "Attempting to load plugin: %s for URI: %s\n",
413 module_filename
, URI
);
416 if (1 != xmlCheckFilename(module_filename
)) {
418 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
419 xsltGenericDebug(xsltGenericDebugContext
,
420 "xmlCheckFilename failed for plugin: %s\n", module_filename
);
427 /* attempt to open the module */
428 m
= xmlModuleOpen(module_filename
, 0);
431 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
432 xsltGenericDebug(xsltGenericDebugContext
,
433 "xmlModuleOpen failed for plugin: %s\n", module_filename
);
440 /* construct initialization func name */
441 regfunc_name
= xmlStrdup(ext_name
);
442 regfunc_name
= xmlStrcat(regfunc_name
, BAD_CAST
"_init");
445 rc
= xmlModuleSymbol(m
, (const char *) regfunc_name
, &vregfunc
);
449 * Call the module's init function. Note that this function
450 * calls xsltRegisterExtModuleFull which will add the module
451 * to xsltExtensionsHash (together with it's entry points).
455 /* register this module in our hash */
456 xmlMutexLock(xsltExtMutex
);
457 xmlHashAddEntry(xsltModuleHash
, URI
, (void *) m
);
458 xmlMutexUnlock(xsltExtMutex
);
461 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
462 xsltGenericDebug(xsltGenericDebugContext
,
463 "xmlModuleSymbol failed for plugin: %s, regfunc: %s\n",
464 module_filename
, regfunc_name
);
467 /* if regfunc not found unload the module immediately */
472 xmlFree(regfunc_name
);
473 return (NULL
== regfunc
) ? -1 : 0;
477 xsltExtModuleRegisterDynamic(const xmlChar
* URI ATTRIBUTE_UNUSED
)
483 /************************************************************************
485 * The stylesheet extension prefixes handling *
487 ************************************************************************/
492 * @style: an XSLT stylesheet
494 * Free up the memory used by XSLT extensions in a stylesheet
497 xsltFreeExts(xsltStylesheetPtr style
)
499 if (style
->nsDefs
!= NULL
)
500 xsltFreeExtDefList((xsltExtDefPtr
) style
->nsDefs
);
504 * xsltRegisterExtPrefix:
505 * @style: an XSLT stylesheet
506 * @prefix: the prefix used (optional)
507 * @URI: the URI associated to the extension
509 * Registers an extension namespace
510 * This is called from xslt.c during compile-time.
511 * The given prefix is not needed.
513 * xsltParseExtElemPrefixes() (new function)
514 * xsltRegisterExtPrefix() (old function)
516 * Returns 0 in case of success, 1 if the @URI was already
517 * registered as an extension namespace and
518 * -1 in case of failure
521 xsltRegisterExtPrefix(xsltStylesheetPtr style
,
522 const xmlChar
* prefix
, const xmlChar
* URI
)
524 xsltExtDefPtr def
, ret
;
526 if ((style
== NULL
) || (URI
== NULL
))
529 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
530 xsltGenericDebug(xsltGenericDebugContext
,
531 "Registering extension namespace '%s'.\n", URI
);
533 def
= (xsltExtDefPtr
) style
->nsDefs
;
534 #ifdef XSLT_REFACTORED
536 * The extension is associated with a namespace name.
538 while (def
!= NULL
) {
539 if (xmlStrEqual(URI
, def
->URI
))
544 while (def
!= NULL
) {
545 if (xmlStrEqual(prefix
, def
->prefix
))
550 ret
= xsltNewExtDef(prefix
, URI
);
553 ret
->next
= (xsltExtDefPtr
) style
->nsDefs
;
557 * check whether there is an extension module with a stylesheet
558 * initialization function.
560 #ifdef XSLT_REFACTORED
562 * Don't initialize modules based on specified namespaces via
563 * the attribute "[xsl:]extension-element-prefixes".
566 if (xsltExtensionsHash
!= NULL
) {
567 xsltExtModulePtr module
;
569 xmlMutexLock(xsltExtMutex
);
570 module
= xmlHashLookup(xsltExtensionsHash
, URI
);
571 xmlMutexUnlock(xsltExtMutex
);
572 if (NULL
== module
) {
573 if (!xsltExtModuleRegisterDynamic(URI
)) {
574 xmlMutexLock(xsltExtMutex
);
575 module
= xmlHashLookup(xsltExtensionsHash
, URI
);
576 xmlMutexUnlock(xsltExtMutex
);
579 if (module
!= NULL
) {
580 xsltStyleGetExtData(style
, URI
);
587 /************************************************************************
589 * The extensions modules interfaces *
591 ************************************************************************/
594 * xsltRegisterExtFunction:
595 * @ctxt: an XSLT transformation context
596 * @name: the name of the element
597 * @URI: the URI associated to the element
598 * @function: the actual implementation which should be called
600 * Registers an extension function
602 * Returns 0 in case of success, -1 in case of failure
605 xsltRegisterExtFunction(xsltTransformContextPtr ctxt
, const xmlChar
* name
,
606 const xmlChar
* URI
, xmlXPathFunction function
)
610 if ((ctxt
== NULL
) || (name
== NULL
) ||
611 (URI
== NULL
) || (function
== NULL
))
613 if (ctxt
->xpathCtxt
!= NULL
) {
614 xmlXPathRegisterFuncNS(ctxt
->xpathCtxt
, name
, URI
, function
);
616 if (ctxt
->extFunctions
== NULL
)
617 ctxt
->extFunctions
= xmlHashCreate(10);
618 if (ctxt
->extFunctions
== NULL
)
621 ret
= xmlHashAddEntry2(ctxt
->extFunctions
, name
, URI
,
622 XML_CAST_FPTR(function
));
628 * xsltRegisterExtElement:
629 * @ctxt: an XSLT transformation context
630 * @name: the name of the element
631 * @URI: the URI associated to the element
632 * @function: the actual implementation which should be called
634 * Registers an extension element
636 * Returns 0 in case of success, -1 in case of failure
639 xsltRegisterExtElement(xsltTransformContextPtr ctxt
, const xmlChar
* name
,
640 const xmlChar
* URI
, xsltTransformFunction function
)
642 if ((ctxt
== NULL
) || (name
== NULL
) ||
643 (URI
== NULL
) || (function
== NULL
))
645 if (ctxt
->extElements
== NULL
)
646 ctxt
->extElements
= xmlHashCreate(10);
647 if (ctxt
->extElements
== NULL
)
649 return (xmlHashAddEntry2
650 (ctxt
->extElements
, name
, URI
, XML_CAST_FPTR(function
)));
655 * @ctxt: an XSLT transformation context
657 * Free the XSLT extension data
660 xsltFreeCtxtExts(xsltTransformContextPtr ctxt
)
662 if (ctxt
->extElements
!= NULL
)
663 xmlHashFree(ctxt
->extElements
, NULL
);
664 if (ctxt
->extFunctions
!= NULL
)
665 xmlHashFree(ctxt
->extFunctions
, NULL
);
669 * xsltStyleGetStylesheetExtData:
670 * @style: an XSLT stylesheet
671 * @URI: the URI associated to the exension module
673 * Fires the compile-time initialization callback
674 * of an extension module and returns a container
675 * holding the user-data (retrieved via the callback).
677 * Returns the create module-data container
678 * or NULL if such a module was not registered.
680 static xsltExtDataPtr
681 xsltStyleInitializeStylesheetModule(xsltStylesheetPtr style
,
684 xsltExtDataPtr dataContainer
;
685 void *userData
= NULL
;
686 xsltExtModulePtr module
;
688 if ((style
== NULL
) || (URI
== NULL
))
691 if (xsltExtensionsHash
== NULL
) {
692 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
693 xsltGenericDebug(xsltGenericDebugContext
,
694 "Not registered extension module: %s\n", URI
);
699 xmlMutexLock(xsltExtMutex
);
701 module
= xmlHashLookup(xsltExtensionsHash
, URI
);
703 xmlMutexUnlock(xsltExtMutex
);
705 if (module
== NULL
) {
706 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
707 xsltGenericDebug(xsltGenericDebugContext
,
708 "Not registered extension module: %s\n", URI
);
713 * The specified module was registered so initialize it.
715 if (style
->extInfos
== NULL
) {
716 style
->extInfos
= xmlHashCreate(10);
717 if (style
->extInfos
== NULL
)
721 * Fire the initialization callback if available.
723 if (module
->styleInitFunc
== NULL
) {
724 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
725 xsltGenericDebug(xsltGenericDebugContext
,
726 "Initializing module with *no* callback: %s\n", URI
);
729 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
730 xsltGenericDebug(xsltGenericDebugContext
,
731 "Initializing module with callback: %s\n", URI
);
734 * Fire the initialization callback.
736 userData
= module
->styleInitFunc(style
, URI
);
739 * Store the user-data in the context of the given stylesheet.
741 dataContainer
= xsltNewExtData(module
, userData
);
742 if (dataContainer
== NULL
) {
743 if (module
->styleShutdownFunc
)
744 module
->styleShutdownFunc(style
, URI
, userData
);
748 if (xmlHashAddEntry(style
->extInfos
, URI
,
749 (void *) dataContainer
) < 0)
751 xsltTransformError(NULL
, style
, NULL
,
752 "Failed to register module '%s'.\n", URI
);
754 if (module
->styleShutdownFunc
)
755 module
->styleShutdownFunc(style
, URI
, userData
);
756 xsltFreeExtData(dataContainer
);
760 return(dataContainer
);
764 * xsltStyleGetExtData:
765 * @style: an XSLT stylesheet
766 * @URI: the URI associated to the exension module
768 * Retrieve the data associated to the extension module
769 * in this given stylesheet.
771 * xsltRegisterExtPrefix(),
772 * ( xsltExtElementPreCompTest(), xsltExtInitTest )
774 * Returns the pointer or NULL if not present
777 xsltStyleGetExtData(xsltStylesheetPtr style
, const xmlChar
* URI
)
779 xsltExtDataPtr dataContainer
= NULL
;
780 xsltStylesheetPtr tmpStyle
;
782 if ((style
== NULL
) || (URI
== NULL
) ||
783 (xsltExtensionsHash
== NULL
))
787 #ifdef XSLT_REFACTORED
789 * This is intended for global storage, so only the main
790 * stylesheet will hold the data.
793 while (tmpStyle
->parent
!= NULL
)
794 tmpStyle
= tmpStyle
->parent
;
795 if (tmpStyle
->extInfos
!= NULL
) {
797 (xsltExtDataPtr
) xmlHashLookup(tmpStyle
->extInfos
, URI
);
798 if (dataContainer
!= NULL
) {
800 * The module was already initialized in the context
801 * of this stylesheet; just return the user-data that
804 return(dataContainer
->extData
);
812 while (tmpStyle
!= NULL
) {
813 if (tmpStyle
->extInfos
!= NULL
) {
815 (xsltExtDataPtr
) xmlHashLookup(tmpStyle
->extInfos
, URI
);
816 if (dataContainer
!= NULL
) {
817 return(dataContainer
->extData
);
820 tmpStyle
= xsltNextImport(tmpStyle
);
826 xsltStyleInitializeStylesheetModule(tmpStyle
, URI
);
827 if (dataContainer
!= NULL
)
828 return (dataContainer
->extData
);
832 #ifdef XSLT_REFACTORED
834 * xsltStyleStylesheetLevelGetExtData:
835 * @style: an XSLT stylesheet
836 * @URI: the URI associated to the exension module
838 * Retrieve the data associated to the extension module in this given
841 * Returns the pointer or NULL if not present
844 xsltStyleStylesheetLevelGetExtData(xsltStylesheetPtr style
,
847 xsltExtDataPtr dataContainer
= NULL
;
849 if ((style
== NULL
) || (URI
== NULL
) ||
850 (xsltExtensionsHash
== NULL
))
853 if (style
->extInfos
!= NULL
) {
854 dataContainer
= (xsltExtDataPtr
) xmlHashLookup(style
->extInfos
, URI
);
856 * The module was already initialized in the context
857 * of this stylesheet; just return the user-data that
861 return(dataContainer
->extData
);
865 xsltStyleInitializeStylesheetModule(style
, URI
);
866 if (dataContainer
!= NULL
)
867 return (dataContainer
->extData
);
874 * @ctxt: an XSLT transformation context
875 * @URI: the URI associated to the exension module
877 * Retrieve the data associated to the extension module in this given
880 * Returns the pointer or NULL if not present
883 xsltGetExtData(xsltTransformContextPtr ctxt
, const xmlChar
* URI
)
887 if ((ctxt
== NULL
) || (URI
== NULL
))
889 if (ctxt
->extInfos
== NULL
) {
890 ctxt
->extInfos
= xmlHashCreate(10);
891 if (ctxt
->extInfos
== NULL
)
895 data
= (xsltExtDataPtr
) xmlHashLookup(ctxt
->extInfos
, URI
);
899 xsltExtModulePtr module
;
901 xmlMutexLock(xsltExtMutex
);
903 module
= xmlHashLookup(xsltExtensionsHash
, URI
);
905 xmlMutexUnlock(xsltExtMutex
);
907 if (module
== NULL
) {
908 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
909 xsltGenericDebug(xsltGenericDebugContext
,
910 "Not registered extension module: %s\n", URI
);
914 if (module
->initFunc
== NULL
)
917 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
918 xsltGenericDebug(xsltGenericDebugContext
,
919 "Initializing module: %s\n", URI
);
922 extData
= module
->initFunc(ctxt
, URI
);
926 data
= xsltNewExtData(module
, extData
);
927 if ((data
== NULL
) ||
928 (xmlHashAddEntry(ctxt
->extInfos
, URI
, (void *) data
) < 0)) {
929 xsltTransformError(ctxt
, NULL
, NULL
,
930 "Failed to register module data: %s\n",
932 if (module
->shutdownFunc
)
933 module
->shutdownFunc(ctxt
, URI
, extData
);
934 xsltFreeExtData(data
);
939 return (data
->extData
);
942 typedef struct _xsltInitExtCtxt xsltInitExtCtxt
;
943 struct _xsltInitExtCtxt
{
944 xsltTransformContextPtr ctxt
;
950 * @styleData: the registered stylesheet data for the module
951 * @ctxt: the XSLT transformation context + the return value
952 * @URI: the extension URI
954 * Initializes an extension module
957 xsltInitCtxtExt(void *payload
, void *data
, const xmlChar
* URI
)
959 xsltExtDataPtr styleData
= (xsltExtDataPtr
) payload
;
960 xsltInitExtCtxt
*ctxt
= (xsltInitExtCtxt
*) data
;
961 xsltExtModulePtr module
;
962 xsltExtDataPtr ctxtData
;
965 if ((styleData
== NULL
) || (ctxt
== NULL
) || (URI
== NULL
) ||
967 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
968 xsltGenericDebug(xsltGenericDebugContext
,
969 "xsltInitCtxtExt: NULL param or error\n");
973 module
= styleData
->extModule
;
974 if ((module
== NULL
) || (module
->initFunc
== NULL
)) {
975 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
976 xsltGenericDebug(xsltGenericDebugContext
,
977 "xsltInitCtxtExt: no module or no initFunc\n");
982 ctxtData
= (xsltExtDataPtr
) xmlHashLookup(ctxt
->ctxt
->extInfos
, URI
);
983 if (ctxtData
!= NULL
) {
984 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
985 xsltGenericDebug(xsltGenericDebugContext
,
986 "xsltInitCtxtExt: already initialized\n");
991 extData
= module
->initFunc(ctxt
->ctxt
, URI
);
992 if (extData
== NULL
) {
993 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
994 xsltGenericDebug(xsltGenericDebugContext
,
995 "xsltInitCtxtExt: no extData\n");
998 ctxtData
= xsltNewExtData(module
, extData
);
999 if (ctxtData
== NULL
) {
1000 if (module
->shutdownFunc
)
1001 module
->shutdownFunc(ctxt
->ctxt
, URI
, extData
);
1006 if (ctxt
->ctxt
->extInfos
== NULL
)
1007 ctxt
->ctxt
->extInfos
= xmlHashCreate(10);
1008 if (ctxt
->ctxt
->extInfos
== NULL
) {
1009 if (module
->shutdownFunc
)
1010 module
->shutdownFunc(ctxt
->ctxt
, URI
, extData
);
1011 xsltFreeExtData(ctxtData
);
1016 if (xmlHashAddEntry(ctxt
->ctxt
->extInfos
, URI
, ctxtData
) < 0) {
1017 xsltGenericError(xsltGenericErrorContext
,
1018 "Failed to register module data: %s\n", URI
);
1019 if (module
->shutdownFunc
)
1020 module
->shutdownFunc(ctxt
->ctxt
, URI
, extData
);
1021 xsltFreeExtData(ctxtData
);
1025 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
1026 xsltGenericDebug(xsltGenericDebugContext
, "Registered module %s\n",
1034 * @ctxt: an XSLT transformation context
1036 * Initialize the set of modules with registered stylesheet data
1038 * Returns the number of modules initialized or -1 in case of error
1041 xsltInitCtxtExts(xsltTransformContextPtr ctxt
)
1043 xsltStylesheetPtr style
;
1044 xsltInitExtCtxt ctx
;
1049 style
= ctxt
->style
;
1056 while (style
!= NULL
) {
1057 if (style
->extInfos
!= NULL
) {
1058 xmlHashScan(style
->extInfos
, xsltInitCtxtExt
, &ctx
);
1062 style
= xsltNextImport(style
);
1064 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
1065 xsltGenericDebug(xsltGenericDebugContext
, "Registered %d modules\n",
1072 * xsltShutdownCtxtExt:
1073 * @data: the registered data for the module
1074 * @ctxt: the XSLT transformation context
1075 * @URI: the extension URI
1077 * Shutdown an extension module loaded
1080 xsltShutdownCtxtExt(void *payload
, void *vctxt
, const xmlChar
* URI
)
1082 xsltExtDataPtr data
= (xsltExtDataPtr
) payload
;
1083 xsltTransformContextPtr ctxt
= (xsltTransformContextPtr
) vctxt
;
1084 xsltExtModulePtr module
;
1086 if ((data
== NULL
) || (ctxt
== NULL
) || (URI
== NULL
))
1088 module
= data
->extModule
;
1089 if ((module
== NULL
) || (module
->shutdownFunc
== NULL
))
1092 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
1093 xsltGenericDebug(xsltGenericDebugContext
,
1094 "Shutting down module : %s\n", URI
);
1096 module
->shutdownFunc(ctxt
, URI
, data
->extData
);
1100 * xsltShutdownCtxtExts:
1101 * @ctxt: an XSLT transformation context
1103 * Shutdown the set of modules loaded
1106 xsltShutdownCtxtExts(xsltTransformContextPtr ctxt
)
1110 if (ctxt
->extInfos
== NULL
)
1112 xmlHashScan(ctxt
->extInfos
, xsltShutdownCtxtExt
, ctxt
);
1113 xmlHashFree(ctxt
->extInfos
, xsltFreeExtDataEntry
);
1114 ctxt
->extInfos
= NULL
;
1119 * @data: the registered data for the module
1120 * @ctxt: the XSLT stylesheet
1121 * @URI: the extension URI
1123 * Shutdown an extension module loaded
1126 xsltShutdownExt(void *payload
, void *vctxt
, const xmlChar
* URI
)
1128 xsltExtDataPtr data
= (xsltExtDataPtr
) payload
;
1129 xsltStylesheetPtr style
= (xsltStylesheetPtr
) vctxt
;
1130 xsltExtModulePtr module
;
1132 if ((data
== NULL
) || (style
== NULL
) || (URI
== NULL
))
1134 module
= data
->extModule
;
1135 if ((module
== NULL
) || (module
->styleShutdownFunc
== NULL
))
1138 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
1139 xsltGenericDebug(xsltGenericDebugContext
,
1140 "Shutting down module : %s\n", URI
);
1142 module
->styleShutdownFunc(style
, URI
, data
->extData
);
1144 * Don't remove the entry from the hash table here, since
1145 * this will produce segfaults - this fixes bug #340624.
1147 * xmlHashRemoveEntry(style->extInfos, URI, xsltFreeExtDataEntry);
1153 * @style: an XSLT stylesheet
1155 * Shutdown the set of modules loaded
1158 xsltShutdownExts(xsltStylesheetPtr style
)
1162 if (style
->extInfos
== NULL
)
1164 xmlHashScan(style
->extInfos
, xsltShutdownExt
, style
);
1165 xmlHashFree(style
->extInfos
, xsltFreeExtDataEntry
);
1166 style
->extInfos
= NULL
;
1170 * xsltCheckExtPrefix:
1171 * @style: the stylesheet
1172 * @URI: the namespace prefix (possibly NULL)
1174 * Check if the given prefix is one of the declared extensions.
1175 * This is intended to be called only at compile-time.
1177 * xsltGetInheritedNsList() (xslt.c)
1178 * xsltParseTemplateContent (xslt.c)
1180 * Returns 1 if this is an extension, 0 otherwise
1183 xsltCheckExtPrefix(xsltStylesheetPtr style
, const xmlChar
* URI
)
1185 #ifdef XSLT_REFACTORED
1186 if ((style
== NULL
) || (style
->compCtxt
== NULL
) ||
1187 (XSLT_CCTXT(style
)->inode
== NULL
) ||
1188 (XSLT_CCTXT(style
)->inode
->extElemNs
== NULL
))
1191 * Lookup the extension namespaces registered
1192 * at the current node in the stylesheet's tree.
1194 if (XSLT_CCTXT(style
)->inode
->extElemNs
!= NULL
) {
1196 xsltPointerListPtr list
= XSLT_CCTXT(style
)->inode
->extElemNs
;
1198 for (i
= 0; i
< list
->number
; i
++) {
1199 if (xmlStrEqual((const xmlChar
*) list
->items
[i
],
1209 if ((style
== NULL
) || (style
->nsDefs
== NULL
))
1212 URI
= BAD_CAST
"#default";
1213 cur
= (xsltExtDefPtr
) style
->nsDefs
;
1214 while (cur
!= NULL
) {
1216 * NOTE: This was change to work on namespace names rather
1217 * than namespace prefixes. This fixes bug #339583.
1218 * TODO: Consider renaming the field "prefix" of xsltExtDef
1221 if (xmlStrEqual(URI
, cur
->prefix
))
1231 * @style: the stylesheet
1232 * @URI: the namespace URI (possibly NULL)
1234 * Check if the given prefix is one of the declared extensions.
1235 * This is intended to be called only at compile-time.
1237 * xsltPrecomputeStylesheet() (xslt.c)
1238 * xsltParseTemplateContent (xslt.c)
1240 * Returns 1 if this is an extension, 0 otherwise
1243 xsltCheckExtURI(xsltStylesheetPtr style
, const xmlChar
* URI
)
1247 if ((style
== NULL
) || (style
->nsDefs
== NULL
))
1251 cur
= (xsltExtDefPtr
) style
->nsDefs
;
1252 while (cur
!= NULL
) {
1253 if (xmlStrEqual(URI
, cur
->URI
))
1261 * xsltRegisterExtModuleFull:
1262 * @URI: URI associated to this module
1263 * @initFunc: the module initialization function
1264 * @shutdownFunc: the module shutdown function
1265 * @styleInitFunc: the module initialization function
1266 * @styleShutdownFunc: the module shutdown function
1268 * Register an XSLT extension module to the library.
1270 * Returns 0 if sucessful, -1 in case of error
1273 xsltRegisterExtModuleFull(const xmlChar
* URI
,
1274 xsltExtInitFunction initFunc
,
1275 xsltExtShutdownFunction shutdownFunc
,
1276 xsltStyleExtInitFunction styleInitFunc
,
1277 xsltStyleExtShutdownFunction styleShutdownFunc
)
1280 xsltExtModulePtr module
;
1282 if ((URI
== NULL
) || (initFunc
== NULL
))
1284 if (xsltExtensionsHash
== NULL
)
1285 xsltExtensionsHash
= xmlHashCreate(10);
1287 if (xsltExtensionsHash
== NULL
)
1290 xmlMutexLock(xsltExtMutex
);
1292 module
= xmlHashLookup(xsltExtensionsHash
, URI
);
1293 if (module
!= NULL
) {
1294 if ((module
->initFunc
== initFunc
) &&
1295 (module
->shutdownFunc
== shutdownFunc
))
1301 module
= xsltNewExtModule(initFunc
, shutdownFunc
,
1302 styleInitFunc
, styleShutdownFunc
);
1303 if (module
== NULL
) {
1307 ret
= xmlHashAddEntry(xsltExtensionsHash
, URI
, (void *) module
);
1310 xmlMutexUnlock(xsltExtMutex
);
1315 * xsltRegisterExtModule:
1316 * @URI: URI associated to this module
1317 * @initFunc: the module initialization function
1318 * @shutdownFunc: the module shutdown function
1320 * Register an XSLT extension module to the library.
1322 * Returns 0 if sucessful, -1 in case of error
1325 xsltRegisterExtModule(const xmlChar
* URI
,
1326 xsltExtInitFunction initFunc
,
1327 xsltExtShutdownFunction shutdownFunc
)
1329 return xsltRegisterExtModuleFull(URI
, initFunc
, shutdownFunc
,
1334 * xsltUnregisterExtModule:
1335 * @URI: URI associated to this module
1337 * Unregister an XSLT extension module from the library.
1339 * Returns 0 if sucessful, -1 in case of error
1342 xsltUnregisterExtModule(const xmlChar
* URI
)
1348 if (xsltExtensionsHash
== NULL
)
1351 xmlMutexLock(xsltExtMutex
);
1353 ret
= xmlHashRemoveEntry(xsltExtensionsHash
, URI
, xsltFreeExtModuleEntry
);
1355 xmlMutexUnlock(xsltExtMutex
);
1361 * xsltUnregisterAllExtModules:
1363 * Unregister all the XSLT extension module from the library.
1366 xsltUnregisterAllExtModules(void)
1368 if (xsltExtensionsHash
== NULL
)
1371 xmlMutexLock(xsltExtMutex
);
1373 xmlHashFree(xsltExtensionsHash
, xsltFreeExtModuleEntry
);
1374 xsltExtensionsHash
= NULL
;
1376 xmlMutexUnlock(xsltExtMutex
);
1380 * xsltXPathGetTransformContext:
1381 * @ctxt: an XPath transformation context
1383 * Provides the XSLT transformation context from the XPath transformation
1384 * context. This is useful when an XPath function in the extension module
1385 * is called by the XPath interpreter and that the XSLT context is needed
1386 * for example to retrieve the associated data pertaining to this XSLT
1389 * Returns the XSLT transformation context or NULL in case of error.
1391 xsltTransformContextPtr
1392 xsltXPathGetTransformContext(xmlXPathParserContextPtr ctxt
)
1394 if ((ctxt
== NULL
) || (ctxt
->context
== NULL
))
1396 return (ctxt
->context
->extra
);
1400 * xsltRegisterExtModuleFunction:
1401 * @name: the function name
1402 * @URI: the function namespace URI
1403 * @function: the function callback
1405 * Registers an extension module function.
1407 * Returns 0 if successful, -1 in case of error.
1410 xsltRegisterExtModuleFunction(const xmlChar
* name
, const xmlChar
* URI
,
1411 xmlXPathFunction function
)
1413 if ((name
== NULL
) || (URI
== NULL
) || (function
== NULL
))
1416 if (xsltFunctionsHash
== NULL
)
1417 xsltFunctionsHash
= xmlHashCreate(10);
1418 if (xsltFunctionsHash
== NULL
)
1421 xmlMutexLock(xsltExtMutex
);
1423 xmlHashUpdateEntry2(xsltFunctionsHash
, name
, URI
,
1424 XML_CAST_FPTR(function
), NULL
);
1426 xmlMutexUnlock(xsltExtMutex
);
1432 * xsltExtModuleFunctionLookup:
1433 * @name: the function name
1434 * @URI: the function namespace URI
1436 * Looks up an extension module function
1438 * Returns the function if found, NULL otherwise.
1441 xsltExtModuleFunctionLookup(const xmlChar
* name
, const xmlChar
* URI
)
1443 xmlXPathFunction ret
;
1445 if ((xsltFunctionsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1448 xmlMutexLock(xsltExtMutex
);
1450 XML_CAST_FPTR(ret
) = xmlHashLookup2(xsltFunctionsHash
, name
, URI
);
1452 xmlMutexUnlock(xsltExtMutex
);
1454 /* if lookup fails, attempt a dynamic load on supported platforms */
1456 if (!xsltExtModuleRegisterDynamic(URI
)) {
1457 xmlMutexLock(xsltExtMutex
);
1459 XML_CAST_FPTR(ret
) =
1460 xmlHashLookup2(xsltFunctionsHash
, name
, URI
);
1462 xmlMutexUnlock(xsltExtMutex
);
1470 * xsltUnregisterExtModuleFunction:
1471 * @name: the function name
1472 * @URI: the function namespace URI
1474 * Unregisters an extension module function
1476 * Returns 0 if successful, -1 in case of error.
1479 xsltUnregisterExtModuleFunction(const xmlChar
* name
, const xmlChar
* URI
)
1483 if ((xsltFunctionsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1486 xmlMutexLock(xsltExtMutex
);
1488 ret
= xmlHashRemoveEntry2(xsltFunctionsHash
, name
, URI
, NULL
);
1490 xmlMutexUnlock(xsltExtMutex
);
1496 * xsltUnregisterAllExtModuleFunction:
1498 * Unregisters all extension module function
1501 xsltUnregisterAllExtModuleFunction(void)
1503 xmlMutexLock(xsltExtMutex
);
1505 xmlHashFree(xsltFunctionsHash
, NULL
);
1506 xsltFunctionsHash
= NULL
;
1508 xmlMutexUnlock(xsltExtMutex
);
1513 xsltFreeElemPreComp(xsltElemPreCompPtr comp
) {
1518 * xsltNewElemPreComp:
1519 * @style: the XSLT stylesheet
1520 * @inst: the element node
1521 * @function: the transform function
1523 * Creates and initializes an #xsltElemPreComp
1525 * Returns the new and initialized #xsltElemPreComp
1528 xsltNewElemPreComp(xsltStylesheetPtr style
, xmlNodePtr inst
,
1529 xsltTransformFunction function
)
1531 xsltElemPreCompPtr cur
;
1533 cur
= (xsltElemPreCompPtr
) xmlMalloc(sizeof(xsltElemPreComp
));
1535 xsltTransformError(NULL
, style
, NULL
,
1536 "xsltNewExtElement : malloc failed\n");
1539 memset(cur
, 0, sizeof(xsltElemPreComp
));
1541 xsltInitElemPreComp(cur
, style
, inst
, function
, xsltFreeElemPreComp
);
1547 * xsltInitElemPreComp:
1548 * @comp: an #xsltElemPreComp (or generally a derived structure)
1549 * @style: the XSLT stylesheet
1550 * @inst: the element node
1551 * @function: the transform function
1552 * @freeFunc: the @comp deallocator
1554 * Initializes an existing #xsltElemPreComp structure. This is usefull
1555 * when extending an #xsltElemPreComp to store precomputed data.
1556 * This function MUST be called on any extension element precomputed
1560 xsltInitElemPreComp(xsltElemPreCompPtr comp
, xsltStylesheetPtr style
,
1561 xmlNodePtr inst
, xsltTransformFunction function
,
1562 xsltElemPreCompDeallocator freeFunc
)
1564 comp
->type
= XSLT_FUNC_EXTENSION
;
1565 comp
->func
= function
;
1567 comp
->free
= freeFunc
;
1569 comp
->next
= style
->preComps
;
1570 style
->preComps
= comp
;
1574 * xsltPreComputeExtModuleElement:
1575 * @style: the stylesheet
1576 * @inst: the element node
1578 * Precomputes an extension module element
1580 * Returns the precomputed data
1583 xsltPreComputeExtModuleElement(xsltStylesheetPtr style
, xmlNodePtr inst
)
1585 xsltExtElementPtr ext
;
1586 xsltElemPreCompPtr comp
= NULL
;
1588 if ((style
== NULL
) || (inst
== NULL
) ||
1589 (inst
->type
!= XML_ELEMENT_NODE
) || (inst
->ns
== NULL
))
1592 xmlMutexLock(xsltExtMutex
);
1594 ext
= (xsltExtElementPtr
)
1595 xmlHashLookup2(xsltElementsHash
, inst
->name
, inst
->ns
->href
);
1597 xmlMutexUnlock(xsltExtMutex
);
1600 * EXT TODO: Now what?
1605 if (ext
->precomp
!= NULL
) {
1607 * REVISIT TODO: Check if the text below is correct.
1608 * This will return a xsltElemPreComp structure or NULL.
1609 * 1) If the the author of the extension needs a
1610 * custom structure to hold the specific values of
1611 * this extension, he will derive a structure based on
1612 * xsltElemPreComp; thus we obviously *cannot* refactor
1613 * the xsltElemPreComp structure, since all already derived
1614 * user-defined strucures will break.
1615 * Example: For the extension xsl:document,
1616 * in xsltDocumentComp() (preproc.c), the structure
1617 * xsltStyleItemDocument is allocated, filled with
1618 * specific values and returned.
1619 * 2) If the author needs no values to be stored in
1620 * this structure, then he'll return NULL;
1622 comp
= ext
->precomp(style
, inst
, ext
->transform
);
1626 * Default creation of a xsltElemPreComp structure, if
1627 * the author of this extension did not create a custom
1630 comp
= xsltNewElemPreComp(style
, inst
, ext
->transform
);
1637 * xsltRegisterExtModuleElement:
1638 * @name: the element name
1639 * @URI: the element namespace URI
1640 * @precomp: the pre-computation callback
1641 * @transform: the transformation callback
1643 * Registers an extension module element.
1645 * Returns 0 if successful, -1 in case of error.
1648 xsltRegisterExtModuleElement(const xmlChar
* name
, const xmlChar
* URI
,
1649 xsltPreComputeFunction precomp
,
1650 xsltTransformFunction transform
)
1654 xsltExtElementPtr ext
;
1656 if ((name
== NULL
) || (URI
== NULL
) || (transform
== NULL
))
1659 if (xsltElementsHash
== NULL
)
1660 xsltElementsHash
= xmlHashCreate(10);
1661 if (xsltElementsHash
== NULL
)
1664 xmlMutexLock(xsltExtMutex
);
1666 ext
= xsltNewExtElement(precomp
, transform
);
1672 xmlHashUpdateEntry2(xsltElementsHash
, name
, URI
, (void *) ext
,
1673 xsltFreeExtElementEntry
);
1676 xmlMutexUnlock(xsltExtMutex
);
1682 * xsltExtElementLookup:
1683 * @ctxt: an XSLT process context
1684 * @name: the element name
1685 * @URI: the element namespace URI
1687 * Looks up an extension element. @ctxt can be NULL to search only in
1690 * Returns the element callback or NULL if not found
1692 xsltTransformFunction
1693 xsltExtElementLookup(xsltTransformContextPtr ctxt
,
1694 const xmlChar
* name
, const xmlChar
* URI
)
1696 xsltTransformFunction ret
;
1698 if ((name
== NULL
) || (URI
== NULL
))
1701 if ((ctxt
!= NULL
) && (ctxt
->extElements
!= NULL
)) {
1702 XML_CAST_FPTR(ret
) = xmlHashLookup2(ctxt
->extElements
, name
, URI
);
1708 ret
= xsltExtModuleElementLookup(name
, URI
);
1714 * xsltExtModuleElementLookup:
1715 * @name: the element name
1716 * @URI: the element namespace URI
1718 * Looks up an extension module element
1720 * Returns the callback function if found, NULL otherwise.
1722 xsltTransformFunction
1723 xsltExtModuleElementLookup(const xmlChar
* name
, const xmlChar
* URI
)
1725 xsltExtElementPtr ext
;
1727 if ((xsltElementsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1730 xmlMutexLock(xsltExtMutex
);
1732 ext
= (xsltExtElementPtr
) xmlHashLookup2(xsltElementsHash
, name
, URI
);
1734 xmlMutexUnlock(xsltExtMutex
);
1737 * if function lookup fails, attempt a dynamic load on
1738 * supported platforms
1741 if (!xsltExtModuleRegisterDynamic(URI
)) {
1742 xmlMutexLock(xsltExtMutex
);
1744 ext
= (xsltExtElementPtr
)
1745 xmlHashLookup2(xsltElementsHash
, name
, URI
);
1747 xmlMutexUnlock(xsltExtMutex
);
1753 return (ext
->transform
);
1757 * xsltExtModuleElementPreComputeLookup:
1758 * @name: the element name
1759 * @URI: the element namespace URI
1761 * Looks up an extension module element pre-computation function
1763 * Returns the callback function if found, NULL otherwise.
1765 xsltPreComputeFunction
1766 xsltExtModuleElementPreComputeLookup(const xmlChar
* name
,
1767 const xmlChar
* URI
)
1769 xsltExtElementPtr ext
;
1771 if ((xsltElementsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1774 xmlMutexLock(xsltExtMutex
);
1776 ext
= (xsltExtElementPtr
) xmlHashLookup2(xsltElementsHash
, name
, URI
);
1778 xmlMutexUnlock(xsltExtMutex
);
1781 if (!xsltExtModuleRegisterDynamic(URI
)) {
1782 xmlMutexLock(xsltExtMutex
);
1784 ext
= (xsltExtElementPtr
)
1785 xmlHashLookup2(xsltElementsHash
, name
, URI
);
1787 xmlMutexUnlock(xsltExtMutex
);
1793 return (ext
->precomp
);
1797 * xsltUnregisterExtModuleElement:
1798 * @name: the element name
1799 * @URI: the element namespace URI
1801 * Unregisters an extension module element
1803 * Returns 0 if successful, -1 in case of error.
1806 xsltUnregisterExtModuleElement(const xmlChar
* name
, const xmlChar
* URI
)
1810 if ((xsltElementsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1813 xmlMutexLock(xsltExtMutex
);
1815 ret
= xmlHashRemoveEntry2(xsltElementsHash
, name
, URI
,
1816 xsltFreeExtElementEntry
);
1818 xmlMutexUnlock(xsltExtMutex
);
1824 * xsltUnregisterAllExtModuleElement:
1826 * Unregisters all extension module element
1829 xsltUnregisterAllExtModuleElement(void)
1831 xmlMutexLock(xsltExtMutex
);
1833 xmlHashFree(xsltElementsHash
, xsltFreeExtElementEntry
);
1834 xsltElementsHash
= NULL
;
1836 xmlMutexUnlock(xsltExtMutex
);
1840 * xsltRegisterExtModuleTopLevel:
1841 * @name: the top-level element name
1842 * @URI: the top-level element namespace URI
1843 * @function: the top-level element callback
1845 * Registers an extension module top-level element.
1847 * Returns 0 if successful, -1 in case of error.
1850 xsltRegisterExtModuleTopLevel(const xmlChar
* name
, const xmlChar
* URI
,
1851 xsltTopLevelFunction function
)
1853 if ((name
== NULL
) || (URI
== NULL
) || (function
== NULL
))
1856 if (xsltTopLevelsHash
== NULL
)
1857 xsltTopLevelsHash
= xmlHashCreate(10);
1858 if (xsltTopLevelsHash
== NULL
)
1861 xmlMutexLock(xsltExtMutex
);
1863 xmlHashUpdateEntry2(xsltTopLevelsHash
, name
, URI
,
1864 XML_CAST_FPTR(function
), NULL
);
1866 xmlMutexUnlock(xsltExtMutex
);
1872 * xsltExtModuleTopLevelLookup:
1873 * @name: the top-level element name
1874 * @URI: the top-level element namespace URI
1876 * Looks up an extension module top-level element
1878 * Returns the callback function if found, NULL otherwise.
1880 xsltTopLevelFunction
1881 xsltExtModuleTopLevelLookup(const xmlChar
* name
, const xmlChar
* URI
)
1883 xsltTopLevelFunction ret
;
1885 if ((xsltTopLevelsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1888 xmlMutexLock(xsltExtMutex
);
1890 XML_CAST_FPTR(ret
) = xmlHashLookup2(xsltTopLevelsHash
, name
, URI
);
1892 xmlMutexUnlock(xsltExtMutex
);
1894 /* if lookup fails, attempt a dynamic load on supported platforms */
1896 if (!xsltExtModuleRegisterDynamic(URI
)) {
1897 xmlMutexLock(xsltExtMutex
);
1899 XML_CAST_FPTR(ret
) = xmlHashLookup2(xsltTopLevelsHash
, name
, URI
);
1901 xmlMutexUnlock(xsltExtMutex
);
1909 * xsltUnregisterExtModuleTopLevel:
1910 * @name: the top-level element name
1911 * @URI: the top-level element namespace URI
1913 * Unregisters an extension module top-level element
1915 * Returns 0 if successful, -1 in case of error.
1918 xsltUnregisterExtModuleTopLevel(const xmlChar
* name
, const xmlChar
* URI
)
1922 if ((xsltTopLevelsHash
== NULL
) || (name
== NULL
) || (URI
== NULL
))
1925 xmlMutexLock(xsltExtMutex
);
1927 ret
= xmlHashRemoveEntry2(xsltTopLevelsHash
, name
, URI
, NULL
);
1929 xmlMutexUnlock(xsltExtMutex
);
1935 * xsltUnregisterAllExtModuleTopLevel:
1937 * Unregisters all extension module function
1940 xsltUnregisterAllExtModuleTopLevel(void)
1942 xmlMutexLock(xsltExtMutex
);
1944 xmlHashFree(xsltTopLevelsHash
, NULL
);
1945 xsltTopLevelsHash
= NULL
;
1947 xmlMutexUnlock(xsltExtMutex
);
1952 * @style: pointer to a stylesheet
1953 * @URI: the namespace URI desired
1955 * looks up URI in extInfos of the stylesheet
1957 * returns a pointer to the hash table if found, else NULL
1960 xsltGetExtInfo(xsltStylesheetPtr style
, const xmlChar
* URI
)
1962 xsltExtDataPtr data
;
1965 * TODO: Why do we have a return type of xmlHashTablePtr?
1966 * Is the user-allocated data for extension modules expected
1967 * to be a xmlHashTablePtr only? Or is this intended for
1968 * the EXSLT module only?
1971 if (style
!= NULL
&& style
->extInfos
!= NULL
) {
1972 data
= xmlHashLookup(style
->extInfos
, URI
);
1973 if (data
!= NULL
&& data
->extData
!= NULL
)
1974 return data
->extData
;
1979 /************************************************************************
1981 * Test of the extension module API *
1983 ************************************************************************/
1985 static xmlChar
*testData
= NULL
;
1986 static xmlChar
*testStyleData
= NULL
;
1989 * xsltExtFunctionTest:
1990 * @ctxt: the XPath Parser context
1991 * @nargs: the number of arguments
1993 * function libxslt:test() for testing the extensions support.
1996 xsltExtFunctionTest(xmlXPathParserContextPtr ctxt
,
1997 int nargs ATTRIBUTE_UNUSED
)
1999 xsltTransformContextPtr tctxt
;
2002 tctxt
= xsltXPathGetTransformContext(ctxt
);
2004 if (testData
== NULL
) {
2005 xsltGenericDebug(xsltGenericDebugContext
,
2006 "xsltExtFunctionTest: not initialized,"
2007 " calling xsltGetExtData\n");
2008 data
= xsltGetExtData(tctxt
, (const xmlChar
*) XSLT_DEFAULT_URL
);
2010 xsltTransformError(tctxt
, NULL
, NULL
,
2011 "xsltExtElementTest: not initialized\n");
2015 if (tctxt
== NULL
) {
2016 xsltTransformError(xsltXPathGetTransformContext(ctxt
), NULL
, NULL
,
2017 "xsltExtFunctionTest: failed to get the transformation context\n");
2021 data
= xsltGetExtData(tctxt
, (const xmlChar
*) XSLT_DEFAULT_URL
);
2023 xsltTransformError(xsltXPathGetTransformContext(ctxt
), NULL
, NULL
,
2024 "xsltExtFunctionTest: failed to get module data\n");
2027 if (data
!= testData
) {
2028 xsltTransformError(xsltXPathGetTransformContext(ctxt
), NULL
, NULL
,
2029 "xsltExtFunctionTest: got wrong module data\n");
2032 #ifdef WITH_XSLT_DEBUG_FUNCTION
2033 xsltGenericDebug(xsltGenericDebugContext
,
2034 "libxslt:test() called with %d args\n", nargs
);
2039 * xsltExtElementPreCompTest:
2040 * @style: the stylesheet
2041 * @inst: the instruction in the stylesheet
2043 * Process a libxslt:test node
2045 static xsltElemPreCompPtr
2046 xsltExtElementPreCompTest(xsltStylesheetPtr style
, xmlNodePtr inst
,
2047 xsltTransformFunction function
)
2049 xsltElemPreCompPtr ret
;
2051 if (style
== NULL
) {
2052 xsltTransformError(NULL
, NULL
, inst
,
2053 "xsltExtElementTest: no transformation context\n");
2056 if (testStyleData
== NULL
) {
2057 xsltGenericDebug(xsltGenericDebugContext
,
2058 "xsltExtElementPreCompTest: not initialized,"
2059 " calling xsltStyleGetExtData\n");
2060 xsltStyleGetExtData(style
, (const xmlChar
*) XSLT_DEFAULT_URL
);
2061 if (testStyleData
== NULL
) {
2062 xsltTransformError(NULL
, style
, inst
,
2063 "xsltExtElementPreCompTest: not initialized\n");
2070 xsltTransformError(NULL
, style
, inst
,
2071 "xsltExtElementPreCompTest: no instruction\n");
2076 ret
= xsltNewElemPreComp(style
, inst
, function
);
2081 * xsltExtElementTest:
2082 * @ctxt: an XSLT processing context
2083 * @node: The current node
2084 * @inst: the instruction in the stylesheet
2085 * @comp: precomputed information
2087 * Process a libxslt:test node
2090 xsltExtElementTest(xsltTransformContextPtr ctxt
, xmlNodePtr node
,
2092 xsltElemPreCompPtr comp ATTRIBUTE_UNUSED
)
2094 xmlNodePtr commentNode
;
2096 if (testData
== NULL
) {
2097 xsltGenericDebug(xsltGenericDebugContext
,
2098 "xsltExtElementTest: not initialized,"
2099 " calling xsltGetExtData\n");
2100 xsltGetExtData(ctxt
, (const xmlChar
*) XSLT_DEFAULT_URL
);
2101 if (testData
== NULL
) {
2102 xsltTransformError(ctxt
, NULL
, inst
,
2103 "xsltExtElementTest: not initialized\n");
2108 xsltTransformError(ctxt
, NULL
, inst
,
2109 "xsltExtElementTest: no transformation context\n");
2113 xsltTransformError(ctxt
, NULL
, inst
,
2114 "xsltExtElementTest: no current node\n");
2118 xsltTransformError(ctxt
, NULL
, inst
,
2119 "xsltExtElementTest: no instruction\n");
2122 if (ctxt
->insert
== NULL
) {
2123 xsltTransformError(ctxt
, NULL
, inst
,
2124 "xsltExtElementTest: no insertion point\n");
2127 commentNode
= xmlNewComment((const xmlChar
*)
2128 "libxslt:test element test worked");
2129 xmlAddChild(ctxt
->insert
, commentNode
);
2134 * @ctxt: an XSLT transformation context
2135 * @URI: the namespace URI for the extension
2137 * A function called at initialization time of an XSLT extension module
2139 * Returns a pointer to the module specific data for this transformation
2142 xsltExtInitTest(xsltTransformContextPtr ctxt
, const xmlChar
* URI
)
2144 if (testStyleData
== NULL
) {
2145 xsltGenericDebug(xsltGenericErrorContext
,
2146 "xsltExtInitTest: not initialized,"
2147 " calling xsltStyleGetExtData\n");
2148 testStyleData
= xsltStyleGetExtData(ctxt
->style
, URI
);
2149 if (testStyleData
== NULL
) {
2150 xsltTransformError(ctxt
, NULL
, NULL
,
2151 "xsltExtInitTest: not initialized\n");
2155 if (testData
!= NULL
) {
2156 xsltTransformError(ctxt
, NULL
, NULL
,
2157 "xsltExtInitTest: already initialized\n");
2160 testData
= (void *) "test data";
2161 xsltGenericDebug(xsltGenericDebugContext
,
2162 "Registered test module : %s\n", URI
);
2168 * xsltExtShutdownTest:
2169 * @ctxt: an XSLT transformation context
2170 * @URI: the namespace URI for the extension
2171 * @data: the data associated to this module
2173 * A function called at shutdown time of an XSLT extension module
2176 xsltExtShutdownTest(xsltTransformContextPtr ctxt
,
2177 const xmlChar
* URI
, void *data
)
2179 if (testData
== NULL
) {
2180 xsltTransformError(ctxt
, NULL
, NULL
,
2181 "xsltExtShutdownTest: not initialized\n");
2184 if (data
!= testData
) {
2185 xsltTransformError(ctxt
, NULL
, NULL
,
2186 "xsltExtShutdownTest: wrong data\n");
2189 xsltGenericDebug(xsltGenericDebugContext
,
2190 "Unregistered test module : %s\n", URI
);
2194 * xsltExtStyleInitTest:
2195 * @style: an XSLT stylesheet
2196 * @URI: the namespace URI for the extension
2198 * A function called at initialization time of an XSLT extension module
2200 * Returns a pointer to the module specific data for this transformation
2203 xsltExtStyleInitTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED
,
2204 const xmlChar
* URI
)
2206 if (testStyleData
!= NULL
) {
2207 xsltTransformError(NULL
, NULL
, NULL
,
2208 "xsltExtInitTest: already initialized\n");
2211 testStyleData
= (void *) "test data";
2212 xsltGenericDebug(xsltGenericDebugContext
,
2213 "Registered test module : %s\n", URI
);
2214 return (testStyleData
);
2219 * xsltExtStyleShutdownTest:
2220 * @style: an XSLT stylesheet
2221 * @URI: the namespace URI for the extension
2222 * @data: the data associated to this module
2224 * A function called at shutdown time of an XSLT extension module
2227 xsltExtStyleShutdownTest(xsltStylesheetPtr style ATTRIBUTE_UNUSED
,
2228 const xmlChar
* URI
, void *data
)
2230 if (testStyleData
== NULL
) {
2231 xsltGenericError(xsltGenericErrorContext
,
2232 "xsltExtShutdownTest: not initialized\n");
2235 if (data
!= testStyleData
) {
2236 xsltTransformError(NULL
, NULL
, NULL
,
2237 "xsltExtShutdownTest: wrong data\n");
2239 testStyleData
= NULL
;
2240 xsltGenericDebug(xsltGenericDebugContext
,
2241 "Unregistered test module : %s\n", URI
);
2245 * xsltRegisterTestModule:
2247 * Registers the test module
2250 xsltRegisterTestModule(void)
2253 xsltRegisterExtModuleFull((const xmlChar
*) XSLT_DEFAULT_URL
,
2254 xsltExtInitTest
, xsltExtShutdownTest
,
2255 xsltExtStyleInitTest
,
2256 xsltExtStyleShutdownTest
);
2257 xsltRegisterExtModuleFunction((const xmlChar
*) "test",
2258 (const xmlChar
*) XSLT_DEFAULT_URL
,
2259 xsltExtFunctionTest
);
2260 xsltRegisterExtModuleElement((const xmlChar
*) "test",
2261 (const xmlChar
*) XSLT_DEFAULT_URL
,
2262 xsltExtElementPreCompTest
,
2263 xsltExtElementTest
);
2267 xsltHashScannerModuleFree(void *payload ATTRIBUTE_UNUSED
,
2268 void *data ATTRIBUTE_UNUSED
,
2269 const xmlChar
*name ATTRIBUTE_UNUSED
)
2272 xmlModuleClose(payload
);
2279 * Initialize the global variables for extensions
2282 xsltInitGlobals(void)
2284 if (xsltExtMutex
== NULL
) {
2285 xsltExtMutex
= xmlNewMutex();
2290 * xsltCleanupGlobals:
2292 * Unregister all global variables set up by the XSLT library
2295 xsltCleanupGlobals(void)
2297 xsltUnregisterAllExtModules();
2298 xsltUnregisterAllExtModuleFunction();
2299 xsltUnregisterAllExtModuleElement();
2300 xsltUnregisterAllExtModuleTopLevel();
2302 xmlMutexLock(xsltExtMutex
);
2303 /* cleanup dynamic module hash */
2304 if (NULL
!= xsltModuleHash
) {
2305 xmlHashScan(xsltModuleHash
, xsltHashScannerModuleFree
, 0);
2306 xmlHashFree(xsltModuleHash
, NULL
);
2307 xsltModuleHash
= NULL
;
2309 xmlMutexUnlock(xsltExtMutex
);
2311 xmlFreeMutex(xsltExtMutex
);
2312 xsltExtMutex
= NULL
;
2318 xsltDebugDumpExtensionsCallback(void *function ATTRIBUTE_UNUSED
,
2319 void *data
, const xmlChar
* name
,
2320 const xmlChar
* URI
,
2321 const xmlChar
* not_used ATTRIBUTE_UNUSED
)
2323 FILE *output
= (FILE *) data
;
2326 fprintf(output
, "{%s}%s\n", URI
, name
);
2330 xsltDebugDumpExtModulesCallback(void *function ATTRIBUTE_UNUSED
,
2331 void *data
, const xmlChar
* URI
,
2332 const xmlChar
* not_used ATTRIBUTE_UNUSED
,
2333 const xmlChar
* not_used2 ATTRIBUTE_UNUSED
)
2335 FILE *output
= (FILE *) data
;
2338 fprintf(output
, "%s\n", URI
);
2342 * xsltDebugDumpExtensions:
2343 * @output: the FILE * for the output, if NULL stdout is used
2345 * Dumps a list of the registered XSLT extension functions and elements
2348 xsltDebugDumpExtensions(FILE * output
)
2353 "Registered XSLT Extensions\n--------------------------\n");
2354 if (!xsltFunctionsHash
)
2355 fprintf(output
, "No registered extension functions\n");
2357 fprintf(output
, "Registered Extension Functions:\n");
2358 xmlMutexLock(xsltExtMutex
);
2359 xmlHashScanFull(xsltFunctionsHash
, xsltDebugDumpExtensionsCallback
,
2361 xmlMutexUnlock(xsltExtMutex
);
2363 if (!xsltElementsHash
)
2364 fprintf(output
, "\nNo registered extension elements\n");
2366 fprintf(output
, "\nRegistered Extension Elements:\n");
2367 xmlMutexLock(xsltExtMutex
);
2368 xmlHashScanFull(xsltElementsHash
, xsltDebugDumpExtensionsCallback
,
2370 xmlMutexUnlock(xsltExtMutex
);
2372 if (!xsltExtensionsHash
)
2373 fprintf(output
, "\nNo registered extension modules\n");
2375 fprintf(output
, "\nRegistered Extension Modules:\n");
2376 xmlMutexLock(xsltExtMutex
);
2377 xmlHashScanFull(xsltExtensionsHash
, xsltDebugDumpExtModulesCallback
,
2379 xmlMutexUnlock(xsltExtMutex
);