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>
* 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:
*
@@ -73,6 +60,13 @@ exsltCommonInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
void
exsltCommonRegister (void) {
xsltRegisterExtModule (EXSLT_COMMON_NAMESPACE,
exsltCommonInit, NULL);
xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
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;
};
static void exsltFuncFunctionElem (xsltTransformContextPtr ctxt,
xmlNodePtr node, xmlNodePtr inst,
xsltStylePreCompPtr comp);
static void exsltFuncResultElem (xsltTransformContextPtr ctxt,
xmlNodePtr node, xmlNodePtr inst,
xsltStylePreCompPtr comp);
static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt,
int nargs);
/**
* 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:
@@ -41,6 +61,7 @@ static void exsltFuncResultElem (xsltTransformContextPtr ctxt,
*/
static exsltFuncData *
exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
xmlHashTablePtr hash;
exsltFuncData *ret;
ret = (exsltFuncData *) xmlMalloc (sizeof(exsltFuncData));
@@ -51,15 +72,13 @@ exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
}
memset(ret, 0, sizeof(exsltFuncData));
ret->funcs = xmlHashCreate(1);
ret->result = NULL;
ret->error = 0;
xsltRegisterExtElement (ctxt, (const xmlChar *) "function",
URI, exsltFuncFunctionElem);
xsltRegisterExtElement (ctxt, (const xmlChar *) "result",
URI, exsltFuncResultElem);
hash = (xmlHashTablePtr) xsltStyleGetExtData(ctxt->style, URI);
xmlHashScanFull(hash, (xmlHashScannerFull) exsltFuncRegisterFunc, ctxt);
ret->funcs = hash;
return(ret);
}
@@ -67,7 +86,7 @@ exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
/**
* exsltFuncShutdown:
* @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
*
* Shutdown the EXSLT - Functions module
@@ -76,23 +95,39 @@ static void
exsltFuncShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
const xmlChar *URI ATTRIBUTE_UNUSED,
exsltFuncData *data) {
if (data->funcs != NULL)
xmlHashFree(data->funcs, (xmlHashDeallocator) xmlFree);
if (data->result != NULL)
xmlXPathFreeObject(data->result);
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
exsltFuncRegister (void) {
xsltRegisterExtModule (EXSLT_FUNCTIONS_NAMESPACE,
(xsltExtInitFunction) exsltFuncInit,
(xsltExtShutdownFunction) exsltFuncShutdown);
static xmlHashTablePtr
exsltFuncStyleInit (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
const xmlChar *URI ATTRIBUTE_UNUSED) {
return xmlHashCreate(1);
}
/**
* 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");
return (NULL);
}
memset(ret, 0, sizeof(exsltFuncFunctionData));
ret->nargs = 0;
ret->content = NULL;
@@ -124,11 +160,12 @@ exsltFuncNewFunctionData (void) {
* @ctxt: an XPath parser context
* @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
exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
xmlXPathObjectPtr obj, oldResult, ret;
xmlHashTablePtr funcs;
exsltFuncData *data;
exsltFuncFunctionData *func;
xmlNodePtr paramNode, oldInsert, fake;
@@ -215,6 +252,7 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
* the generation of result nodes.
*/
if (fake->children != NULL) {
xmlDebugDumpNode (stderr, fake, 1);
xsltGenericError(xsltGenericErrorContext,
"{%s}%s: cannot write to result tree while "
"executing a function\n",
@@ -224,16 +262,15 @@ exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
valuePush(ctxt, ret);
}
static void
exsltFuncFunctionElem (xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlNodePtr inst, xsltStylePreCompPtr comp) {
exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) {
xmlChar *name, *prefix;
xmlNsPtr ns;
exsltFuncData *data;
xmlHashTablePtr data;
exsltFuncFunctionData *func;
xsltStylePreCompPtr param_comp;
if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL))
if ((style == NULL) || (inst == NULL))
return;
{
@@ -267,27 +304,36 @@ exsltFuncFunctionElem (xsltTransformContextPtr ctxt, xmlNodePtr node,
*/
func = exsltFuncNewFunctionData();
func->content = inst->children;
param_comp = (xsltStylePreCompPtr) func->content->_private;
while ((param_comp != NULL) && (param_comp->type == XSLT_FUNC_PARAM)) {
while (IS_XSLT_ELEM(func->content) &&
IS_XSLT_NAME(func->content, "param")) {
func->content = func->content->next;
func->nargs++;
param_comp = (xsltStylePreCompPtr) func->content->_private;
}
xsltParseTemplateContent(style, inst);
/*
* Register the function data such that it can be retrieved
* by exslFuncFunctionFunction
*/
data = (exsltFuncData *) xsltGetExtData (ctxt, EXSLT_FUNCTIONS_NAMESPACE);
xmlHashAddEntry2 (data->funcs, ns->href, name, func);
/*
* Register the function such that it is available for use in XPath
* expressions.
*/
xsltRegisterExtFunction (ctxt, name, ns->href,
exsltFuncFunctionFunction);
data = (xmlHashTablePtr) xsltStyleGetExtData (style,
EXSLT_FUNCTIONS_NAMESPACE);
if (data == NULL) {
xsltGenericError(xsltGenericErrorContext,
"exsltFuncFunctionComp: no stylesheet data\n");
xmlFree(name);
return;
}
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);
}
@@ -416,3 +462,25 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt, xmlNodePtr node,
}
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);
}
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:
*
@@ -292,5 +279,16 @@ exsltMathInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
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);
}
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:
*
@@ -247,5 +229,22 @@ exsltSetsInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
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
*/
/**
* 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:
* @ctxt: an XSLT transformation context
@@ -47,6 +71,12 @@ typedef void (*xsltExtShutdownFunction) (xsltTransformContextPtr ctxt,
int xsltRegisterExtModule (const xmlChar *URI,
xsltExtInitFunction initFunc,
xsltExtShutdownFunction shutdownFunc);
int xsltRegisterExtModuleFull
(const xmlChar * URI,
xsltExtInitFunction initFunc,
xsltExtShutdownFunction shutdownFunc,
xsltStyleExtInitFunction styleInitFunc,
xsltStyleExtShutdownFunction styleShutdownFunc);
int xsltUnregisterExtModule (const xmlChar * URI);
@@ -55,16 +85,76 @@ void xsltUnregisterAllExtModules(void);
void * xsltGetExtData (xsltTransformContextPtr ctxt,
const xmlChar *URI);
void * xsltStyleGetExtData (xsltStylesheetPtr style,
const xmlChar *URI);
void xsltShutdownCtxtExts (xsltTransformContextPtr ctxt);
void xsltShutdownExts (xsltStylesheetPtr style);
xsltTransformContextPtr
xsltXPathGetTransformContext
(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,
const xmlChar *name,
const xmlChar *URI,
xmlXPathEvalFunc function);
xmlXPathFunction function);
int xsltRegisterExtElement (xsltTransformContextPtr ctxt,
const xmlChar *name,
const xmlChar *URI,
@@ -85,6 +175,11 @@ void xsltFreeCtxtExts (xsltTransformContextPtr ctxt);
void xsltFreeExts (xsltStylesheetPtr style);
/**
* Test module http://xmlsoft.org/XSLT/
*/
void xsltRegisterTestModule (void);
#ifdef __cplusplus
}
#endif

View File

@@ -51,6 +51,41 @@
*/
#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 *
@@ -625,7 +660,11 @@ xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
name = xmlSplitQName2(obj->stringval, &prefix);
if (name == NULL) {
xmlNsPtr ns;
name = xmlStrdup(obj->stringval);
ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL);
nsURI = xmlStrdup(ns->href);
} else {
nsURI = xmlXPathNsLookup(ctxt->context, prefix);
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));
} else {
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 *
@@ -932,8 +806,4 @@ xsltRegisterAllFunctions(xmlXPathContextPtr ctxt)
xsltElementAvailableFunction);
xmlXPathRegisterFunc(ctxt, (const xmlChar *) "function-available",
xsltFunctionAvailableFunction);
xsltRegisterExtModule((const xmlChar *) XSLT_DEFAULT_URL,
xsltExtInitTest,
xsltExtShutdownTest);
}

View File

@@ -18,6 +18,19 @@
extern "C" {
#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
*/

View File

@@ -36,6 +36,7 @@
#include "preproc.h"
#include "extra.h"
#include "imports.h"
#include "extensions.h"
#ifdef WITH_XSLT_DEBUG
#define WITH_XSLT_DEBUG_PREPROC
@@ -1343,6 +1344,15 @@ xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
if (IS_XSLT_NAME(inst, "document")) {
xsltDocumentComp(style, inst);
} 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.
*/

View File

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

View File

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

View File

@@ -328,6 +328,7 @@ xsltNewStylesheet(void) {
cur->exclPrefixNr = 0;
cur->exclPrefixMax = 0;
cur->exclPrefixTab = NULL;
cur->extInfos = NULL;
return(cur);
}
@@ -369,6 +370,7 @@ xsltFreeStylesheet(xsltStylesheetPtr sheet)
xsltFreeNamespaceAliasHashes(sheet);
xsltFreeStyleDocuments(sheet);
xsltFreeStylePreComps(sheet);
xsltShutdownExts(sheet);
if (sheet->doc != NULL)
xmlFreeDoc(sheet->doc);
if (sheet->variables != NULL)
@@ -1247,24 +1249,21 @@ xsltGatherNamespaces(xsltStylesheetPtr style) {
/**
* xsltParseTemplateContent:
* @style: the XSLT stylesheet
* @ret: the "template" structure
* @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
* and process xslt:text
*/
static void
xsltParseTemplateContent(xsltStylesheetPtr style, xsltTemplatePtr ret,
xmlNodePtr template) {
void
xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr template) {
xmlNodePtr cur, delete;
/*
* This content comes from the stylesheet
* For stylesheets, the set of whitespace-preserving
* element names consists of just xsl:text.
*/
ret->elem = template;
cur = template->children;
delete = NULL;
while (cur != NULL) {
@@ -1412,8 +1411,6 @@ skip_children:
break;
cur = cur->next;
}
ret->content = template->children;
}
/**
@@ -1599,7 +1596,9 @@ xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
/*
* 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);
error:
@@ -1652,28 +1651,44 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
cur = top->children;
/*
* process xsl:import elements
*/
while (cur != NULL) {
if (IS_BLANK_NODE(cur)) {
cur = cur->next;
continue;
}
if (!(IS_XSLT_ELEM(cur))) {
#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")) {
if (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "import")) {
xsltParseStylesheetImport(style, cur);
} else
break;
cur = cur->next;
}
/*
* process other top-level elements
*/
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))) {
xsltPreComputeFunction function;
function = xsltExtModuleTopLevelLookup(cur->name,
cur->ns->href);
if (function != NULL)
function(style, cur);
#ifdef WITH_XSLT_DEBUG_PARSING
xsltGenericDebug(xsltGenericDebugContext,
"xsltParseStylesheetTop : found foreign element %s\n",
@@ -1819,7 +1834,9 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
/*
* 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);
}

View File

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

View File

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

View File

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