1
0
mirror of https://gitlab.gnome.org/GNOME/libxslt synced 2025-08-05 23:35:48 +03:00

new extension framework. Added stylesheet module data, top-level and

* libxslt/extensions.[ch] libxslt/functions.[ch] libxslt/preproc.c
	  libxslt/transform.[ch] libxslt/variables.c libxslt/xslt.c
	  libxslt/xsltInternals.h: new extension framework.
	  Added stylesheet module data, top-level and extension elements
	  precomputing, global registration of top-level elements and
	  extension elements and functions.
	  Extensions are no longer initialized from extension-element-prefixes
	  declarations but when modules need the data.
	  init/shutdown functions registered with xsltRegisterExtModule{,Full}
	  only allocate and free module data, they shouldn't register the
	  elements and functions any more.
	* libxslt/xsltutils.c: fixed a bug in xsltPrintErrorContext when
	  @node wasn't NULL.
	* libxslt/xslt.c: fixed xsltPrecomputeStylesheetTop which allowed
	  non-XSLT top-level elements before any xsl:import element.
	* libexslt/common.c libexslt/functions.c libexslt/math.c
	  libexslt/sets.c: adapted to use the new extension framework.
	* libxslt/functions.c libxslt/extensions[ch] xsltproc/xsltproc.c:
	  moved the test module from functions.c to extensions.[ch],
	  modified it to use the new extension framework. Updated xsltproc
	  to register the test module.
This commit is contained in:
Thomas Broyer
2001-07-26 17:27:38 +00:00
parent 93a9ef80f2
commit 3a16b45ef1
17 changed files with 1280 additions and 363 deletions

View File

@@ -1,3 +1,27 @@
Thu Jul 26 19:05:48 CEST 2001 Thomas Broyer <tbroyer@ltgt.net>
* libxslt/extensions.[ch] libxslt/functions.[ch] libxslt/preproc.c
libxslt/transform.[ch] libxslt/variables.c libxslt/xslt.c
libxslt/xsltInternals.h: new extension framework.
Added stylesheet module data, top-level and extension elements
precomputing, global registration of top-level elements and
extension elements and functions.
Extensions are no longer initialized from extension-element-prefixes
declarations but when modules need the data.
init/shutdown functions registered with xsltRegisterExtModule{,Full}
only allocate and free module data, they shouldn't register the
elements and functions any more.
* libxslt/xsltutils.c: fixed a bug in xsltPrintErrorContext when
@node wasn't NULL.
* libxslt/xslt.c: fixed xsltPrecomputeStylesheetTop which allowed
non-XSLT top-level elements before any xsl:import element.
* libexslt/common.c libexslt/functions.c libexslt/math.c
libexslt/sets.c: adapted to use the new extension framework.
* libxslt/functions.c libxslt/extensions[ch] xsltproc/xsltproc.c:
moved the test module from functions.c to extensions.[ch],
modified it to use the new extension framework. Updated xsltproc
to register the test module.
Thu Jul 26 10:20:19 EDT 2001 Daniel Veillard <daniel@veillard.com> Thu Jul 26 10:20:19 EDT 2001 Daniel Veillard <daniel@veillard.com>
* libxslt/pattern.c: fixed an ugly problem with namespaces * libxslt/pattern.c: fixed an ugly problem with namespaces

View File

@@ -52,19 +52,6 @@ exsltObjectTypeFunction (xmlXPathParserContextPtr ctxt, int nargs) {
} }
static void *
exsltCommonInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
xsltRegisterExtFunction (ctxt, (const xmlChar *) "node-set",
URI, xsltFunctionNodeSet);
xsltRegisterExtFunction (ctxt, (const xmlChar *) "object-type",
URI, exsltObjectTypeFunction);
xsltRegisterExtElement (ctxt, (const xmlChar *) "document",
URI, xsltDocumentElem);
return(NULL);
}
/** /**
* exsltCommonRegister: * exsltCommonRegister:
* *
@@ -73,6 +60,13 @@ exsltCommonInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
void void
exsltCommonRegister (void) { exsltCommonRegister (void) {
xsltRegisterExtModule (EXSLT_COMMON_NAMESPACE, xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
exsltCommonInit, NULL); EXSLT_COMMON_NAMESPACE,
xsltFunctionNodeSet);
xsltRegisterExtModuleFunction((const xmlChar *) "object-type",
EXSLT_COMMON_NAMESPACE,
exsltObjectTypeFunction);
xsltRegisterExtModuleElement((const xmlChar *) "document",
EXSLT_COMMON_NAMESPACE,
NULL, xsltDocumentElem);
} }

View File

@@ -23,12 +23,32 @@ struct _exsltFuncData {
int error; int error;
}; };
static void exsltFuncFunctionElem (xsltTransformContextPtr ctxt,
xmlNodePtr node, xmlNodePtr inst, static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt,
xsltStylePreCompPtr comp); int nargs);
static void exsltFuncResultElem (xsltTransformContextPtr ctxt,
xmlNodePtr node, xmlNodePtr inst, /**
xsltStylePreCompPtr comp); * exsltFuncRegisterFunc:
* @func: the #exsltFuncFunctionData for the function
* @ctxt: an XSLT transformation context
* @URI: the function namespace URI
* @name: the function name
*
* Registers a function declared by a func:function element
*/
static void
exsltFuncRegisterFunc (exsltFuncFunctionData *data,
xsltTransformContextPtr ctxt,
const xmlChar *URI, const xmlChar *name) {
if ((data == NULL) || (ctxt == NULL) || (URI == NULL) || (name == NULL))
return;
xsltGenericDebug(xsltGenericDebugContext,
"exsltFuncRegisterFunc: register {%s}%s\n",
URI, name);
xsltRegisterExtFunction(ctxt, name, URI,
exsltFuncFunctionFunction);
}
/** /**
* exsltFuncInit: * exsltFuncInit:
@@ -41,6 +61,7 @@ static void exsltFuncResultElem (xsltTransformContextPtr ctxt,
*/ */
static exsltFuncData * static exsltFuncData *
exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) { exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
xmlHashTablePtr hash;
exsltFuncData *ret; exsltFuncData *ret;
ret = (exsltFuncData *) xmlMalloc (sizeof(exsltFuncData)); ret = (exsltFuncData *) xmlMalloc (sizeof(exsltFuncData));
@@ -51,15 +72,13 @@ exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
} }
memset(ret, 0, sizeof(exsltFuncData)); memset(ret, 0, sizeof(exsltFuncData));
ret->funcs = xmlHashCreate(1);
ret->result = NULL; ret->result = NULL;
ret->error = 0; ret->error = 0;
xsltRegisterExtElement (ctxt, (const xmlChar *) "function", hash = (xmlHashTablePtr) xsltStyleGetExtData(ctxt->style, URI);
URI, exsltFuncFunctionElem); xmlHashScanFull(hash, (xmlHashScannerFull) exsltFuncRegisterFunc, ctxt);
xsltRegisterExtElement (ctxt, (const xmlChar *) "result",
URI, exsltFuncResultElem);
ret->funcs = hash;
return(ret); return(ret);
} }
@@ -67,7 +86,7 @@ exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
/** /**
* exsltFuncShutdown: * exsltFuncShutdown:
* @ctxt: an XSLT transformation context * @ctxt: an XSLT transformation context
* @URI: the namespace URI fir the extension * @URI: the namespace URI for the extension
* @data: the module data to free up * @data: the module data to free up
* *
* Shutdown the EXSLT - Functions module * Shutdown the EXSLT - Functions module
@@ -76,23 +95,39 @@ static void
exsltFuncShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, exsltFuncShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
const xmlChar *URI ATTRIBUTE_UNUSED, const xmlChar *URI ATTRIBUTE_UNUSED,
exsltFuncData *data) { exsltFuncData *data) {
if (data->funcs != NULL)
xmlHashFree(data->funcs, (xmlHashDeallocator) xmlFree);
if (data->result != NULL) if (data->result != NULL)
xmlXPathFreeObject(data->result); xmlXPathFreeObject(data->result);
xmlFree(data); xmlFree(data);
} }
/** /**
* exsltFuncRegister: * exsltFuncStyleInit:
* @style: an XSLT stylesheet
* @URI: the namespace URI for the extension
* *
* Registers the EXSLT - Functions module * Allocates the styleshet data for EXSLT - Function
*
* Returns the allocated data
*/ */
void static xmlHashTablePtr
exsltFuncRegister (void) { exsltFuncStyleInit (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
xsltRegisterExtModule (EXSLT_FUNCTIONS_NAMESPACE, const xmlChar *URI ATTRIBUTE_UNUSED) {
(xsltExtInitFunction) exsltFuncInit, return xmlHashCreate(1);
(xsltExtShutdownFunction) exsltFuncShutdown); }
/**
* exsltFuncStyleShutdown:
* @style: an XSLT stylesheet
* @URI: the namespace URI for the extension
* @data: the stylesheet data to free up
*
* Shutdown the EXSLT - Function module
*/
static void
exsltFuncStyleShutdown (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
const xmlChar *URI ATTRIBUTE_UNUSED,
xmlHashTablePtr data) {
xmlHashFree(data, NULL);
} }
/** /**
@@ -112,6 +147,7 @@ exsltFuncNewFunctionData (void) {
"exsltFuncNewFunctionData: not enough memory\n"); "exsltFuncNewFunctionData: not enough memory\n");
return (NULL); return (NULL);
} }
memset(ret, 0, sizeof(exsltFuncFunctionData));
ret->nargs = 0; ret->nargs = 0;
ret->content = NULL; ret->content = NULL;
@@ -124,11 +160,12 @@ exsltFuncNewFunctionData (void) {
* @ctxt: an XPath parser context * @ctxt: an XPath parser context
* @nargs: the number of arguments * @nargs: the number of arguments
* *
* Evaluates the func:function element defining the called function. * Evaluates the func:function element that defines the called function.
*/ */
static void static void
exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) { exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr obj, oldResult, ret; xmlXPathObjectPtr obj, oldResult, ret;
xmlHashTablePtr funcs;
exsltFuncData *data; exsltFuncData *data;
exsltFuncFunctionData *func; exsltFuncFunctionData *func;
xmlNodePtr paramNode, oldInsert, fake; xmlNodePtr paramNode, oldInsert, fake;
@@ -215,6 +252,7 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
* the generation of result nodes. * the generation of result nodes.
*/ */
if (fake->children != NULL) { if (fake->children != NULL) {
xmlDebugDumpNode (stderr, fake, 1);
xsltGenericError(xsltGenericErrorContext, xsltGenericError(xsltGenericErrorContext,
"{%s}%s: cannot write to result tree while " "{%s}%s: cannot write to result tree while "
"executing a function\n", "executing a function\n",
@@ -224,16 +262,15 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
valuePush(ctxt, ret); valuePush(ctxt, ret);
} }
static void static void
exsltFuncFunctionElem (xsltTransformContextPtr ctxt, xmlNodePtr node, exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) {
xmlNodePtr inst, xsltStylePreCompPtr comp) {
xmlChar *name, *prefix; xmlChar *name, *prefix;
xmlNsPtr ns; xmlNsPtr ns;
exsltFuncData *data; xmlHashTablePtr data;
exsltFuncFunctionData *func; exsltFuncFunctionData *func;
xsltStylePreCompPtr param_comp;
if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL)) if ((style == NULL) || (inst == NULL))
return; return;
{ {
@@ -267,27 +304,36 @@ exsltFuncFunctionElem (xsltTransformContextPtr ctxt, xmlNodePtr node,
*/ */
func = exsltFuncNewFunctionData(); func = exsltFuncNewFunctionData();
func->content = inst->children; func->content = inst->children;
param_comp = (xsltStylePreCompPtr) func->content->_private; while (IS_XSLT_ELEM(func->content) &&
while ((param_comp != NULL) && (param_comp->type == XSLT_FUNC_PARAM)) { IS_XSLT_NAME(func->content, "param")) {
func->content = func->content->next; func->content = func->content->next;
func->nargs++; func->nargs++;
param_comp = (xsltStylePreCompPtr) func->content->_private;
} }
xsltParseTemplateContent(style, inst);
/* /*
* Register the function data such that it can be retrieved * Register the function data such that it can be retrieved
* by exslFuncFunctionFunction * by exslFuncFunctionFunction
*/ */
data = (exsltFuncData *) xsltGetExtData (ctxt, EXSLT_FUNCTIONS_NAMESPACE); data = (xmlHashTablePtr) xsltStyleGetExtData (style,
xmlHashAddEntry2 (data->funcs, ns->href, name, func); EXSLT_FUNCTIONS_NAMESPACE);
if (data == NULL) {
/* xsltGenericError(xsltGenericErrorContext,
* Register the function such that it is available for use in XPath "exsltFuncFunctionComp: no stylesheet data\n");
* expressions. xmlFree(name);
*/ return;
xsltRegisterExtFunction (ctxt, name, ns->href, }
exsltFuncFunctionFunction);
if (xmlHashAddEntry2 (data, ns->href, name, func) < 0) {
xsltGenericError(xsltGenericErrorContext,
"Failed to register function {%s}%s\n",
ns->href, name);
} else {
xsltGenericDebug(xsltGenericDebugContext,
"exsltFuncFunctionComp: register {%s}%s\n",
ns->href, name);
}
xmlFree(name); xmlFree(name);
} }
@@ -416,3 +462,25 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt, xmlNodePtr node,
} }
data->result = ret; data->result = ret;
} }
/**
* exsltFuncRegister:
*
* Registers the EXSLT - Functions module
*/
void
exsltFuncRegister (void) {
xsltRegisterExtModuleFull (EXSLT_FUNCTIONS_NAMESPACE,
(xsltExtInitFunction) exsltFuncInit,
(xsltExtShutdownFunction) exsltFuncShutdown,
(xsltStyleExtInitFunction) exsltFuncStyleInit,
(xsltStyleExtShutdownFunction) exsltFuncStyleShutdown);
xsltRegisterExtModuleTopLevel ((const xmlChar *) "function",
EXSLT_FUNCTIONS_NAMESPACE,
exsltFuncFunctionComp);
xsltRegisterExtModuleElement ((const xmlChar *) "result",
EXSLT_FUNCTIONS_NAMESPACE,
NULL,
exsltFuncResultElem);
}

View File

@@ -271,19 +271,6 @@ exsltMathLowestFunction (xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathReturnNodeSet(ctxt, ret); xmlXPathReturnNodeSet(ctxt, ret);
} }
static void *
exsltMathInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
xsltRegisterExtFunction (ctxt, (const xmlChar *) "min",
URI, exsltMathMinFunction);
xsltRegisterExtFunction (ctxt, (const xmlChar *) "max",
URI, exsltMathMaxFunction);
xsltRegisterExtFunction (ctxt, (const xmlChar *) "highest",
URI, exsltMathHighestFunction);
xsltRegisterExtFunction (ctxt, (const xmlChar *) "lowest",
URI, exsltMathLowestFunction);
return(NULL);
}
/** /**
* exsltMathRegister: * exsltMathRegister:
* *
@@ -292,5 +279,16 @@ exsltMathInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
void void
exsltMathRegister (void) { exsltMathRegister (void) {
xsltRegisterExtModule (EXSLT_MATH_NAMESPACE, exsltMathInit, NULL); xsltRegisterExtModuleFunction ((const xmlChar *) "min",
EXSLT_MATH_NAMESPACE,
exsltMathMinFunction);
xsltRegisterExtModuleFunction ((const xmlChar *) "max",
EXSLT_MATH_NAMESPACE,
exsltMathMaxFunction);
xsltRegisterExtModuleFunction ((const xmlChar *) "highest",
EXSLT_MATH_NAMESPACE,
exsltMathHighestFunction);
xsltRegisterExtModuleFunction ((const xmlChar *) "lowest",
EXSLT_MATH_NAMESPACE,
exsltMathLowestFunction);
} }

View File

@@ -221,24 +221,6 @@ exsltSetsTrailingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathReturnNodeSet(ctxt, ret); xmlXPathReturnNodeSet(ctxt, ret);
} }
static void *
exsltSetsInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
xsltRegisterExtFunction (ctxt, (const xmlChar *) "difference",
URI, exsltSetsDifferenceFunction);
xsltRegisterExtFunction (ctxt, (const xmlChar *) "intersection",
URI, exsltSetsIntersectionFunction);
xsltRegisterExtFunction (ctxt, (const xmlChar *) "distinct",
URI, exsltSetsDistinctFunction);
xsltRegisterExtFunction (ctxt, (const xmlChar *) "has-same-nodes",
URI, exsltSetsHasSameNodesFunction);
xsltRegisterExtFunction (ctxt, (const xmlChar *) "leading",
URI, exsltSetsLeadingFunction);
xsltRegisterExtFunction (ctxt, (const xmlChar *) "trailing",
URI, exsltSetsTrailingFunction);
return(NULL);
}
/** /**
* exsltCommonRegister: * exsltCommonRegister:
* *
@@ -247,5 +229,22 @@ exsltSetsInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
void void
exsltSetsRegister (void) { exsltSetsRegister (void) {
xsltRegisterExtModule (EXSLT_SETS_NAMESPACE, exsltSetsInit, NULL); xsltRegisterExtModuleFunction ((const xmlChar *) "difference",
EXSLT_SETS_NAMESPACE,
exsltSetsDifferenceFunction);
xsltRegisterExtModuleFunction ((const xmlChar *) "intersection",
EXSLT_SETS_NAMESPACE,
exsltSetsIntersectionFunction);
xsltRegisterExtModuleFunction ((const xmlChar *) "distinct",
EXSLT_SETS_NAMESPACE,
exsltSetsDistinctFunction);
xsltRegisterExtModuleFunction ((const xmlChar *) "has-same-nodes",
EXSLT_SETS_NAMESPACE,
exsltSetsHasSameNodesFunction);
xsltRegisterExtModuleFunction ((const xmlChar *) "leading",
EXSLT_SETS_NAMESPACE,
exsltSetsLeadingFunction);
xsltRegisterExtModuleFunction ((const xmlChar *) "trailing",
EXSLT_SETS_NAMESPACE,
exsltSetsTrailingFunction);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -20,6 +20,30 @@ extern "C" {
* Extension Modules API * Extension Modules API
*/ */
/**
* xsltStyleExtInitFunction:
* @ctxt: an XSLT stylesheet
* @URI: the namespace URI for the extension
*
* A function called at initialization time of an XSLT extension module
*
* Returns a pointer to the module specific data for this transformation
*/
typedef void * (*xsltStyleExtInitFunction) (xsltStylesheetPtr style,
const xmlChar *URI);
/**
* xsltStyleExtShutdownFunction:
* @ctxt: an XSLT stylesheet
* @URI: the namespace URI for the extension
* @data: the data associated to this module
*
* A function called at shutdown time of an XSLT extension module
*/
typedef void (*xsltStyleExtShutdownFunction) (xsltStylesheetPtr style,
const xmlChar *URI,
void *data);
/** /**
* xsltExtInitFunction: * xsltExtInitFunction:
* @ctxt: an XSLT transformation context * @ctxt: an XSLT transformation context
@@ -47,6 +71,12 @@ typedef void (*xsltExtShutdownFunction) (xsltTransformContextPtr ctxt,
int xsltRegisterExtModule (const xmlChar *URI, int xsltRegisterExtModule (const xmlChar *URI,
xsltExtInitFunction initFunc, xsltExtInitFunction initFunc,
xsltExtShutdownFunction shutdownFunc); xsltExtShutdownFunction shutdownFunc);
int xsltRegisterExtModuleFull
(const xmlChar * URI,
xsltExtInitFunction initFunc,
xsltExtShutdownFunction shutdownFunc,
xsltStyleExtInitFunction styleInitFunc,
xsltStyleExtShutdownFunction styleShutdownFunc);
int xsltUnregisterExtModule (const xmlChar * URI); int xsltUnregisterExtModule (const xmlChar * URI);
@@ -55,16 +85,76 @@ void xsltUnregisterAllExtModules(void);
void * xsltGetExtData (xsltTransformContextPtr ctxt, void * xsltGetExtData (xsltTransformContextPtr ctxt,
const xmlChar *URI); const xmlChar *URI);
void * xsltStyleGetExtData (xsltStylesheetPtr style,
const xmlChar *URI);
void xsltShutdownCtxtExts (xsltTransformContextPtr ctxt); void xsltShutdownCtxtExts (xsltTransformContextPtr ctxt);
void xsltShutdownExts (xsltStylesheetPtr style);
xsltTransformContextPtr xsltTransformContextPtr
xsltXPathGetTransformContext xsltXPathGetTransformContext
(xmlXPathParserContextPtr ctxt); (xmlXPathParserContextPtr ctxt);
/*
* extension functions
*/
int xsltRegisterExtModuleFunction (const xmlChar *name,
const xmlChar *URI,
xmlXPathFunction function);
xmlXPathFunction
xsltExtFunctionLookup (xsltTransformContextPtr ctxt,
const xmlChar *name,
const xmlChar *URI);
xmlXPathFunction
xsltExtModuleFunctionLookup (const xmlChar *name,
const xmlChar *URI);
int xsltUnregisterExtModuleFunction (const xmlChar *name,
const xmlChar *URI);
/*
* extension elements
*/
typedef void
(*xsltPreComputeFunction) (xsltStylesheetPtr ctxt,
xmlNodePtr inst);
int xsltRegisterExtModuleElement (const xmlChar *name,
const xmlChar *URI,
xsltPreComputeFunction precomp,
xsltTransformFunction transform);
xsltTransformFunction
xsltExtElementLookup (xsltTransformContextPtr ctxt,
const xmlChar *name,
const xmlChar *URI);
xsltTransformFunction
xsltExtModuleElementLookup (const xmlChar *name,
const xmlChar *URI);
xsltPreComputeFunction
xsltExtModuleElementPreComputeLookup
(const xmlChar *name,
const xmlChar *URI);
int xsltUnregisterExtModuleElement (const xmlChar *name,
const xmlChar *URI);
/*
* top-level elements
*/
int xsltRegisterExtModuleTopLevel (const xmlChar *name,
const xmlChar *URI,
xsltPreComputeFunction function);
xsltPreComputeFunction
xsltExtModuleTopLevelLookup (const xmlChar *name,
const xmlChar *URI);
int xsltUnregisterExtModuleTopLevel (const xmlChar *name,
const xmlChar *URI);
/* These 2 functions are deprecated for use within modules */
int xsltRegisterExtFunction (xsltTransformContextPtr ctxt, int xsltRegisterExtFunction (xsltTransformContextPtr ctxt,
const xmlChar *name, const xmlChar *name,
const xmlChar *URI, const xmlChar *URI,
xmlXPathEvalFunc function); xmlXPathFunction function);
int xsltRegisterExtElement (xsltTransformContextPtr ctxt, int xsltRegisterExtElement (xsltTransformContextPtr ctxt,
const xmlChar *name, const xmlChar *name,
const xmlChar *URI, const xmlChar *URI,
@@ -85,6 +175,11 @@ void xsltFreeCtxtExts (xsltTransformContextPtr ctxt);
void xsltFreeExts (xsltStylesheetPtr style); void xsltFreeExts (xsltStylesheetPtr style);
/**
* Test module http://xmlsoft.org/XSLT/
*/
void xsltRegisterTestModule (void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -51,6 +51,41 @@
*/ */
#define DOCBOOK_XSL_HACK #define DOCBOOK_XSL_HACK
/**
* xsltXPathFunctionLookup:
* @ctxt: a void * but the XSLT transformation context actually
* @name: the function name
* @ns_uri: the function namespace URI
*
* This is the entry point when a function is needed by the XPath
* interpretor.
*
* Returns the callback function or NULL if not found
*/
xmlXPathFunction
xsltXPathFunctionLookup (void *ctxt ATTRIBUTE_UNUSED,
const xmlChar *name, const xmlChar *ns_uri) {
xmlXPathFunction ret;
if ((name == NULL) || (ns_uri == NULL))
return (NULL);
#ifdef WITH_XSLT_DEBUG_FUNCTION
xsltGenericDebug(xsltGenericDebugContext,
"Lookup function {%s}%s\n", ns_uri, name);
#endif
ret = xsltExtModuleFunctionLookup(name, ns_uri);
#ifdef WITH_XSLT_DEBUG_FUNCTION
if (ret != NULL)
xsltGenericDebug(xsltGenericDebugContext,
"found function %s\n", name);
#endif
return(ret);
}
/************************************************************************ /************************************************************************
* * * *
* Module interfaces * * Module interfaces *
@@ -625,7 +660,11 @@ xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
name = xmlSplitQName2(obj->stringval, &prefix); name = xmlSplitQName2(obj->stringval, &prefix);
if (name == NULL) { if (name == NULL) {
xmlNsPtr ns;
name = xmlStrdup(obj->stringval); name = xmlStrdup(obj->stringval);
ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL);
nsURI = xmlStrdup(ns->href);
} else { } else {
nsURI = xmlXPathNsLookup(ctxt->context, prefix); nsURI = xmlXPathNsLookup(ctxt->context, prefix);
if (nsURI == NULL) { if (nsURI == NULL) {
@@ -636,7 +675,7 @@ xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
} }
} }
if (xmlHashLookup2(tctxt->extElements, name, nsURI) != NULL) { if (xsltExtElementLookup(tctxt, name, nsURI) != NULL) {
valuePush(ctxt, xmlXPathNewBoolean(1)); valuePush(ctxt, xmlXPathNewBoolean(1));
} else { } else {
valuePush(ctxt, xmlXPathNewBoolean(0)); valuePush(ctxt, xmlXPathNewBoolean(0));
@@ -735,171 +774,6 @@ xsltCurrentFunction(xmlXPathParserContextPtr ctxt, int nargs){
} }
} }
/************************************************************************
* *
* Test of the extension module API *
* *
************************************************************************/
static xmlChar *testData = NULL;
/**
* xsltExtFunctionTest:
* @ctxt: the XPath Parser context
* @nargs: the number of arguments
*
* function libxslt:test() for testing the extensions support.
*/
static void
xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, int nargs)
{
xsltTransformContextPtr tctxt;
void *data;
if (testData == NULL) {
xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltExtFunctionTest: not initialized\n");
return;
}
tctxt = xsltXPathGetTransformContext(ctxt);
if (tctxt == NULL) {
xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltExtFunctionTest: failed to get the transformation context\n");
return;
}
data = xsltGetExtData(tctxt, (const xmlChar *) XSLT_DEFAULT_URL);
if (data == NULL) {
xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltExtFunctionTest: failed to get module data\n");
return;
}
if (data != testData) {
xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltExtFunctionTest: got wrong module data\n");
return;
}
#ifdef WITH_XSLT_DEBUG_FUNCTION
xsltGenericDebug(xsltGenericDebugContext,
"libxslt:test() called with %d args\n", nargs);
#endif
}
/**
* xsltExtElementTest:
* @ctxt: an XSLT processing context
* @node: The current node
* @inst: the instruction in the stylesheet
* @comp: precomputed informations
*
* Process a libxslt:test node
*/
static void
xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlNodePtr inst,
xsltStylePreCompPtr comp ATTRIBUTE_UNUSED)
{
xmlNodePtr comment;
if (testData == NULL) {
xsltPrintErrorContext(ctxt, NULL, inst);
xsltGenericError(xsltGenericErrorContext,
"xsltExtElementTest: not initialized\n");
return;
}
if (ctxt == NULL) {
xsltPrintErrorContext(ctxt, NULL, inst);
xsltGenericError(xsltGenericErrorContext,
"xsltExtElementTest: no transformation context\n");
return;
}
if (node == NULL) {
xsltPrintErrorContext(ctxt, NULL, inst);
xsltGenericError(xsltGenericErrorContext,
"xsltExtElementTest: no current node\n");
return;
}
if (inst == NULL) {
xsltPrintErrorContext(ctxt, NULL, inst);
xsltGenericError(xsltGenericErrorContext,
"xsltExtElementTest: no instruction\n");
return;
}
if (ctxt->insert == NULL) {
xsltPrintErrorContext(ctxt, NULL, inst);
xsltGenericError(xsltGenericErrorContext,
"xsltExtElementTest: no insertion point\n");
return;
}
comment =
xmlNewComment((const xmlChar *)
"libxslt:test element test worked");
xmlAddChild(ctxt->insert, comment);
}
/**
* xsltExtInitTest:
* @ctxt: an XSLT transformation context
* @URI: the namespace URI for the extension
*
* A function called at initialization time of an XSLT extension module
*
* Returns a pointer to the module specific data for this transformation
*/
static void *
xsltExtInitTest(xsltTransformContextPtr ctxt, const xmlChar * URI)
{
if (testData != NULL) {
xsltPrintErrorContext(ctxt, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltExtInitTest: already initialized\n");
return (NULL);
}
testData = (void *) "test data";
xsltRegisterExtFunction(ctxt, (const xmlChar *) "test",
(const xmlChar *) XSLT_DEFAULT_URL,
xsltExtFunctionTest);
xsltRegisterExtElement(ctxt, (const xmlChar *) "test",
(const xmlChar *) XSLT_DEFAULT_URL,
xsltExtElementTest);
xsltGenericDebug(xsltGenericDebugContext,
"Registered test module : %s\n", URI);
return (testData);
}
/**
* xsltExtShutdownTest:
* @ctxt: an XSLT transformation context
* @URI: the namespace URI for the extension
* @data: the data associated to this module
*
* A function called at shutdown time of an XSLT extension module
*/
static void
xsltExtShutdownTest(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
const xmlChar * URI, void *data)
{
if (testData == NULL) {
xsltPrintErrorContext(ctxt, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltExtShutdownTest: not initialized\n");
return;
}
if (data != testData) {
xsltPrintErrorContext(ctxt, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltExtShutdownTest: wrong data\n");
}
testData = NULL;
xsltGenericDebug(xsltGenericDebugContext,
"Unregistered test module : %s\n", URI);
}
/************************************************************************ /************************************************************************
* * * *
* Registration of XSLT and libxslt functions * * Registration of XSLT and libxslt functions *
@@ -932,8 +806,4 @@ xsltRegisterAllFunctions(xmlXPathContextPtr ctxt)
xsltElementAvailableFunction); xsltElementAvailableFunction);
xmlXPathRegisterFunc(ctxt, (const xmlChar *) "function-available", xmlXPathRegisterFunc(ctxt, (const xmlChar *) "function-available",
xsltFunctionAvailableFunction); xsltFunctionAvailableFunction);
xsltRegisterExtModule((const xmlChar *) XSLT_DEFAULT_URL,
xsltExtInitTest,
xsltExtShutdownTest);
} }

View File

@@ -18,6 +18,19 @@
extern "C" { extern "C" {
#endif #endif
/**
* XSLT_REGISTER_FUNCTION_LOOKUP:
*
* registering macro, not general purpose at all but used in different modules
*/
#define XSLT_REGISTER_FUNCTION_LOOKUP(ctxt) \
xmlXPathRegisterFuncLookup((ctxt)->xpathCtxt, \
xsltXPathFunctionLookup, (void *)(ctxt));
xmlXPathFunction
xsltXPathFunctionLookup (void *ctxt, const xmlChar *name,
const xmlChar *ns_uri);
/* /*
* Interfaces for the functions implementations * Interfaces for the functions implementations
*/ */

View File

@@ -36,6 +36,7 @@
#include "preproc.h" #include "preproc.h"
#include "extra.h" #include "extra.h"
#include "imports.h" #include "imports.h"
#include "extensions.h"
#ifdef WITH_XSLT_DEBUG #ifdef WITH_XSLT_DEBUG
#define WITH_XSLT_DEBUG_PREPROC #define WITH_XSLT_DEBUG_PREPROC
@@ -1343,6 +1344,15 @@ xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
if (IS_XSLT_NAME(inst, "document")) { if (IS_XSLT_NAME(inst, "document")) {
xsltDocumentComp(style, inst); xsltDocumentComp(style, inst);
} else { } else {
xsltPreComputeFunction function;
/*
* Precompute the element
*/
function =
xsltExtModuleElementPreComputeLookup(inst->name,
inst->ns->href);
if (function != NULL)
function(style, inst);
/* /*
* Mark the element for later recognition. * Mark the element for later recognition.
*/ */

View File

@@ -233,6 +233,7 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) {
cur->xpathCtxt->proximityPosition = 0; cur->xpathCtxt->proximityPosition = 0;
cur->xpathCtxt->contextSize = 0; cur->xpathCtxt->contextSize = 0;
XSLT_REGISTER_VARIABLE_LOOKUP(cur); XSLT_REGISTER_VARIABLE_LOOKUP(cur);
XSLT_REGISTER_FUNCTION_LOOKUP(cur);
cur->xpathCtxt->nsHash = style->nsHash; cur->xpathCtxt->nsHash = style->nsHash;
docu = xsltNewDocument(cur, doc); docu = xsltNewDocument(cur, doc);
if (docu == NULL) { if (docu == NULL) {
@@ -632,7 +633,7 @@ xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr node,
************************************************************************/ ************************************************************************/
void xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node, void xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
xsltStackElemPtr params); xsltStackElemPtr params);
/** /**
* xsltDefaultProcessOneNode: * xsltDefaultProcessOneNode:
* @ctxt: a XSLT process context * @ctxt: a XSLT process context
@@ -1129,8 +1130,7 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
* Flagged as an extension element * Flagged as an extension element
*/ */
function = (xsltTransformFunction) function = (xsltTransformFunction)
xmlHashLookup2(ctxt->extElements, cur->name, xsltExtElementLookup(ctxt, cur->name, cur->ns->href);
cur->ns->href);
if (function == NULL) { if (function == NULL) {
xmlNodePtr child; xmlNodePtr child;
int found = 0; int found = 0;

View File

@@ -26,6 +26,11 @@ int xsltGetXIncludeDefault (void);
/** /**
* Private Interfaces * Private Interfaces
*/ */
xsltTransformFunction
xsltExtElementLookup (xsltTransformContextPtr ctxt,
const xmlChar *name,
const xmlChar *URI);
xmlDocPtr xsltApplyStylesheet (xsltStylesheetPtr style, xmlDocPtr xsltApplyStylesheet (xsltStylesheetPtr style,
xmlDocPtr doc, xmlDocPtr doc,
const char **params); const char **params);

View File

@@ -358,7 +358,7 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem,
xmlNodePtr oldInsert; xmlNodePtr oldInsert;
container = xmlNewDocNode(ctxt->output, NULL, container = xmlNewDocNode(ctxt->output, NULL,
(const xmlChar *) "fake", NULL); (const xmlChar *) "fake", NULL);
if (container == NULL) if (container == NULL)
return(NULL); return(NULL);
@@ -472,7 +472,7 @@ xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt) {
xmlNodePtr oldInsert; xmlNodePtr oldInsert;
container = xmlNewDocNode(ctxt->output, NULL, container = xmlNewDocNode(ctxt->output, NULL,
(const xmlChar *) "fake", NULL); (const xmlChar *) "fake", NULL);
if (container == NULL) if (container == NULL)
return(NULL); return(NULL);

View File

@@ -328,6 +328,7 @@ xsltNewStylesheet(void) {
cur->exclPrefixNr = 0; cur->exclPrefixNr = 0;
cur->exclPrefixMax = 0; cur->exclPrefixMax = 0;
cur->exclPrefixTab = NULL; cur->exclPrefixTab = NULL;
cur->extInfos = NULL;
return(cur); return(cur);
} }
@@ -369,6 +370,7 @@ xsltFreeStylesheet(xsltStylesheetPtr sheet)
xsltFreeNamespaceAliasHashes(sheet); xsltFreeNamespaceAliasHashes(sheet);
xsltFreeStyleDocuments(sheet); xsltFreeStyleDocuments(sheet);
xsltFreeStylePreComps(sheet); xsltFreeStylePreComps(sheet);
xsltShutdownExts(sheet);
if (sheet->doc != NULL) if (sheet->doc != NULL)
xmlFreeDoc(sheet->doc); xmlFreeDoc(sheet->doc);
if (sheet->variables != NULL) if (sheet->variables != NULL)
@@ -1247,24 +1249,21 @@ xsltGatherNamespaces(xsltStylesheetPtr style) {
/** /**
* xsltParseTemplateContent: * xsltParseTemplateContent:
* @style: the XSLT stylesheet * @style: the XSLT stylesheet
* @ret: the "template" structure
* @template: the container node (can be a document for literal results) * @template: the container node (can be a document for literal results)
* *
* parse an XSLT template element content * parse a template content-model
* Clean-up the template content from unwanted ignorable blank nodes * Clean-up the template content from unwanted ignorable blank nodes
* and process xslt:text * and process xslt:text
*/ */
static void void
xsltParseTemplateContent(xsltStylesheetPtr style, xsltTemplatePtr ret, xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr template) {
xmlNodePtr template) {
xmlNodePtr cur, delete; xmlNodePtr cur, delete;
/* /*
* This content comes from the stylesheet * This content comes from the stylesheet
* For stylesheets, the set of whitespace-preserving * For stylesheets, the set of whitespace-preserving
* element names consists of just xsl:text. * element names consists of just xsl:text.
*/ */
ret->elem = template;
cur = template->children; cur = template->children;
delete = NULL; delete = NULL;
while (cur != NULL) { while (cur != NULL) {
@@ -1412,8 +1411,6 @@ skip_children:
break; break;
cur = cur->next; cur = cur->next;
} }
ret->content = template->children;
} }
/** /**
@@ -1599,7 +1596,9 @@ xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
/* /*
* parse the content and register the pattern * parse the content and register the pattern
*/ */
xsltParseTemplateContent(style, ret, template); xsltParseTemplateContent(style, template);
ret->elem = template;
ret->content = template->children;
xsltAddTemplate(style, ret, mode, modeURI); xsltAddTemplate(style, ret, mode, modeURI);
error: error:
@@ -1652,28 +1651,44 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
cur = top->children; cur = top->children;
/*
* process xsl:import elements
*/
while (cur != NULL) { while (cur != NULL) {
if (IS_BLANK_NODE(cur)) { if (IS_BLANK_NODE(cur)) {
cur = cur->next; cur = cur->next;
continue; continue;
} }
if (!(IS_XSLT_ELEM(cur))) { if (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "import")) {
#ifdef WITH_XSLT_DEBUG_PARSING
xsltGenericDebug(xsltGenericDebugContext,
"xsltParseStylesheetTop : found foreign element %s\n",
cur->name);
#endif
cur = cur->next;
continue;
}
if (IS_XSLT_NAME(cur, "import")) {
xsltParseStylesheetImport(style, cur); xsltParseStylesheetImport(style, cur);
} else } else
break; break;
cur = cur->next; cur = cur->next;
} }
/*
* process other top-level elements
*/
while (cur != NULL) { while (cur != NULL) {
if (IS_BLANK_NODE(cur)) {
cur = cur->next;
continue;
}
if ((cur->type == XML_ELEMENT_NODE) && (cur->ns == NULL)) {
xsltGenericError(xsltGenericErrorContext,
"Found a top-level element %s with null namespace URI\n",
cur->name);
style->errors++;
cur = cur->next;
continue;
}
if (!(IS_XSLT_ELEM(cur))) { if (!(IS_XSLT_ELEM(cur))) {
xsltPreComputeFunction function;
function = xsltExtModuleTopLevelLookup(cur->name,
cur->ns->href);
if (function != NULL)
function(style, cur);
#ifdef WITH_XSLT_DEBUG_PARSING #ifdef WITH_XSLT_DEBUG_PARSING
xsltGenericDebug(xsltGenericDebugContext, xsltGenericDebug(xsltGenericDebugContext,
"xsltParseStylesheetTop : found foreign element %s\n", "xsltParseStylesheetTop : found foreign element %s\n",
@@ -1819,7 +1834,9 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
/* /*
* parse the content and register the pattern * parse the content and register the pattern
*/ */
xsltParseTemplateContent(ret, template, (xmlNodePtr) doc); xsltParseTemplateContent(ret, (xmlNodePtr) doc);
template->elem = (xmlNodePtr) doc;
template->content = doc->children;
xsltAddTemplate(ret, template, NULL, NULL); xsltAddTemplate(ret, template, NULL, NULL);
} }

View File

@@ -323,6 +323,11 @@ struct _xsltStylesheet {
int exclPrefixMax; /* size of the array */ int exclPrefixMax; /* size of the array */
void *_private; /* user defined data */ void *_private; /* user defined data */
/*
* Extensions
*/
xmlHashTablePtr extInfos; /* the extension data */
}; };
/* /*
@@ -449,6 +454,9 @@ xmlXPathError xsltFormatNumberConversion(xsltDecimalFormatPtr self,
double number, double number,
xmlChar **result); xmlChar **result);
void xsltParseTemplateContent(xsltStylesheetPtr style,
xmlNodePtr template);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -288,7 +288,7 @@ xsltPrintErrorContext(xsltTransformContextPtr ctxt,
const xmlChar *name = NULL; const xmlChar *name = NULL;
const char *type = "error"; const char *type = "error";
if ((node != NULL) && (ctxt != NULL)) if ((node == NULL) && (ctxt != NULL))
node = ctxt->inst; node = ctxt->inst;
if (node != NULL) { if (node != NULL) {

View File

@@ -406,9 +406,10 @@ main(int argc, char **argv)
xmlSubstituteEntitiesDefault(1); xmlSubstituteEntitiesDefault(1);
/* /*
* Register the EXSLT extensions * Register the EXSLT extensions and the test module
*/ */
exsltRegisterAll(); exsltRegisterAll();
xsltRegisterTestModule();
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
if ((!strcmp(argv[i], "-maxdepth")) || if ((!strcmp(argv[i], "-maxdepth")) ||