1
0
mirror of https://gitlab.gnome.org/GNOME/libxslt synced 2025-08-08 21:42:07 +03:00

modified extension framework to easify extension element precomputation.

* libxslt/extensions.[ch] libxslt/preproc.[ch] libxslt/transform.c
	  libxslt/xslt.c libxslt/xsltInternals.h: modified extension framework
	  to easify extension element precomputation.
	* libexslt/functions.c: uses the new framework and precomputes
	  func:result elements.
This commit is contained in:
Thomas Broyer
2001-08-05 07:37:44 +00:00
parent bc7aff0434
commit 5583b7bc3c
9 changed files with 258 additions and 54 deletions

View File

@@ -1,3 +1,11 @@
Sun Aug 5 09:37:14 CEST 2001 Thomas Broyer <tbroyer@ltgt.net>
* libxslt/extensions.[ch] libxslt/preproc.[ch] libxslt/transform.c
libxslt/xslt.c libxslt/xsltInternals.h: modified extension framework
to easify extension element precomputation.
* libexslt/functions.c: uses the new framework and precomputes
func:result elements.
Sat Aug 4 20:42:32 CEST 2001 Daniel Veillard <daniel@veillard.com> Sat Aug 4 20:42:32 CEST 2001 Daniel Veillard <daniel@veillard.com>
* libxslt/transform.c: bug fix on output="text" from Nicolas Marsgui * libxslt/transform.c: bug fix on output="text" from Nicolas Marsgui

View File

@@ -29,6 +29,11 @@ struct _exsltFuncData {
int error; /* did an error occur? */ int error; /* did an error occur? */
}; };
typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp;
struct _exsltFuncResultPreComp {
xsltElemPreComp comp;
xmlXPathCompExprPtr select;
};
static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt,
int nargs); int nargs);
@@ -161,6 +166,22 @@ exsltFuncNewFunctionData (void) {
return(ret); return(ret);
} }
/**
* exsltFreeFuncResultPreComp:
* @comp: the #exsltFuncResultPreComp to free up
*
* Deallocates an #exsltFuncResultPreComp
*/
static void
exsltFreeFuncResultPreComp (exsltFuncResultPreComp *comp) {
if (comp == NULL)
return;
if (comp->select != NULL)
xmlXPathFreeCompExpr (comp->select);
xmlFree(comp);
}
/** /**
* exsltFuncFunctionFunction: * exsltFuncFunctionFunction:
* @ctxt: an XPath parser context * @ctxt: an XPath parser context
@@ -348,14 +369,12 @@ exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) {
xmlFree(name); xmlFree(name);
} }
static void static xsltElemPreCompPtr
exsltFuncResultElem (xsltTransformContextPtr ctxt, exsltFuncResultComp (xsltStylesheetPtr style, xmlNodePtr inst,
xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst, xsltTransformFunction function) {
xsltStylePreCompPtr comp ATTRIBUTE_UNUSED) {
xmlNodePtr test; xmlNodePtr test;
xmlChar *select; xmlChar *select;
exsltFuncData *data; exsltFuncResultPreComp *ret;
xmlXPathObjectPtr ret;
/* /*
* "Validity" checking * "Validity" checking
@@ -371,7 +390,7 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
xsltGenericError(xsltGenericErrorContext, xsltGenericError(xsltGenericErrorContext,
"exsltFuncResultElem: only xsl:fallback is " "exsltFuncResultElem: only xsl:fallback is "
"allowed to follow func:result\n"); "allowed to follow func:result\n");
return; return (NULL);
} }
/* it is an error for a func:result element to not be a descendant /* it is an error for a func:result element to not be a descendant
* of func:function. * of func:function.
@@ -391,7 +410,7 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
xsltGenericError(xsltGenericErrorContext, xsltGenericError(xsltGenericErrorContext,
"func:result element not allowed within" "func:result element not allowed within"
" another func:result element\n"); " another func:result element\n");
return; return (NULL);
} }
} }
if (IS_XSLT_ELEM(test) && if (IS_XSLT_ELEM(test) &&
@@ -400,9 +419,46 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
xsltGenericError(xsltGenericErrorContext, xsltGenericError(xsltGenericErrorContext,
"func:result element not allowed within" "func:result element not allowed within"
" a variable binding element\n"); " a variable binding element\n");
return; return (NULL);
} }
} }
/*
* Precomputation
*/
ret = (exsltFuncResultPreComp *)
xmlMalloc (sizeof(exsltFuncResultPreComp));
if (ret == NULL) {
xsltPrintErrorContext(NULL, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"exsltFuncResultComp : malloc failed\n");
return (NULL);
}
memset(ret, 0, sizeof(exsltFuncResultPreComp));
xsltInitElemPreComp ((xsltElemPreCompPtr) ret, style, inst, function,
(xsltElemPreCompDeallocator) exsltFreeFuncResultPreComp);
ret->select = NULL;
/*
* Precompute the select attribute
*/
select = xmlGetNsProp(inst, (const xmlChar *) "select", NULL);
if (select != NULL) {
ret->select = xmlXPathCompile (select);
xmlFree(select);
}
return ((xsltElemPreCompPtr) ret);
}
static void
exsltFuncResultElem (xsltTransformContextPtr ctxt,
xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst,
exsltFuncResultPreComp *comp) {
exsltFuncData *data;
xmlXPathObjectPtr ret;
/* It is an error if instantiating the content of the /* It is an error if instantiating the content of the
* func:function element results in the instantiation of more than * func:function element results in the instantiation of more than
* one func:result elements. * one func:result elements.
@@ -419,12 +475,10 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
data->error = 1; data->error = 1;
return; return;
} }
/* /*
* Processing * Processing
*/ */
select = xmlGetProp(inst, (const xmlChar *) "select"); if (comp->select != NULL) {
if (select != NULL) {
/* If the func:result element has a select attribute, then the /* If the func:result element has a select attribute, then the
* value of the attribute must be an expression and the * value of the attribute must be an expression and the
* returned value is the object that results from evaluating * returned value is the object that results from evaluating
@@ -435,17 +489,15 @@ exsltFuncResultElem (xsltTransformContextPtr ctxt,
"func:result content must be empty if it" "func:result content must be empty if it"
" has a select attribute\n"); " has a select attribute\n");
data->error = 1; data->error = 1;
xmlFree(select);
return; return;
} }
ret = xmlXPathEvalExpression(select, ctxt->xpathCtxt); ret = xmlXPathCompiledEval(comp->select, ctxt->xpathCtxt);
xmlFree(select);
if (ret == NULL) { if (ret == NULL) {
xsltGenericError(xsltGenericErrorContext, xsltGenericError(xsltGenericErrorContext,
"exsltFuncResultElem: ret == NULL\n"); "exsltFuncResultElem: ret == NULL\n");
return; return;
} }
} else if (test->children != NULL) { } else if (inst->children != NULL) {
/* If the func:result element does not have a select attribute /* If the func:result element does not have a select attribute
* and has non-empty content (i.e. the func:result element has * and has non-empty content (i.e. the func:result element has
* one or more child nodes), then the content of the * one or more child nodes), then the content of the
@@ -494,7 +546,7 @@ exsltFuncRegister (void) {
EXSLT_FUNCTIONS_NAMESPACE, EXSLT_FUNCTIONS_NAMESPACE,
exsltFuncFunctionComp); exsltFuncFunctionComp);
xsltRegisterExtModuleElement ((const xmlChar *) "result", xsltRegisterExtModuleElement ((const xmlChar *) "result",
EXSLT_FUNCTIONS_NAMESPACE, EXSLT_FUNCTIONS_NAMESPACE,
NULL, (xsltPreComputeFunction)exsltFuncResultComp,
exsltFuncResultElem); (xsltTransformFunction) exsltFuncResultElem);
} }

View File

@@ -342,7 +342,7 @@ xsltRegisterExtPrefix(xsltStylesheetPtr style,
*/ */
int int
xsltRegisterExtFunction(xsltTransformContextPtr ctxt, const xmlChar *name, xsltRegisterExtFunction(xsltTransformContextPtr ctxt, const xmlChar *name,
const xmlChar *URI, xmlXPathEvalFunc function) { const xmlChar *URI, xmlXPathFunction function) {
if ((ctxt == NULL) || (name == NULL) || if ((ctxt == NULL) || (name == NULL) ||
(URI == NULL) || (function == NULL)) (URI == NULL) || (function == NULL))
return(-1); return(-1);
@@ -954,6 +954,96 @@ xsltUnregisterAllExtModuleFunction (void) {
xsltFunctionsHash = NULL; xsltFunctionsHash = NULL;
} }
/**
* xsltNewElemPreComp:
* @style: the XSLT stylesheet
* @inst: the element node
* @function: the transform function
*
* Creates and initializes an #xsltElemPreComp
*
* Returns the new and initialized #xsltElemPreComp
*/
xsltElemPreCompPtr
xsltNewElemPreComp (xsltStylesheetPtr style, xmlNodePtr inst,
xsltTransformFunction function) {
xsltElemPreCompPtr cur;
cur = (xsltElemPreCompPtr) xmlMalloc (sizeof(xsltElemPreComp));
if (cur == NULL) {
xsltPrintErrorContext(style, NULL, NULL);
xsltGenericError(xsltGenericErrorContext,
"xsltNewExtElement : malloc failed\n");
return (NULL);
}
memset(cur, 0, sizeof(xsltElemPreComp));
xsltInitElemPreComp (cur, style, inst, function,
(xsltElemPreCompDeallocator) xmlFree);
return (cur);
}
/**
* xsltInitElemPreComp:
* @comp: an #xsltElemPreComp (or generally a derived structure)
* @style: the XSLT stylesheet
* @inst: the element node
* @function: the transform function
* @freeFunc: the @comp deallocator
*
* Initializes an existing #xsltElemPreComp structure. This is usefull
* when extending an #xsltElemPreComp to store precomputed data.
* This function MUST be called on any extension element precomputed
* data struct.
*/
void
xsltInitElemPreComp (xsltElemPreCompPtr comp, xsltStylesheetPtr style,
xmlNodePtr inst, xsltTransformFunction function,
xsltElemPreCompDeallocator freeFunc) {
comp->type = XSLT_FUNC_EXTENSION;
comp->func = function;
comp->inst = inst;
comp->free = freeFunc;
comp->next = style->preComps;
style->preComps = comp;
}
/**
* xsltPreComputeExtModuleElement:
* @style: the stylesheet
* @inst: the element node
*
* Precomputes an extension module element
*
* Returns the precomputed data
*/
xsltElemPreCompPtr
xsltPreComputeExtModuleElement (xsltStylesheetPtr style,
xmlNodePtr inst) {
xsltExtElementPtr ext;
xsltElemPreCompPtr comp = NULL;
if ((style == NULL) || (inst == NULL) ||
(inst->type != XML_ELEMENT_NODE) || (inst->ns == NULL))
return (NULL);
ext = (xsltExtElementPtr)
xmlHashLookup2 (xsltElementsHash, inst->name,
inst->ns->href);
if (ext == NULL)
return (NULL);
if (ext->precomp != NULL)
comp = ext->precomp(style, inst, ext->transform);
if (comp == NULL)
comp = xsltNewElemPreComp (style, inst, ext->transform);
return (comp);
}
/** /**
* xsltRegisterExtModuleElement: * xsltRegisterExtModuleElement:
* @name: the element name * @name: the element name
@@ -1106,7 +1196,7 @@ xsltUnregisterAllExtModuleElement (void) {
*/ */
int int
xsltRegisterExtModuleTopLevel (const xmlChar *name, const xmlChar *URI, xsltRegisterExtModuleTopLevel (const xmlChar *name, const xmlChar *URI,
xsltPreComputeFunction function) { xsltTopLevelFunction function) {
if ((name == NULL) || (URI == NULL) || (function == NULL)) if ((name == NULL) || (URI == NULL) || (function == NULL))
return(-1); return(-1);
@@ -1130,12 +1220,12 @@ xsltRegisterExtModuleTopLevel (const xmlChar *name, const xmlChar *URI,
* *
* Returns the callback function if found, NULL otherwise. * Returns the callback function if found, NULL otherwise.
*/ */
xsltPreComputeFunction xsltTopLevelFunction
xsltExtModuleTopLevelLookup (const xmlChar *name, const xmlChar *URI) { xsltExtModuleTopLevelLookup (const xmlChar *name, const xmlChar *URI) {
if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL)) if ((xsltTopLevelsHash == NULL) || (name == NULL) || (URI == NULL))
return(NULL); return(NULL);
return((xsltPreComputeFunction) return((xsltTopLevelFunction)
xmlHashLookup2(xsltTopLevelsHash, name, URI)); xmlHashLookup2(xsltTopLevelsHash, name, URI));
} }
@@ -1244,8 +1334,11 @@ xsltExtFunctionTest(xmlXPathParserContextPtr ctxt, int nargs ATTRIBUTE_UNUSED)
* *
* Process a libxslt:test node * Process a libxslt:test node
*/ */
static void static xsltElemPreCompPtr
xsltExtElementPreCompTest(xsltStylesheetPtr style, xmlNodePtr inst) { xsltExtElementPreCompTest(xsltStylesheetPtr style, xmlNodePtr inst,
xsltTransformFunction function) {
xsltElemPreCompPtr ret;
if (style == NULL) { if (style == NULL) {
xsltPrintErrorContext(NULL, NULL, inst); xsltPrintErrorContext(NULL, NULL, inst);
xsltGenericError(xsltGenericErrorContext, xsltGenericError(xsltGenericErrorContext,
@@ -1272,6 +1365,8 @@ xsltExtElementPreCompTest(xsltStylesheetPtr style, xmlNodePtr inst) {
style->errors++; style->errors++;
return; return;
} }
ret = xsltNewElemPreComp (style, inst, function);
return (ret);
} }
/** /**
@@ -1286,7 +1381,7 @@ xsltExtElementPreCompTest(xsltStylesheetPtr style, xmlNodePtr inst) {
static void static void
xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltExtElementTest(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlNodePtr inst, xmlNodePtr inst,
xsltStylePreCompPtr comp ATTRIBUTE_UNUSED) xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
{ {
xmlNodePtr comment; xmlNodePtr comment;

View File

@@ -113,9 +113,20 @@ int xsltUnregisterExtModuleFunction (const xmlChar *name,
/* /*
* extension elements * extension elements
*/ */
typedef void typedef xsltElemPreCompPtr
(*xsltPreComputeFunction) (xsltStylesheetPtr ctxt, (*xsltPreComputeFunction) (xsltStylesheetPtr style,
xmlNodePtr inst); xmlNodePtr inst,
xsltTransformFunction function);
xsltElemPreCompPtr
xsltNewElemPreComp (xsltStylesheetPtr style,
xmlNodePtr inst,
xsltTransformFunction function);
void xsltInitElemPreComp (xsltElemPreCompPtr comp,
xsltStylesheetPtr style,
xmlNodePtr inst,
xsltTransformFunction function,
xsltElemPreCompDeallocator freeFunc);
int xsltRegisterExtModuleElement (const xmlChar *name, int xsltRegisterExtModuleElement (const xmlChar *name,
const xmlChar *URI, const xmlChar *URI,
@@ -138,10 +149,14 @@ int xsltUnregisterExtModuleElement (const xmlChar *name,
/* /*
* top-level elements * top-level elements
*/ */
typedef void
(*xsltTopLevelFunction) (xsltStylesheetPtr style,
xmlNodePtr inst);
int xsltRegisterExtModuleTopLevel (const xmlChar *name, int xsltRegisterExtModuleTopLevel (const xmlChar *name,
const xmlChar *URI, const xmlChar *URI,
xsltPreComputeFunction function); xsltTopLevelFunction function);
xsltPreComputeFunction xsltTopLevelFunction
xsltExtModuleTopLevelLookup (const xmlChar *name, xsltExtModuleTopLevelLookup (const xmlChar *name,
const xmlChar *URI); const xmlChar *URI);
int xsltUnregisterExtModuleTopLevel (const xmlChar *name, int xsltUnregisterExtModuleTopLevel (const xmlChar *name,
@@ -172,6 +187,9 @@ int xsltInitCtxtExts (xsltTransformContextPtr ctxt);
void xsltFreeCtxtExts (xsltTransformContextPtr ctxt); void xsltFreeCtxtExts (xsltTransformContextPtr ctxt);
void xsltFreeExts (xsltStylesheetPtr style); void xsltFreeExts (xsltStylesheetPtr style);
xsltElemPreCompPtr
xsltPreComputeExtModuleElement (xsltStylesheetPtr style,
xmlNodePtr inst);
/** /**
* Test module http://xmlsoft.org/XSLT/ * Test module http://xmlsoft.org/XSLT/

View File

@@ -1213,7 +1213,10 @@ xsltFreeStylePreComps(xsltStylesheetPtr style) {
cur = style->preComps; cur = style->preComps;
while (cur != NULL) { while (cur != NULL) {
next = cur->next; next = cur->next;
xsltFreeStylePreComp(cur); if (cur->type == XSLT_FUNC_EXTENSION)
((xsltElemPreCompPtr)cur)->free(cur);
else
xsltFreeStylePreComp(cur);
cur = next; cur = next;
} }
} }
@@ -1341,20 +1344,16 @@ xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
cur->nsNr = i; cur->nsNr = i;
} }
} else { } else {
/* FIXME */
if (IS_XSLT_NAME(inst, "document")) { if (IS_XSLT_NAME(inst, "document")) {
xsltDocumentComp(style, inst); xsltDocumentComp(style, inst);
} else { } else {
xsltPreComputeFunction function; inst->_private =
(void *) xsltPreComputeExtModuleElement(style, inst);
/* /*
* Precompute the element * Unknown element, maybe registered at the context
*/ * level. Mark it for later recognition.
function =
xsltExtModuleElementPreComputeLookup(inst->name,
inst->ns->href);
if (function != NULL)
function(style, inst);
/*
* Mark the element for later recognition.
*/ */
if (inst->_private == NULL) if (inst->_private == NULL)
inst->_private = (void *) xsltExtMarker; inst->_private = (void *) xsltExtMarker;

View File

@@ -19,6 +19,8 @@ extern "C" {
/* /*
* Interfaces * Interfaces
*/ */
extern const xmlChar *xsltExtMarker;
void xsltStylePreCompute (xsltStylesheetPtr style, void xsltStylePreCompute (xsltStylesheetPtr style,
xmlNodePtr inst); xmlNodePtr inst);
void xsltFreeStylePreComps (xsltStylesheetPtr style); void xsltFreeStylePreComps (xsltStylesheetPtr style);

View File

@@ -1129,8 +1129,12 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
/* /*
* Flagged as an extension element * Flagged as an extension element
*/ */
function = (xsltTransformFunction) if (cur->_private == xsltExtMarker)
xsltExtElementLookup(ctxt, cur->name, cur->ns->href); function = (xsltTransformFunction)
xsltExtElementLookup(ctxt, cur->name, cur->ns->href);
else
function = ((xsltElemPreCompPtr)cur->_private)->func;
if (function == NULL) { if (function == NULL) {
xmlNodePtr child; xmlNodePtr child;
int found = 0; int found = 0;

View File

@@ -1682,7 +1682,7 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
continue; continue;
} }
if (!(IS_XSLT_ELEM(cur))) { if (!(IS_XSLT_ELEM(cur))) {
xsltPreComputeFunction function; xsltTopLevelFunction function;
function = xsltExtModuleTopLevelLookup(cur->name, function = xsltExtModuleTopLevelLookup(cur->name,
cur->ns->href); cur->ns->href);

View File

@@ -107,14 +107,13 @@ typedef struct _xsltTransformContext xsltTransformContext;
typedef xsltTransformContext *xsltTransformContextPtr; typedef xsltTransformContext *xsltTransformContextPtr;
/** /**
* xsltStylePreComp: * xsltElemPreComp:
* *
* The in-memory structure corresponding to XSLT stylesheet constructs * The in-memory structure corresponding to element precomputed data,
* precomputed data. * designed to be extended by extension implementors.
*/ */
typedef struct _xsltElemPreComp xsltElemPreComp;
typedef struct _xsltStylePreComp xsltStylePreComp; typedef xsltElemPreComp *xsltElemPreCompPtr;
typedef xsltStylePreComp *xsltStylePreCompPtr;
/** /**
* xsltTransformFunction: * xsltTransformFunction:
@@ -129,7 +128,7 @@ typedef xsltStylePreComp *xsltStylePreCompPtr;
typedef void (*xsltTransformFunction) (xsltTransformContextPtr ctxt, typedef void (*xsltTransformFunction) (xsltTransformContextPtr ctxt,
xmlNodePtr node, xmlNodePtr node,
xmlNodePtr inst, xmlNodePtr inst,
xsltStylePreCompPtr comp); xsltElemPreCompPtr comp);
typedef enum { typedef enum {
XSLT_FUNC_COPY=1, XSLT_FUNC_COPY=1,
@@ -152,17 +151,44 @@ typedef enum {
XSLT_FUNC_WITHPARAM, XSLT_FUNC_WITHPARAM,
XSLT_FUNC_PARAM, XSLT_FUNC_PARAM,
XSLT_FUNC_VARIABLE, XSLT_FUNC_VARIABLE,
XSLT_FUNC_WHEN XSLT_FUNC_WHEN,
XSLT_FUNC_EXTENSION
} xsltStyleType; } xsltStyleType;
/**
* xsltElemPreCompDeallocator:
* @comp: the #xsltElemPreComp to free up
*
* Deallocates an #xsltElemPreComp structure
*/
typedef void (*xsltElemPreCompDeallocator) (xsltElemPreCompPtr comp);
/**
* xsltElemPreComp:
*
* The in-memory structure corresponding to element precomputed data,
* designed to be extended by extension implementors.
*/
struct _xsltElemPreComp {
xsltElemPreCompPtr next; /* chained list */
xsltStyleType type; /* type of the element */
xsltTransformFunction func; /* handling function */
xmlNodePtr inst; /* the instruction */
/* end of common part */
xsltElemPreCompDeallocator free; /* the deallocator */
};
/** /**
* xsltStylePreComp: * xsltStylePreComp:
* *
* The in-memory structure corresponding to XSLT stylesheet constructs * The in-memory structure corresponding to XSLT stylesheet constructs
* precomputed data. * precomputed data.
*/ */
typedef struct _xsltStylePreComp xsltStylePreComp;
typedef xsltStylePreComp *xsltStylePreCompPtr;
struct _xsltStylePreComp { struct _xsltStylePreComp {
struct _xsltStylePreComp *next;/* chained list */ xsltElemPreCompPtr next; /* chained list */
xsltStyleType type; /* type of the element */ xsltStyleType type; /* type of the element */
xsltTransformFunction func; /* handling function */ xsltTransformFunction func; /* handling function */
xmlNodePtr inst; /* the instruction */ xmlNodePtr inst; /* the instruction */