From: Daniel Veillard Date: Mon, 19 Mar 2001 17:52:26 +0000 (+0000) Subject: Switched all the processing to compiled XPath form, there is a X-Git-Tag: v1.1.28~1405 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7f6e74674b2407a13b710d253face364ff28a2ab;p=platform%2Fupstream%2Flibxslt.git Switched all the processing to compiled XPath form, there is a small problem showing up in the mediaobject.filename template of DocBook, but the way unparsed-entity-uri() doesn't follow the spec it seems so ...: - xsltutils.h: cleanup some garbage added last night - xsltInternals.h variables.c transform.c templates.[ch] preproc.c pattern.c keys.c: switched the whole XSLt processing to use XPath precompiled expressions and reusing them. - functions.c: some cleanup, seems people don't use unparsed-entity-uri() the way it's supposed to be used Daniel --- diff --git a/ChangeLog b/ChangeLog index eef15e0..3686022 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Mon Mar 19 18:40:40 CET 2001 Daniel Veillard + + * xsltutils.h: cleanup some garbage added last night + * xsltInternals.h variables.c transform.c templates.[ch] + preproc.c pattern.c keys.c: switched the whole XSLt processing + to use XPath precompiled expressions and reusing them. + * functions.c: some cleanup, seems people don't use + unparsed-entity-uri() the way it's supposed to be used + Mon Mar 19 01:08:05 CET 2001 Daniel Veillard * libxslt/keys.c libxslt/templates.c libxslt/transform.c diff --git a/libxslt/functions.c b/libxslt/functions.c index c6c0a93..6966750 100644 --- a/libxslt/functions.c +++ b/libxslt/functions.c @@ -295,19 +295,19 @@ xsltUnparsedEntityURIFunction(xmlXPathParserContextPtr ctxt, int nargs){ xmlXPathObjectPtr obj; xmlChar *str; - if (nargs != 1) { + if ((nargs != 1) || (ctxt->value == NULL)) { xsltGenericError(xsltGenericErrorContext, - "system-property() : expects one string arg\n"); + "unparsed-entity-uri() : expects one string arg\n"); ctxt->error = XPATH_INVALID_ARITY; return; } - if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) { + obj = valuePop(ctxt); + if (obj->type != XPATH_STRING) { xsltGenericError(xsltGenericErrorContext, - "generate-id() : invalid arg expecting a string\n"); - ctxt->error = XPATH_INVALID_TYPE; - return; + "unparsed-entity-uri() : invalid arg expecting a string\n"); + obj = xmlXPathConvertString(obj); } - obj = valuePop(ctxt); + str = obj->stringval; if (str == NULL) { valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); @@ -321,8 +321,7 @@ xsltUnparsedEntityURIFunction(xmlXPathParserContextPtr ctxt, int nargs){ if (entity->URI != NULL) valuePush(ctxt, xmlXPathNewString(entity->URI)); else - valuePush(ctxt, xmlXPathNewString( - xmlStrdup((const xmlChar *)""))); + valuePush(ctxt, xmlXPathNewString((const xmlChar *)"")); } } xmlXPathFreeObject(obj); @@ -416,7 +415,7 @@ xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){ return; } cur = nodelist->nodeTab[0]; - for (i = 2;i <= nodelist->nodeNr;i++) { + for (i = 1;i < nodelist->nodeNr;i++) { ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]); if (ret == -1) cur = nodelist->nodeTab[i]; diff --git a/libxslt/keys.c b/libxslt/keys.c index fd2f6c3..ca53107 100644 --- a/libxslt/keys.c +++ b/libxslt/keys.c @@ -291,11 +291,12 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc, int i; xmlChar *pattern = NULL; xmlNodeSetPtr nodelist = NULL, keylist; - xmlXPathObjectPtr res = NULL, tmp; + xmlXPathObjectPtr res = NULL; xmlChar *str; - xmlXPathParserContextPtr xpathParserCtxt; + xmlXPathCompExprPtr comp; xsltKeyTablePtr table; + /* * Prepare the search */ @@ -310,22 +311,14 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc, * Evaluate the nodelist */ - xpathParserCtxt = - xmlXPathNewParserContext(pattern, ctxt->xpathCtxt); - if (xpathParserCtxt == NULL) + comp = xmlXPathCompile(pattern); + if (comp == NULL) goto error; ctxt->document = doc; ctxt->node = (xmlNodePtr) doc->doc; ctxt->xpathCtxt->node = (xmlNodePtr) doc->doc; - xmlXPathEvalExpr(xpathParserCtxt); - xmlXPathRunEval(xpathParserCtxt); - res = valuePop(xpathParserCtxt); - do { - tmp = valuePop(xpathParserCtxt); - if (tmp != NULL) { - xmlXPathFreeObject(tmp); - } - } while (tmp != NULL); + res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt); + xmlXPathFreeCompExpr(comp); if (res != NULL) { if (res->type == XPATH_NODESET) { nodelist = res->nodesetval; @@ -359,9 +352,12 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc, if (table == NULL) goto error; + comp = xmlXPathCompile(keyd->use); + if (comp == NULL) + goto error; for (i = 0;i < nodelist->nodeNr;i++) { ctxt->node = nodelist->nodeTab[i]; - str = xsltEvalXPathString(ctxt, keyd->use); + str = xsltEvalXPathString(ctxt, comp); if (str != NULL) { #ifdef DEBUG_KEYS xsltGenericDebug(xsltGenericDebugContext, @@ -385,6 +381,7 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc, #endif } } + xmlXPathFreeCompExpr(comp); table->next = doc->keys; doc->keys = table; @@ -392,8 +389,6 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc, error: if (res != NULL) xmlXPathFreeObject(res); - if (xpathParserCtxt != NULL) - xmlXPathFreeParserContext(xpathParserCtxt); if (pattern != NULL) xmlFree(pattern); } diff --git a/libxslt/pattern.c b/libxslt/pattern.c index 787db93..0a07ed0 100644 --- a/libxslt/pattern.c +++ b/libxslt/pattern.c @@ -65,6 +65,7 @@ struct _xsltStepOp { xmlChar *value; xmlChar *value2; xmlChar *value3; + xmlXPathCompExprPtr comp; /* * Optimisations for count */ @@ -150,6 +151,8 @@ xsltFreeCompMatch(xsltCompMatchPtr comp) { xmlFree(op->value2); if (op->value3 != NULL) xmlFree(op->value3); + if (op->comp != NULL) + xmlXPathFreeCompExpr(op->comp); } memset(comp, -1, sizeof(xsltCompMatch)); xmlFree(comp); @@ -655,21 +658,30 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, oldNode = ctxt->node; ctxt->node = node; - if ((step->value == NULL) || - (!xsltEvalXPathPredicate(ctxt, step->value))) { - if (pos != 0) { - ctxt->xpathCtxt->contextSize = oldCS; - ctxt->xpathCtxt->proximityPosition = oldCP; - } - ctxt->node = oldNode; - return(0); + if (step->value == NULL) + goto wrong_index; + + if (step->comp == NULL) { + step->comp = xmlXPathCompile(step->value); + if (step->comp == NULL) + goto wrong_index; } + if (!xsltEvalXPathPredicate(ctxt, step->comp)) + goto wrong_index; + if (pos != 0) { ctxt->xpathCtxt->contextSize = oldCS; ctxt->xpathCtxt->proximityPosition = oldCP; } ctxt->node = oldNode; break; +wrong_index: + if (pos != 0) { + ctxt->xpathCtxt->contextSize = oldCS; + ctxt->xpathCtxt->proximityPosition = oldCP; + } + ctxt->node = oldNode; + return(0); } case XSLT_OP_PI: if (node->type != XML_PI_NODE) diff --git a/libxslt/preproc.c b/libxslt/preproc.c index 1476aea..1bb3079 100644 --- a/libxslt/preproc.c +++ b/libxslt/preproc.c @@ -158,6 +158,8 @@ xsltFreeStylePreComp(xsltStylePreCompPtr comp) { xmlFree(comp->numdata.value); if (comp->numdata.format != NULL) xmlFree(comp->numdata.format); + if (comp->comp != NULL) + xmlXPathFreeCompExpr(comp->comp); memset(comp, -1, sizeof(xsltStylePreComp)); diff --git a/libxslt/templates.c b/libxslt/templates.c index 14e1640..23e3a3e 100644 --- a/libxslt/templates.c +++ b/libxslt/templates.c @@ -39,7 +39,7 @@ /** * xsltEvalXPathPredicate: * @ctxt: the XSLT transformation context - * @str: the XPath expression + * @comp: the XPath compiled expression * * Process the expression using XPath and evaluate the result as * an XPath predicate @@ -47,47 +47,36 @@ * Returns 1 is the predicate was true, 0 otherwise */ int -xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, const xmlChar *expr) { - int ret; - xmlXPathObjectPtr res, tmp; - xmlXPathParserContextPtr xpathParserCtxt; - - xpathParserCtxt = - xmlXPathNewParserContext(expr, ctxt->xpathCtxt); - if (xpathParserCtxt == NULL) - return(0); +xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, + xmlXPathCompExprPtr comp) { + int ret, position; + xmlXPathObjectPtr res; + + position = ctxt->xpathCtxt->proximityPosition; ctxt->xpathCtxt->node = ctxt->node; - xmlXPathEvalExpr(xpathParserCtxt); - xmlXPathRunEval(xpathParserCtxt); - res = valuePop(xpathParserCtxt); - do { - tmp = valuePop(xpathParserCtxt); - if (tmp != NULL) { - xmlXPathFreeObject(tmp); - } - } while (tmp != NULL); + res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt); + ctxt->xpathCtxt->proximityPosition = position; if (res != NULL) { - ret = xmlXPathEvaluatePredicateResult(xpathParserCtxt, res); + ret = xmlXPathEvalPredicate(ctxt->xpathCtxt, res); xmlXPathFreeObject(res); #ifdef DEBUG_TEMPLATES xsltGenericDebug(xsltGenericDebugContext, - "xsltEvalXPathPredicate: %s returns %d\n", expr, ret); + "xsltEvalXPathPredicate: returns %d\n", ret); #endif } else { #ifdef DEBUG_TEMPLATES xsltGenericDebug(xsltGenericDebugContext, - "xsltEvalXPathPredicate: %s failed\n", expr); + "xsltEvalXPathPredicate: failed\n"); #endif ret = 0; } - xmlXPathFreeParserContext(xpathParserCtxt); return(ret); } /** * xsltEvalXPathString: * @ctxt: the XSLT transformation context - * @str: the XPath expression + * @comp: the compiled XPath expression * * Process the expression using XPath and get a string * @@ -95,27 +84,15 @@ xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, const xmlChar *expr) { * caller. */ xmlChar * -xsltEvalXPathString(xsltTransformContextPtr ctxt, const xmlChar *expr) { +xsltEvalXPathString(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp) { xmlChar *ret = NULL; - xmlXPathObjectPtr res, tmp; - xmlXPathParserContextPtr xpathParserCtxt; + xmlXPathObjectPtr res; - xpathParserCtxt = - xmlXPathNewParserContext(expr, ctxt->xpathCtxt); - if (xpathParserCtxt == NULL) - return(NULL); ctxt->xpathCtxt->node = ctxt->node; - xmlXPathEvalExpr(xpathParserCtxt); - xmlXPathRunEval(xpathParserCtxt); - xmlXPathStringFunction(xpathParserCtxt, 1); - res = valuePop(xpathParserCtxt); - do { - tmp = valuePop(xpathParserCtxt); - if (tmp != NULL) { - xmlXPathFreeObject(tmp); - } - } while (tmp != NULL); + res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt); if (res != NULL) { + if (res->type != XPATH_STRING) + res = xmlXPathConvertString(res); if (res->type == XPATH_STRING) { ret = res->stringval; res->stringval = NULL; @@ -125,10 +102,9 @@ xsltEvalXPathString(xsltTransformContextPtr ctxt, const xmlChar *expr) { } xmlXPathFreeObject(res); } - xmlXPathFreeParserContext(xpathParserCtxt); #ifdef DEBUG_TEMPLATES xsltGenericDebug(xsltGenericDebugContext, - "xsltEvalXPathString: %s returns %s\n", expr, ret); + "xsltEvalXPathString: returns %s\n", ret); #endif return(ret); } @@ -208,7 +184,13 @@ xsltAttrTemplateValueProcess(xsltTransformContextPtr ctxt, const xmlChar *str) { if (expr == NULL) return(ret); else { - val = xsltEvalXPathString(ctxt, expr); + xmlXPathCompExprPtr comp; + /* + * TODO: keep precompiled form around + */ + comp = xmlXPathCompile(expr); + val = xsltEvalXPathString(ctxt, comp); + xmlXPathFreeCompExpr(comp); xmlFree(expr); if (val != NULL) { ret = xmlStrcat(ret, val); @@ -254,8 +236,9 @@ xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, return(NULL); /* - * TODO: accelerator if there is no AttrValueTemplate in the stylesheet - * return expr directly + * TODO: though now {} is detected ahead, it would still be good to + * optimize both functions to keep the splitted value if the + * attribute content and the XPath precompiled expressions around */ ret = xsltAttrTemplateValueProcess(ctxt, expr); diff --git a/libxslt/templates.h b/libxslt/templates.h index be2f6c0..93294f6 100644 --- a/libxslt/templates.h +++ b/libxslt/templates.h @@ -18,7 +18,7 @@ extern "C" { #endif int xsltEvalXPathPredicate (xsltTransformContextPtr ctxt, - const xmlChar *expr); + xmlXPathCompExprPtr comp); xmlChar * xsltEvalTemplateString (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr parent); @@ -30,7 +30,7 @@ xmlChar * xsltEvalStaticAttrValueTemplate (xsltTransformContextPtr ctxt, const xmlChar *name, int *found); xmlChar * xsltEvalXPathString (xsltTransformContextPtr ctxt, - const xmlChar *expr); + xmlXPathCompExprPtr comp); xmlNodePtr * xsltTemplateProcess (xsltTransformContextPtr ctxt, xmlNodePtr node); xmlAttrPtr xsltAttrListTemplateProcess (xsltTransformContextPtr ctxt, diff --git a/libxslt/transform.c b/libxslt/transform.c index d8bd3d4..1b6b718 100644 --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -1132,9 +1132,7 @@ xsltSort(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltStylePreCompPtr comp) { xmlXPathObjectPtr *results = NULL; xmlNodeSetPtr list = NULL; - xmlXPathParserContextPtr xpathParserCtxt = NULL; - xmlXPathObjectPtr res, tmp; - const xmlChar *start; + xmlXPathObjectPtr res; int len = 0; int i; xmlNodePtr oldNode; @@ -1148,6 +1146,12 @@ xsltSort(xsltTransformContextPtr ctxt, xmlNodePtr node, return; if (comp->select == NULL) return; + if (comp->comp == NULL) { + comp->comp = xmlXPathCompile(comp->select); + if (comp->comp == NULL) + return; + } + list = ctxt->nodeList; if ((list == NULL) || (list->nodeNr <= 1)) @@ -1159,9 +1163,6 @@ xsltSort(xsltTransformContextPtr ctxt, xmlNodePtr node, /* TODO: xsl:sort case-order attribute */ - xpathParserCtxt = xmlXPathNewParserContext(comp->select, ctxt->xpathCtxt); - if (xpathParserCtxt == NULL) - goto error; results = xmlMalloc(len * sizeof(xmlXPathObjectPtr)); if (results == NULL) { xsltGenericError(xsltGenericErrorContext, @@ -1169,28 +1170,18 @@ xsltSort(xsltTransformContextPtr ctxt, xmlNodePtr node, goto error; } - start = xpathParserCtxt->cur; oldNode = ctxt->node; for (i = 0;i < len;i++) { - xpathParserCtxt->cur = start; ctxt->xpathCtxt->contextSize = len; ctxt->xpathCtxt->proximityPosition = i + 1; ctxt->node = list->nodeTab[i]; ctxt->xpathCtxt->node = ctxt->node; - xmlXPathEvalExpr(xpathParserCtxt); - xmlXPathRunEval(xpathParserCtxt); - xmlXPathStringFunction(xpathParserCtxt, 1); - if (comp->number) - xmlXPathNumberFunction(xpathParserCtxt, 1); - res = valuePop(xpathParserCtxt); - do { - tmp = valuePop(xpathParserCtxt); - if (tmp != NULL) { - xmlXPathFreeObject(tmp); - } - } while (tmp != NULL); - + res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt); if (res != NULL) { + if (res->type != XPATH_STRING) + res = xmlXPathConvertString(res); + if (comp->number) + res = xmlXPathConvertNumber(res); if (comp->number) { if (res->type == XPATH_NUMBER) { results[i] = res; @@ -1219,8 +1210,6 @@ xsltSort(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltSortFunction(list, &results[0], comp->descending, comp->number); error: - if (xpathParserCtxt != NULL) - xmlXPathFreeParserContext(xpathParserCtxt); if (results != NULL) { for (i = 0;i < len;i++) xmlXPathFreeObject(results[i]); @@ -1674,8 +1663,7 @@ error: void xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltStylePreCompPtr comp) { - xmlXPathObjectPtr res = NULL, tmp; - xmlXPathParserContextPtr xpathParserCtxt = NULL; + xmlXPathObjectPtr res = NULL; xmlNodePtr copy = NULL; xmlNodeSetPtr list = NULL; int i; @@ -1685,25 +1673,18 @@ xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node, if (comp->select == NULL) return; + if (comp->comp == NULL) { + comp->comp = xmlXPathCompile(comp->select); + if (comp->comp == NULL) + return; + } #ifdef DEBUG_PROCESS xsltGenericDebug(xsltGenericDebugContext, "xsltCopyOf: select %s\n", comp->select); #endif - xpathParserCtxt = - xmlXPathNewParserContext(comp->select, ctxt->xpathCtxt); - if (xpathParserCtxt == NULL) - goto error; ctxt->xpathCtxt->node = node; - xmlXPathEvalExpr(xpathParserCtxt); - xmlXPathRunEval(xpathParserCtxt); - res = valuePop(xpathParserCtxt); - do { - tmp = valuePop(xpathParserCtxt); - if (tmp != NULL) { - xmlXPathFreeObject(tmp); - } - } while (tmp != NULL); + res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt); if (res != NULL) { if (res->type == XPATH_NODESET) { list = res->nodesetval; @@ -1735,9 +1716,7 @@ xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node, } } else { /* convert to a string */ - valuePush(xpathParserCtxt, res); - xmlXPathStringFunction(xpathParserCtxt, 1); - res = valuePop(xpathParserCtxt); + res = xmlXPathConvertString(res); if ((res != NULL) && (res->type == XPATH_STRING)) { /* append content as text node */ copy = xmlNewText(res->stringval); @@ -1745,12 +1724,6 @@ xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlAddChild(ctxt->insert, copy); } } - do { - tmp = valuePop(xpathParserCtxt); - if (tmp != NULL) { - xmlXPathFreeObject(tmp); - } - } while (tmp != NULL); if (copy == NULL) { xsltGenericError(xsltGenericErrorContext, "xsltDefaultProcessOneNode: text copy failed\n"); @@ -1763,11 +1736,6 @@ xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node, } } -error: - if (xpathParserCtxt != NULL) { - xmlXPathFreeParserContext(xpathParserCtxt); - xpathParserCtxt = NULL; - } if (res != NULL) xmlXPathFreeObject(res); } @@ -1784,8 +1752,7 @@ error: void xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltStylePreCompPtr comp) { - xmlXPathObjectPtr res = NULL, tmp; - xmlXPathParserContextPtr xpathParserCtxt = NULL; + xmlXPathObjectPtr res = NULL; xmlNodePtr copy = NULL; if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL)) @@ -1793,28 +1760,22 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node, if (comp->select == NULL) return; + if (comp->comp == NULL) { + comp->comp = xmlXPathCompile(comp->select); + if (comp->comp == NULL) + return; + } #ifdef DEBUG_PROCESS xsltGenericDebug(xsltGenericDebugContext, "xsltValueOf: select %s\n", comp->select); #endif - xpathParserCtxt = - xmlXPathNewParserContext(comp->select, ctxt->xpathCtxt); - if (xpathParserCtxt == NULL) - goto error; ctxt->xpathCtxt->node = node; - xmlXPathEvalExpr(xpathParserCtxt); - xmlXPathRunEval(xpathParserCtxt); - xmlXPathStringFunction(xpathParserCtxt, 1); - res = valuePop(xpathParserCtxt); - do { - tmp = valuePop(xpathParserCtxt); - if (tmp != NULL) { - xmlXPathFreeObject(tmp); - } - } while (tmp != NULL); + res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt); if (res != NULL) { + if (res->type != XPATH_STRING) + res = xmlXPathConvertString(res); if (res->type == XPATH_STRING) { copy = xmlNewText(res->stringval); if (copy != NULL) { @@ -1833,11 +1794,6 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltGenericDebug(xsltGenericDebugContext, "xsltValueOf: result %s\n", res->stringval); #endif -error: - if (xpathParserCtxt != NULL) { - xmlXPathFreeParserContext(xpathParserCtxt); - xpathParserCtxt = NULL; - } if (res != NULL) xmlXPathFreeObject(res); } @@ -1968,9 +1924,8 @@ void xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltStylePreCompPtr comp) { xmlNodePtr cur, delete = NULL; - xmlXPathObjectPtr res = NULL, tmp; + xmlXPathObjectPtr res = NULL; xmlNodeSetPtr list = NULL, oldlist; - xmlXPathParserContextPtr xpathParserCtxt = NULL; int i, oldProximityPosition, oldContextSize; const xmlChar *oldmode, *oldmodeURI; int have_sort=0; @@ -1998,27 +1953,18 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node, ctxt->modeURI = comp->modeURI; if (comp->select != NULL) { + if (comp->comp == NULL) { + comp->comp = xmlXPathCompile(comp->select); + if (comp->comp == NULL) + goto error; + } #ifdef DEBUG_PROCESS xsltGenericDebug(xsltGenericDebugContext, "xsltApplyTemplates: select %s\n", comp->select); #endif - if (ctxt->xpathCtxt == NULL) { - } - xpathParserCtxt = - xmlXPathNewParserContext(comp->select, ctxt->xpathCtxt); - if (xpathParserCtxt == NULL) - goto error; ctxt->xpathCtxt->node = node; - xmlXPathEvalExpr(xpathParserCtxt); - xmlXPathRunEval(xpathParserCtxt); - res = valuePop(xpathParserCtxt); - do { - tmp = valuePop(xpathParserCtxt); - if (tmp != NULL) { - xmlXPathFreeObject(tmp); - } - } while (tmp != NULL); + res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt); if (res != NULL) { if (res->type == XPATH_NODESET) { list = res->nodesetval; @@ -2142,8 +2088,6 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node, error: ctxt->mode = oldmode; ctxt->modeURI = oldmodeURI; - if (xpathParserCtxt != NULL) - xmlXPathFreeParserContext(xpathParserCtxt); if (res != NULL) xmlXPathFreeObject(res); if (list != NULL) @@ -2164,8 +2108,7 @@ void xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltStylePreCompPtr comp) { xmlChar *prop = NULL; - xmlXPathObjectPtr res = NULL, tmp; - xmlXPathParserContextPtr xpathParserCtxt = NULL; + xmlXPathObjectPtr res = NULL; xmlNodePtr replacement, when; int doit = 1; @@ -2188,7 +2131,8 @@ xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr node, goto error; } while (IS_XSLT_ELEM(replacement) && (IS_XSLT_NAME(replacement, "when"))) { - + xmlXPathCompExprPtr comp; + /* TODO: build a precompiled block for when too ! */ when = replacement; prop = xmlGetNsProp(when, (const xmlChar *)"test", XSLT_NAMESPACE); if (prop == NULL) { @@ -2201,22 +2145,15 @@ xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr node, "xsl:when: test %s\n", prop); #endif - xpathParserCtxt = xmlXPathNewParserContext(prop, ctxt->xpathCtxt); - if (xpathParserCtxt == NULL) + comp = xmlXPathCompile(prop); + if (comp == NULL) goto error; ctxt->xpathCtxt->node = node; - xmlXPathEvalExpr(xpathParserCtxt); - xmlXPathRunEval(xpathParserCtxt); - xmlXPathBooleanFunction(xpathParserCtxt, 1); - res = valuePop(xpathParserCtxt); - do { - tmp = valuePop(xpathParserCtxt); - if (tmp != NULL) { - xmlXPathFreeObject(tmp); - } - } while (tmp != NULL); - + res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt); + xmlXPathFreeCompExpr(comp); if (res != NULL) { + if (res->type != XPATH_BOOLEAN) + res = xmlXPathConvertBoolean(res); if (res->type == XPATH_BOOLEAN) doit = res->boolval; else { @@ -2238,9 +2175,6 @@ xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltFreeStackElemList(varsPop(ctxt)); goto done; } - if (xpathParserCtxt != NULL) - xmlXPathFreeParserContext(xpathParserCtxt); - xpathParserCtxt = NULL; if (prop != NULL) xmlFree(prop); prop = NULL; @@ -2267,8 +2201,6 @@ xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr node, done: error: - if (xpathParserCtxt != NULL) - xmlXPathFreeParserContext(xpathParserCtxt); if (prop != NULL) xmlFree(prop); if (res != NULL) @@ -2287,8 +2219,7 @@ error: void xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltStylePreCompPtr comp) { - xmlXPathObjectPtr res = NULL, tmp; - xmlXPathParserContextPtr xpathParserCtxt = NULL; + xmlXPathObjectPtr res = NULL; int doit = 1; if (comp == NULL) { @@ -2300,28 +2231,22 @@ xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr node, if (comp->test == NULL) return; + if (comp->comp == NULL) { + comp->comp = xmlXPathCompile(comp->test); + if (comp->comp == NULL) + return; + } #ifdef DEBUG_PROCESS xsltGenericDebug(xsltGenericDebugContext, "xsltIf: test %s\n", comp->test); #endif - xpathParserCtxt = xmlXPathNewParserContext(comp->test, ctxt->xpathCtxt); - if (xpathParserCtxt == NULL) - goto error; ctxt->xpathCtxt->node = node; - xmlXPathEvalExpr(xpathParserCtxt); - xmlXPathRunEval(xpathParserCtxt); - xmlXPathBooleanFunction(xpathParserCtxt, 1); - res = valuePop(xpathParserCtxt); - do { - tmp = valuePop(xpathParserCtxt); - if (tmp != NULL) { - xmlXPathFreeObject(tmp); - } - } while (tmp != NULL); - + res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt); if (res != NULL) { + if (res->type != XPATH_BOOLEAN) + res = xmlXPathConvertBoolean(res); if (res->type == XPATH_BOOLEAN) doit = res->boolval; else { @@ -2344,8 +2269,6 @@ xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr node, } error: - if (xpathParserCtxt != NULL) - xmlXPathFreeParserContext(xpathParserCtxt); if (res != NULL) xmlXPathFreeObject(res); } @@ -2362,10 +2285,9 @@ error: void xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltStylePreCompPtr comp) { - xmlXPathObjectPtr res = NULL, tmp; + xmlXPathObjectPtr res = NULL; xmlNodePtr replacement; xmlNodeSetPtr list = NULL, oldlist; - xmlXPathParserContextPtr xpathParserCtxt = NULL; int i, oldProximityPosition, oldContextSize; /* xmlNodePtr oldInsert = ctxt->insert; */ xmlNodePtr oldNode = ctxt->node; @@ -2379,26 +2301,19 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node, if (comp->select == NULL) return; + if (comp->comp == NULL) { + comp->comp = xmlXPathCompile(comp->select); + if (comp->comp == NULL) + return; + } #ifdef DEBUG_PROCESS xsltGenericDebug(xsltGenericDebugContext, "xsltForEach: select %s\n", comp->select); #endif - xpathParserCtxt = xmlXPathNewParserContext(comp->select, ctxt->xpathCtxt); - if (xpathParserCtxt == NULL) - goto error; ctxt->xpathCtxt->node = node; - xmlXPathEvalExpr(xpathParserCtxt); - xmlXPathRunEval(xpathParserCtxt); - res = valuePop(xpathParserCtxt); - do { - tmp = valuePop(xpathParserCtxt); - if (tmp != NULL) { - xmlXPathFreeObject(tmp); - } - } while (tmp != NULL); - + res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt); if (res != NULL) { if (res->type == XPATH_NODESET) list = res->nodesetval; @@ -2445,8 +2360,6 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node, ctxt->xpathCtxt->proximityPosition = oldProximityPosition; error: - if (xpathParserCtxt != NULL) - xmlXPathFreeParserContext(xpathParserCtxt); if (res != NULL) xmlXPathFreeObject(res); } diff --git a/libxslt/variables.c b/libxslt/variables.c index 3d33e2b..c47c0dd 100644 --- a/libxslt/variables.c +++ b/libxslt/variables.c @@ -243,9 +243,7 @@ xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name, * Returns 0 in case of success, -1 in case of error */ int -xsltEvalVariables(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) { - xmlXPathParserContextPtr xpathParserCtxt; - +xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) { if ((ctxt == NULL) || (elem == NULL)) return(-1); @@ -254,30 +252,19 @@ xsltEvalVariables(xsltTransformContextPtr ctxt, xsltStackElemPtr elem) { "Evaluating variable %s\n", elem->name); #endif if (elem->select != NULL) { - xmlXPathObjectPtr result, tmp; + xmlXPathCompExprPtr comp; + xmlXPathObjectPtr result; - xpathParserCtxt = xmlXPathNewParserContext(elem->select, - ctxt->xpathCtxt); - if (xpathParserCtxt == NULL) + comp = xmlXPathCompile(elem->select); + if (comp == NULL) return(-1); ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node; - xmlXPathEvalExpr(xpathParserCtxt); - xmlXPathRunEval(xpathParserCtxt); - result = valuePop(xpathParserCtxt); - do { - tmp = valuePop(xpathParserCtxt); - if (tmp != NULL) { - xmlXPathFreeObject(tmp); - } - } while (tmp != NULL); - + result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt); + xmlXPathFreeCompExpr(comp); if (result == NULL) { xsltGenericError(xsltGenericErrorContext, "Evaluating global variable %s failed\n"); - } - if (xpathParserCtxt != NULL) - xmlXPathFreeParserContext(xpathParserCtxt); - if (result != NULL) { + } else { #ifdef DEBUG_VARIABLE #ifdef LIBXML_DEBUG_ENABLED if ((xsltGenericDebugContext == stdout) || @@ -359,7 +346,7 @@ xsltEvalGlobalVariables(xsltTransformContextPtr ctxt) { elem = style->variables; while (elem != NULL) { - xsltEvalVariables(ctxt, elem); + xsltEvalVariable(ctxt, elem); elem = elem->next; } @@ -463,7 +450,7 @@ xsltBuildVariable(xsltTransformContextPtr ctxt, const xmlChar *name, if (ns_uri) elem->nameURI = xmlStrdup(ns_uri); elem->tree = tree; - xsltEvalVariables(ctxt, elem); + xsltEvalVariable(ctxt, elem); return(elem); } @@ -554,7 +541,7 @@ xsltGlobalVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name, xsltGenericDebug(xsltGenericDebugContext, "uncomputed global variable %s\n", name); #endif - xsltEvalVariables(ctxt, elem); + xsltEvalVariable(ctxt, elem); } if (elem->value != NULL) return(xmlXPathObjectCopy(elem->value)); @@ -593,7 +580,7 @@ xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name, xsltGenericDebug(xsltGenericDebugContext, "uncomputed variable %s\n", name); #endif - xsltEvalVariables(ctxt, elem); + xsltEvalVariable(ctxt, elem); } if (elem->value != NULL) return(xmlXPathObjectCopy(elem->value)); diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h index 77eb428..4893fee 100644 --- a/libxslt/xsltInternals.h +++ b/libxslt/xsltInternals.h @@ -257,6 +257,8 @@ struct _xsltStylePreComp { xmlChar *filename; /* document URL */ xsltNumberData numdata; /* number */ + + xmlXPathCompExprPtr comp; /* a precompiled XPath expression */ }; /* diff --git a/libxslt/xsltutils.h b/libxslt/xsltutils.h index 966ec76..44238e5 100644 --- a/libxslt/xsltutils.h +++ b/libxslt/xsltutils.h @@ -23,7 +23,6 @@ extern "C" { int xmlXPathIsNodeType(const xmlChar *name); xmlChar *xmlSplitQName2(const xmlChar *name, xmlChar **prefix); void xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs); -void xmlXPathRunEval(xmlXPathParserContextPtr ctxt); /********* void xmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt, xmlXPathVariableLookupFunc f, void *data)