Switched all the processing to compiled XPath form, there is a
authorDaniel Veillard <veillard@src.gnome.org>
Mon, 19 Mar 2001 17:52:26 +0000 (17:52 +0000)
committerDaniel Veillard <veillard@src.gnome.org>
Mon, 19 Mar 2001 17:52:26 +0000 (17:52 +0000)
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

ChangeLog
libxslt/functions.c
libxslt/keys.c
libxslt/pattern.c
libxslt/preproc.c
libxslt/templates.c
libxslt/templates.h
libxslt/transform.c
libxslt/variables.c
libxslt/xsltInternals.h
libxslt/xsltutils.h

index eef15e0..3686022 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Mon Mar 19 18:40:40 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+       * 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 <Daniel.Veillard@imag.fr>
 
        * libxslt/keys.c libxslt/templates.c libxslt/transform.c
index c6c0a93..6966750 100644 (file)
@@ -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];
index fd2f6c3..ca53107 100644 (file)
@@ -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);
 }
index 787db93..0a07ed0 100644 (file)
@@ -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)
index 1476aea..1bb3079 100644 (file)
@@ -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));
 
index 14e1640..23e3a3e 100644 (file)
@@ -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
  * 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);
index be2f6c0..93294f6 100644 (file)
@@ -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,
index d8bd3d4..1b6b718 100644 (file)
@@ -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);
 }
index 3d33e2b..c47c0dd 100644 (file)
@@ -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));
index 77eb428..4893fee 100644 (file)
@@ -257,6 +257,8 @@ struct _xsltStylePreComp {
     xmlChar *filename;         /* document URL */
 
     xsltNumberData numdata;    /* number */
+
+    xmlXPathCompExprPtr comp;  /* a precompiled XPath expression */
 };
 
 /*
index 966ec76..44238e5 100644 (file)
@@ -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)