Committing again, since I forgot to switch from win to linux linebreaks in
authorKasimier T. Buchcik <kbuchcik@src.gnome.org>
Fri, 14 Jul 2006 16:18:32 +0000 (16:18 +0000)
committerKasimier T. Buchcik <kbuchcik@src.gnome.org>
Fri, 14 Jul 2006 16:18:32 +0000 (16:18 +0000)
* libxslt/attributes.c libxslt/documents.c
  libxslt/functions.c libxslt/keys.c libxslt/namespaces.c
  libxslt/pattern.c libxslt/preproc.c libxslt/templates.c
  libxslt/templates.h libxslt/transform.c
  libxslt/variables.c libxslt/xslt.c
  libxslt/xsltInternals.h libxslt/xsltutils.c
  libxslt/xsltutils.h libexslt/common.c libexslt/dynamic.c
  libexslt/functions.c libexslt/strings.c:
  Committing again, since I forgot to switch from win to linux
  linebreaks in the files.

20 files changed:
ChangeLog
libexslt/common.c
libexslt/dynamic.c
libexslt/functions.c
libexslt/strings.c
libxslt/attributes.c
libxslt/documents.c
libxslt/functions.c
libxslt/keys.c
libxslt/namespaces.c
libxslt/pattern.c
libxslt/preproc.c
libxslt/templates.c
libxslt/templates.h
libxslt/transform.c
libxslt/variables.c
libxslt/xslt.c
libxslt/xsltInternals.h
libxslt/xsltutils.c
libxslt/xsltutils.h

index 625f593..ca84632 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Fri Jul 14 18:16:59 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
+
+       * libxslt/attributes.c libxslt/documents.c
+         libxslt/functions.c libxslt/keys.c libxslt/namespaces.c
+         libxslt/pattern.c libxslt/preproc.c libxslt/templates.c
+         libxslt/templates.h libxslt/transform.c
+         libxslt/variables.c libxslt/xslt.c
+         libxslt/xsltInternals.h libxslt/xsltutils.c
+         libxslt/xsltutils.h libexslt/common.c libexslt/dynamic.c
+         libexslt/functions.c libexslt/strings.c:
+         Committing again, since I forgot to switch from win to linux
+         linebreaks in the files.
+                                                   
 Fri Jul 14 17:55:42 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
 
        * libxslt/attributes.c libxslt/documents.c
index 7b07ea2..ba57fa5 100644 (file)
-#define IN_LIBEXSLT\r
-#include "libexslt/libexslt.h"\r
-\r
-#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)\r
-#include <win32config.h>\r
-#else\r
-#include "config.h"\r
-#endif\r
-\r
-#include <libxml/tree.h>\r
-#include <libxml/xpath.h>\r
-#include <libxml/xpathInternals.h>\r
-\r
-#include <libxslt/xsltconfig.h>\r
-#include <libxslt/xsltutils.h>\r
-#include <libxslt/xsltInternals.h>\r
-#include <libxslt/extensions.h>\r
-#include <libxslt/transform.h>\r
-#include <libxslt/extra.h>\r
-#include <libxslt/preproc.h>\r
-\r
-#include "exslt.h"\r
-\r
-static void\r
-exsltNodeSetFunction (xmlXPathParserContextPtr ctxt, int nargs) {\r
-    if (nargs != 1) {\r
-       xmlXPathSetArityError(ctxt);\r
-       return;\r
-    }\r
-    if (xmlXPathStackIsNodeSet (ctxt)) {\r
-       xsltFunctionNodeSet (ctxt, nargs);\r
-       return;\r
-    } else {\r
-       xmlDocPtr fragment;\r
-       xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);\r
-       xmlNodePtr txt;\r
-       xmlChar *strval;\r
-       xmlXPathObjectPtr obj;\r
-       /*\r
-       * SPEC EXSLT:\r
-       * "You can also use this function to turn a string into a text\r
-       * node, which is helpful if you want to pass a string to a\r
-       * function that only accepts a node-set."\r
-       */\r
-       fragment = xsltCreateRVT(tctxt);\r
-       if (fragment == NULL) {\r
-           xsltTransformError(tctxt, NULL, tctxt->inst,\r
-               "exsltNodeSetFunction: Failed to create a tree fragment.\n");\r
-           tctxt->state = XSLT_STATE_STOPPED; \r
-           return;\r
-       }\r
-       xsltRegisterLocalRVT(tctxt, fragment);\r
-\r
-       strval = xmlXPathPopString (ctxt);\r
-       \r
-       txt = xmlNewDocText (fragment, strval);\r
-       xmlAddChild((xmlNodePtr) fragment, txt);\r
-       obj = xmlXPathNewNodeSet(txt);  \r
-       if (obj == NULL) {\r
-           xsltTransformError(tctxt, NULL, tctxt->inst,\r
-               "exsltNodeSetFunction: Failed to create a node set object.\n");\r
-           tctxt->state = XSLT_STATE_STOPPED;\r
-       }\r
-       if (strval != NULL)\r
-           xmlFree (strval);\r
-       \r
-       valuePush (ctxt, obj);\r
-    }\r
-}\r
-\r
-static void\r
-exsltObjectTypeFunction (xmlXPathParserContextPtr ctxt, int nargs) {\r
-    xmlXPathObjectPtr obj, ret;\r
-\r
-    if (nargs != 1) {\r
-       xmlXPathSetArityError(ctxt);\r
-       return;\r
-    }\r
-\r
-    obj = valuePop(ctxt);\r
-\r
-    switch (obj->type) {\r
-    case XPATH_STRING:\r
-       ret = xmlXPathNewCString("string");\r
-       break;\r
-    case XPATH_NUMBER:\r
-       ret = xmlXPathNewCString("number");\r
-       break;\r
-    case XPATH_BOOLEAN:\r
-       ret = xmlXPathNewCString("boolean");\r
-       break;\r
-    case XPATH_NODESET:\r
-       ret = xmlXPathNewCString("node-set");\r
-       break;\r
-    case XPATH_XSLT_TREE:\r
-       ret = xmlXPathNewCString("RTF");\r
-       break;\r
-    case XPATH_USERS:\r
-       ret = xmlXPathNewCString("external");\r
-       break;\r
-    default:\r
-       xsltGenericError(xsltGenericErrorContext,\r
-               "object-type() invalid arg\n");\r
-       ctxt->error = XPATH_INVALID_TYPE;\r
-       xmlXPathFreeObject(obj);\r
-       return;\r
-    }\r
-    xmlXPathFreeObject(obj);\r
-    valuePush(ctxt, ret);\r
-}\r
-\r
-\r
-/**\r
- * exsltCommonRegister:\r
- *\r
- * Registers the EXSLT - Common module\r
- */\r
-\r
-void\r
-exsltCommonRegister (void) {\r
-    xsltRegisterExtModuleFunction((const xmlChar *) "node-set",\r
-                                 EXSLT_COMMON_NAMESPACE,\r
-                                 exsltNodeSetFunction);\r
-    xsltRegisterExtModuleFunction((const xmlChar *) "object-type",\r
-                                 EXSLT_COMMON_NAMESPACE,\r
-                                 exsltObjectTypeFunction);\r
-    xsltRegisterExtModuleElement((const xmlChar *) "document",\r
-                                EXSLT_COMMON_NAMESPACE,\r
-                                (xsltPreComputeFunction) xsltDocumentComp,\r
-                                (xsltTransformFunction) xsltDocumentElem);\r
-}\r
+#define IN_LIBEXSLT
+#include "libexslt/libexslt.h"
+
+#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
+#include <win32config.h>
+#else
+#include "config.h"
+#endif
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <libxslt/xsltconfig.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/extensions.h>
+#include <libxslt/transform.h>
+#include <libxslt/extra.h>
+#include <libxslt/preproc.h>
+
+#include "exslt.h"
+
+static void
+exsltNodeSetFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+    if (nargs != 1) {
+       xmlXPathSetArityError(ctxt);
+       return;
+    }
+    if (xmlXPathStackIsNodeSet (ctxt)) {
+       xsltFunctionNodeSet (ctxt, nargs);
+       return;
+    } else {
+       xmlDocPtr fragment;
+       xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
+       xmlNodePtr txt;
+       xmlChar *strval;
+       xmlXPathObjectPtr obj;
+       /*
+       * SPEC EXSLT:
+       * "You can also use this function to turn a string into a text
+       * node, which is helpful if you want to pass a string to a
+       * function that only accepts a node-set."
+       */
+       fragment = xsltCreateRVT(tctxt);
+       if (fragment == NULL) {
+           xsltTransformError(tctxt, NULL, tctxt->inst,
+               "exsltNodeSetFunction: Failed to create a tree fragment.\n");
+           tctxt->state = XSLT_STATE_STOPPED; 
+           return;
+       }
+       xsltRegisterLocalRVT(tctxt, fragment);
+
+       strval = xmlXPathPopString (ctxt);
+       
+       txt = xmlNewDocText (fragment, strval);
+       xmlAddChild((xmlNodePtr) fragment, txt);
+       obj = xmlXPathNewNodeSet(txt);  
+       if (obj == NULL) {
+           xsltTransformError(tctxt, NULL, tctxt->inst,
+               "exsltNodeSetFunction: Failed to create a node set object.\n");
+           tctxt->state = XSLT_STATE_STOPPED;
+       }
+       if (strval != NULL)
+           xmlFree (strval);
+       
+       valuePush (ctxt, obj);
+    }
+}
+
+static void
+exsltObjectTypeFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+    xmlXPathObjectPtr obj, ret;
+
+    if (nargs != 1) {
+       xmlXPathSetArityError(ctxt);
+       return;
+    }
+
+    obj = valuePop(ctxt);
+
+    switch (obj->type) {
+    case XPATH_STRING:
+       ret = xmlXPathNewCString("string");
+       break;
+    case XPATH_NUMBER:
+       ret = xmlXPathNewCString("number");
+       break;
+    case XPATH_BOOLEAN:
+       ret = xmlXPathNewCString("boolean");
+       break;
+    case XPATH_NODESET:
+       ret = xmlXPathNewCString("node-set");
+       break;
+    case XPATH_XSLT_TREE:
+       ret = xmlXPathNewCString("RTF");
+       break;
+    case XPATH_USERS:
+       ret = xmlXPathNewCString("external");
+       break;
+    default:
+       xsltGenericError(xsltGenericErrorContext,
+               "object-type() invalid arg\n");
+       ctxt->error = XPATH_INVALID_TYPE;
+       xmlXPathFreeObject(obj);
+       return;
+    }
+    xmlXPathFreeObject(obj);
+    valuePush(ctxt, ret);
+}
+
+
+/**
+ * exsltCommonRegister:
+ *
+ * Registers the EXSLT - Common module
+ */
+
+void
+exsltCommonRegister (void) {
+    xsltRegisterExtModuleFunction((const xmlChar *) "node-set",
+                                 EXSLT_COMMON_NAMESPACE,
+                                 exsltNodeSetFunction);
+    xsltRegisterExtModuleFunction((const xmlChar *) "object-type",
+                                 EXSLT_COMMON_NAMESPACE,
+                                 exsltObjectTypeFunction);
+    xsltRegisterExtModuleElement((const xmlChar *) "document",
+                                EXSLT_COMMON_NAMESPACE,
+                                (xsltPreComputeFunction) xsltDocumentComp,
+                                (xsltTransformFunction) xsltDocumentElem);
+}
index 87ef8da..11c291b 100644 (file)
-/*\r
- * dynamic.c: Implementation of the EXSLT -- Dynamic module\r
- *\r
- * References:\r
- *   http://www.exslt.org/dyn/dyn.html\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * Authors:\r
- *   Mark Vakoc <mark_vakoc@jdedwards.com>\r
- *   Thomas Broyer <tbroyer@ltgt.net>\r
- *\r
- * TODO:\r
- * elements:\r
- * functions:\r
- *    min\r
- *    max\r
- *    sum\r
- *    map\r
- *    closure\r
- */\r
-\r
-#define IN_LIBEXSLT\r
-#include "libexslt/libexslt.h"\r
-\r
-#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)\r
-#include <win32config.h>\r
-#else\r
-#include "config.h"\r
-#endif\r
-\r
-#include <libxml/tree.h>\r
-#include <libxml/xpath.h>\r
-#include <libxml/xpathInternals.h>\r
-\r
-#include <libxslt/xsltconfig.h>\r
-#include <libxslt/xsltutils.h>\r
-#include <libxslt/xsltInternals.h>\r
-#include <libxslt/extensions.h>\r
-\r
-#include "exslt.h"\r
-\r
-/**\r
- * exsltDynEvaluateFunction:\r
- * @ctxt:  an XPath parser context\r
- * @nargs:  the number of arguments\r
- *\r
- * Evaluates the string as an XPath expression and returns the result\r
- * value, which may be a boolean, number, string, node set, result tree\r
- * fragment or external object.\r
- */\r
-\r
-static void\r
-exsltDynEvaluateFunction(xmlXPathParserContextPtr ctxt, int nargs) {\r
-       xmlChar *str = NULL;\r
-       xmlXPathObjectPtr ret = NULL;\r
-\r
-       if (ctxt == NULL)\r
-               return;\r
-       if (nargs != 1) {\r
-               xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);\r
-        xsltGenericError(xsltGenericErrorContext,\r
-                       "dyn:evalute() : invalid number of args %d\n", nargs);\r
-               ctxt->error = XPATH_INVALID_ARITY;\r
-               return;\r
-       }\r
-       str = xmlXPathPopString(ctxt);\r
-       /* return an empty node-set if an empty string is passed in */\r
-       if (!str||!xmlStrlen(str)) {\r
-               if (str) xmlFree(str);\r
-               valuePush(ctxt,xmlXPathNewNodeSet(NULL));\r
-               return;\r
-       }\r
-       ret = xmlXPathEval(str,ctxt->context);\r
-       if (ret)\r
-               valuePush(ctxt,ret);\r
-       else {\r
-               xsltGenericError(xsltGenericErrorContext,\r
-                       "dyn:evaluate() : unable to evaluate expression '%s'\n",str);\r
-               valuePush(ctxt,xmlXPathNewNodeSet(NULL));\r
-       }       \r
-       xmlFree(str);\r
-       return;\r
-}\r
-\r
-/**\r
- * exsltDynMapFunction:\r
- * @ctxt:  an XPath parser context\r
- * @nargs:  the number of arguments\r
- *\r
- * Evaluates the string as an XPath expression and returns the result\r
- * value, which may be a boolean, number, string, node set, result tree\r
- * fragment or external object.\r
- */\r
-\r
-static void\r
-exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs)\r
-{\r
-    xmlChar *str = NULL;\r
-    xmlNodeSetPtr nodeset = NULL;\r
-    xmlXPathCompExprPtr comp = NULL;\r
-    xmlXPathObjectPtr ret = NULL;\r
-    xmlDocPtr oldDoc, container;\r
-    xmlNodePtr oldNode;\r
-    int oldContextSize;\r
-    int oldProximityPosition;\r
-    int i, j;\r
-\r
-\r
-    if (nargs != 2) {\r
-        xmlXPathSetArityError(ctxt);\r
-        return;\r
-    }\r
-    str = xmlXPathPopString(ctxt);\r
-    if (xmlXPathCheckError(ctxt)) {\r
-        xmlXPathSetTypeError(ctxt);\r
-        return;\r
-    }\r
-\r
-    nodeset = xmlXPathPopNodeSet(ctxt);\r
-    if (xmlXPathCheckError(ctxt)) {\r
-        xmlXPathSetTypeError(ctxt);\r
-        return;\r
-    }\r
-    if (str == NULL || !xmlStrlen(str) || !(comp = xmlXPathCompile(str))) {\r
-        if (nodeset != NULL)\r
-            xmlXPathFreeNodeSet(nodeset);\r
-        if (str != NULL)\r
-            xmlFree(str);\r
-        valuePush(ctxt, xmlXPathNewNodeSet(NULL));\r
-        return;\r
-    }\r
-\r
-    ret = xmlXPathNewNodeSet(NULL);\r
-    if (ret == NULL) {\r
-        xsltGenericError(xsltGenericErrorContext,\r
-                         "exsltDynMapFunctoin: ret == NULL\n");\r
-        goto cleanup;\r
-    }\r
-\r
-    oldDoc = ctxt->context->doc;\r
-    oldNode = ctxt->context->node;\r
-    oldContextSize = ctxt->context->contextSize;\r
-    oldProximityPosition = ctxt->context->proximityPosition;\r
-\r
-        /** \r
-        * since we really don't know we're going to be adding node(s) \r
-        * down the road we create the RVT regardless \r
-        */\r
-    container = xsltCreateRVT(xsltXPathGetTransformContext(ctxt));\r
-    if (container != NULL)\r
-        xsltRegisterLocalRVT(xsltXPathGetTransformContext(ctxt), container);\r
-\r
-    if (nodeset && nodeset->nodeNr > 0) {\r
-        xmlXPathNodeSetSort(nodeset);\r
-        ctxt->context->contextSize = nodeset->nodeNr;\r
-        ctxt->context->proximityPosition = 0;\r
-        for (i = 0; i < nodeset->nodeNr; i++) {\r
-            xmlXPathObjectPtr subResult = NULL;\r
-\r
-            ctxt->context->proximityPosition++;\r
-            ctxt->context->node = nodeset->nodeTab[i];\r
-            ctxt->context->doc = nodeset->nodeTab[i]->doc;\r
-\r
-            subResult = xmlXPathCompiledEval(comp, ctxt->context);\r
-            if (subResult != NULL) {\r
-                switch (subResult->type) {\r
-                    case XPATH_NODESET:\r
-                        if (subResult->nodesetval != NULL)\r
-                            for (j = 0; j < subResult->nodesetval->nodeNr;\r
-                                 j++)\r
-                                xmlXPathNodeSetAdd(ret->nodesetval,\r
-                                                   subResult->nodesetval->\r
-                                                   nodeTab[j]);\r
-                        break;\r
-                    case XPATH_BOOLEAN:\r
-                        if (container != NULL) {\r
-                            xmlNodePtr cur =\r
-                                xmlNewChild((xmlNodePtr) container, NULL,\r
-                                            BAD_CAST "boolean",\r
-                                            BAD_CAST (subResult->\r
-                                            boolval ? "true" : ""));\r
-                            if (cur != NULL) {\r
-                                cur->ns =\r
-                                    xmlNewNs(cur,\r
-                                             BAD_CAST\r
-                                             "http://exslt.org/common",\r
-                                             BAD_CAST "exsl");\r
-                                xmlXPathNodeSetAddUnique(ret->nodesetval,\r
-                                                         cur);\r
-                            }\r
-                        }\r
-                        break;\r
-                    case XPATH_NUMBER:\r
-                        if (container != NULL) {\r
-                            xmlChar *val =\r
-                                xmlXPathCastNumberToString(subResult->\r
-                                                           floatval);\r
-                            xmlNodePtr cur =\r
-                                xmlNewChild((xmlNodePtr) container, NULL,\r
-                                            BAD_CAST "number", val);\r
-                            if (val != NULL)\r
-                                xmlFree(val);\r
-\r
-                            if (cur != NULL) {\r
-                                cur->ns =\r
-                                    xmlNewNs(cur,\r
-                                             BAD_CAST\r
-                                             "http://exslt.org/common",\r
-                                             BAD_CAST "exsl");\r
-                                xmlXPathNodeSetAddUnique(ret->nodesetval,\r
-                                                         cur);\r
-                            }\r
-                        }\r
-                        break;\r
-                    case XPATH_STRING:\r
-                        if (container != NULL) {\r
-                            xmlNodePtr cur =\r
-                                xmlNewChild((xmlNodePtr) container, NULL,\r
-                                            BAD_CAST "string",\r
-                                            subResult->stringval);\r
-                            if (cur != NULL) {\r
-                                cur->ns =\r
-                                    xmlNewNs(cur,\r
-                                             BAD_CAST\r
-                                             "http://exslt.org/common",\r
-                                             BAD_CAST "exsl");\r
-                                xmlXPathNodeSetAddUnique(ret->nodesetval,\r
-                                                         cur);\r
-                            }\r
-                        }\r
-                        break;\r
-                   default:\r
-                        break;\r
-                }\r
-                xmlXPathFreeObject(subResult);\r
-            }\r
-        }\r
-    }\r
-    ctxt->context->doc = oldDoc;\r
-    ctxt->context->node = oldNode;\r
-    ctxt->context->contextSize = oldContextSize;\r
-    ctxt->context->proximityPosition = oldProximityPosition;\r
-\r
-\r
-  cleanup:\r
-    /* restore the xpath context */\r
-    if (comp != NULL)\r
-        xmlXPathFreeCompExpr(comp);\r
-    if (nodeset != NULL)\r
-        xmlXPathFreeNodeSet(nodeset);\r
-    if (str != NULL)\r
-        xmlFree(str);\r
-    valuePush(ctxt, ret);\r
-    return;\r
-}\r
-\r
-\r
-/**\r
- * exsltDynRegister:\r
- *\r
- * Registers the EXSLT - Dynamic module\r
- */\r
-\r
-void\r
-exsltDynRegister (void) {\r
-    xsltRegisterExtModuleFunction ((const xmlChar *) "evaluate",\r
-                                  EXSLT_DYNAMIC_NAMESPACE,\r
-                                  exsltDynEvaluateFunction);\r
-  xsltRegisterExtModuleFunction ((const xmlChar *) "map",\r
-                                  EXSLT_DYNAMIC_NAMESPACE,\r
-                                  exsltDynMapFunction);\r
-\r
-}\r
+/*
+ * dynamic.c: Implementation of the EXSLT -- Dynamic module
+ *
+ * References:
+ *   http://www.exslt.org/dyn/dyn.html
+ *
+ * See Copyright for the status of this software.
+ *
+ * Authors:
+ *   Mark Vakoc <mark_vakoc@jdedwards.com>
+ *   Thomas Broyer <tbroyer@ltgt.net>
+ *
+ * TODO:
+ * elements:
+ * functions:
+ *    min
+ *    max
+ *    sum
+ *    map
+ *    closure
+ */
+
+#define IN_LIBEXSLT
+#include "libexslt/libexslt.h"
+
+#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
+#include <win32config.h>
+#else
+#include "config.h"
+#endif
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <libxslt/xsltconfig.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/extensions.h>
+
+#include "exslt.h"
+
+/**
+ * exsltDynEvaluateFunction:
+ * @ctxt:  an XPath parser context
+ * @nargs:  the number of arguments
+ *
+ * Evaluates the string as an XPath expression and returns the result
+ * value, which may be a boolean, number, string, node set, result tree
+ * fragment or external object.
+ */
+
+static void
+exsltDynEvaluateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
+       xmlChar *str = NULL;
+       xmlXPathObjectPtr ret = NULL;
+
+       if (ctxt == NULL)
+               return;
+       if (nargs != 1) {
+               xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
+        xsltGenericError(xsltGenericErrorContext,
+                       "dyn:evalute() : invalid number of args %d\n", nargs);
+               ctxt->error = XPATH_INVALID_ARITY;
+               return;
+       }
+       str = xmlXPathPopString(ctxt);
+       /* return an empty node-set if an empty string is passed in */
+       if (!str||!xmlStrlen(str)) {
+               if (str) xmlFree(str);
+               valuePush(ctxt,xmlXPathNewNodeSet(NULL));
+               return;
+       }
+       ret = xmlXPathEval(str,ctxt->context);
+       if (ret)
+               valuePush(ctxt,ret);
+       else {
+               xsltGenericError(xsltGenericErrorContext,
+                       "dyn:evaluate() : unable to evaluate expression '%s'\n",str);
+               valuePush(ctxt,xmlXPathNewNodeSet(NULL));
+       }       
+       xmlFree(str);
+       return;
+}
+
+/**
+ * exsltDynMapFunction:
+ * @ctxt:  an XPath parser context
+ * @nargs:  the number of arguments
+ *
+ * Evaluates the string as an XPath expression and returns the result
+ * value, which may be a boolean, number, string, node set, result tree
+ * fragment or external object.
+ */
+
+static void
+exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+    xmlChar *str = NULL;
+    xmlNodeSetPtr nodeset = NULL;
+    xmlXPathCompExprPtr comp = NULL;
+    xmlXPathObjectPtr ret = NULL;
+    xmlDocPtr oldDoc, container;
+    xmlNodePtr oldNode;
+    int oldContextSize;
+    int oldProximityPosition;
+    int i, j;
+
+
+    if (nargs != 2) {
+        xmlXPathSetArityError(ctxt);
+        return;
+    }
+    str = xmlXPathPopString(ctxt);
+    if (xmlXPathCheckError(ctxt)) {
+        xmlXPathSetTypeError(ctxt);
+        return;
+    }
+
+    nodeset = xmlXPathPopNodeSet(ctxt);
+    if (xmlXPathCheckError(ctxt)) {
+        xmlXPathSetTypeError(ctxt);
+        return;
+    }
+    if (str == NULL || !xmlStrlen(str) || !(comp = xmlXPathCompile(str))) {
+        if (nodeset != NULL)
+            xmlXPathFreeNodeSet(nodeset);
+        if (str != NULL)
+            xmlFree(str);
+        valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+        return;
+    }
+
+    ret = xmlXPathNewNodeSet(NULL);
+    if (ret == NULL) {
+        xsltGenericError(xsltGenericErrorContext,
+                         "exsltDynMapFunctoin: ret == NULL\n");
+        goto cleanup;
+    }
+
+    oldDoc = ctxt->context->doc;
+    oldNode = ctxt->context->node;
+    oldContextSize = ctxt->context->contextSize;
+    oldProximityPosition = ctxt->context->proximityPosition;
+
+        /** 
+        * since we really don't know we're going to be adding node(s) 
+        * down the road we create the RVT regardless 
+        */
+    container = xsltCreateRVT(xsltXPathGetTransformContext(ctxt));
+    if (container != NULL)
+        xsltRegisterLocalRVT(xsltXPathGetTransformContext(ctxt), container);
+
+    if (nodeset && nodeset->nodeNr > 0) {
+        xmlXPathNodeSetSort(nodeset);
+        ctxt->context->contextSize = nodeset->nodeNr;
+        ctxt->context->proximityPosition = 0;
+        for (i = 0; i < nodeset->nodeNr; i++) {
+            xmlXPathObjectPtr subResult = NULL;
+
+            ctxt->context->proximityPosition++;
+            ctxt->context->node = nodeset->nodeTab[i];
+            ctxt->context->doc = nodeset->nodeTab[i]->doc;
+
+            subResult = xmlXPathCompiledEval(comp, ctxt->context);
+            if (subResult != NULL) {
+                switch (subResult->type) {
+                    case XPATH_NODESET:
+                        if (subResult->nodesetval != NULL)
+                            for (j = 0; j < subResult->nodesetval->nodeNr;
+                                 j++)
+                                xmlXPathNodeSetAdd(ret->nodesetval,
+                                                   subResult->nodesetval->
+                                                   nodeTab[j]);
+                        break;
+                    case XPATH_BOOLEAN:
+                        if (container != NULL) {
+                            xmlNodePtr cur =
+                                xmlNewChild((xmlNodePtr) container, NULL,
+                                            BAD_CAST "boolean",
+                                            BAD_CAST (subResult->
+                                            boolval ? "true" : ""));
+                            if (cur != NULL) {
+                                cur->ns =
+                                    xmlNewNs(cur,
+                                             BAD_CAST
+                                             "http://exslt.org/common",
+                                             BAD_CAST "exsl");
+                                xmlXPathNodeSetAddUnique(ret->nodesetval,
+                                                         cur);
+                            }
+                        }
+                        break;
+                    case XPATH_NUMBER:
+                        if (container != NULL) {
+                            xmlChar *val =
+                                xmlXPathCastNumberToString(subResult->
+                                                           floatval);
+                            xmlNodePtr cur =
+                                xmlNewChild((xmlNodePtr) container, NULL,
+                                            BAD_CAST "number", val);
+                            if (val != NULL)
+                                xmlFree(val);
+
+                            if (cur != NULL) {
+                                cur->ns =
+                                    xmlNewNs(cur,
+                                             BAD_CAST
+                                             "http://exslt.org/common",
+                                             BAD_CAST "exsl");
+                                xmlXPathNodeSetAddUnique(ret->nodesetval,
+                                                         cur);
+                            }
+                        }
+                        break;
+                    case XPATH_STRING:
+                        if (container != NULL) {
+                            xmlNodePtr cur =
+                                xmlNewChild((xmlNodePtr) container, NULL,
+                                            BAD_CAST "string",
+                                            subResult->stringval);
+                            if (cur != NULL) {
+                                cur->ns =
+                                    xmlNewNs(cur,
+                                             BAD_CAST
+                                             "http://exslt.org/common",
+                                             BAD_CAST "exsl");
+                                xmlXPathNodeSetAddUnique(ret->nodesetval,
+                                                         cur);
+                            }
+                        }
+                        break;
+                   default:
+                        break;
+                }
+                xmlXPathFreeObject(subResult);
+            }
+        }
+    }
+    ctxt->context->doc = oldDoc;
+    ctxt->context->node = oldNode;
+    ctxt->context->contextSize = oldContextSize;
+    ctxt->context->proximityPosition = oldProximityPosition;
+
+
+  cleanup:
+    /* restore the xpath context */
+    if (comp != NULL)
+        xmlXPathFreeCompExpr(comp);
+    if (nodeset != NULL)
+        xmlXPathFreeNodeSet(nodeset);
+    if (str != NULL)
+        xmlFree(str);
+    valuePush(ctxt, ret);
+    return;
+}
+
+
+/**
+ * exsltDynRegister:
+ *
+ * Registers the EXSLT - Dynamic module
+ */
+
+void
+exsltDynRegister (void) {
+    xsltRegisterExtModuleFunction ((const xmlChar *) "evaluate",
+                                  EXSLT_DYNAMIC_NAMESPACE,
+                                  exsltDynEvaluateFunction);
+  xsltRegisterExtModuleFunction ((const xmlChar *) "map",
+                                  EXSLT_DYNAMIC_NAMESPACE,
+                                  exsltDynMapFunction);
+
+}
index 4d904c9..2cf7249 100644 (file)
-#define IN_LIBEXSLT\r
-#include "libexslt/libexslt.h"\r
-\r
-#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)\r
-#include <win32config.h>\r
-#else\r
-#include "config.h"\r
-#endif\r
-\r
-#include <string.h>\r
-\r
-#include <libxml/tree.h>\r
-#include <libxml/xpath.h>\r
-#include <libxml/xpathInternals.h>\r
-#include <libxml/hash.h>\r
-#include <libxml/debugXML.h>\r
-\r
-#include <libxslt/xsltutils.h>\r
-#include <libxslt/variables.h>\r
-#include <libxslt/xsltInternals.h>\r
-#include <libxslt/extensions.h>\r
-#include <libxslt/transform.h>\r
-#include <libxslt/imports.h>\r
-\r
-#include "exslt.h"\r
-\r
-typedef struct _exsltFuncFunctionData exsltFuncFunctionData;\r
-struct _exsltFuncFunctionData {\r
-    int nargs;                 /* number of arguments to the function */\r
-    xmlNodePtr content;                /* the func:fuction template content */\r
-};\r
-\r
-typedef struct _exsltFuncData exsltFuncData;\r
-struct _exsltFuncData {\r
-    xmlHashTablePtr funcs;     /* pointer to the stylesheet module data */\r
-    xmlXPathObjectPtr result;  /* returned by func:result */\r
-    int error;                 /* did an error occur? */\r
-    xmlDocPtr RVT;   /* result tree fragment */\r
-};\r
-\r
-typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp;\r
-struct _exsltFuncResultPreComp {\r
-    xsltElemPreComp comp;\r
-    xmlXPathCompExprPtr select;\r
-    xmlNsPtr *nsList;\r
-    int nsNr;\r
-};\r
-\r
-/* Used for callback function in exsltInitFunc */\r
-typedef struct _exsltFuncImportRegData exsltFuncImportRegData;\r
-struct _exsltFuncImportRegData {\r
-    xsltTransformContextPtr ctxt;\r
-    xmlHashTablePtr hash;\r
-};\r
-\r
-static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt,\r
-                                      int nargs);\r
-static exsltFuncFunctionData *exsltFuncNewFunctionData(void);\r
-\r
-static const xmlChar *exsltResultDataID = (const xmlChar *) "EXSLT Result";\r
-\r
-/**\r
- * exsltFuncRegisterFunc:\r
- * @func:  the #exsltFuncFunctionData for the function\r
- * @ctxt:  an XSLT transformation context\r
- * @URI:  the function namespace URI\r
- * @name: the function name\r
- *\r
- * Registers a function declared by a func:function element\r
- */\r
-static void\r
-exsltFuncRegisterFunc (exsltFuncFunctionData *data,\r
-                      xsltTransformContextPtr ctxt,\r
-                      const xmlChar *URI, const xmlChar *name,\r
-                      ATTRIBUTE_UNUSED const xmlChar *ignored) {\r
-    if ((data == NULL) || (ctxt == NULL) || (URI == NULL) || (name == NULL))\r
-       return;\r
-\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-                    "exsltFuncRegisterFunc: register {%s}%s\n",\r
-                    URI, name);\r
-    xsltRegisterExtFunction(ctxt, name, URI,\r
-                           exsltFuncFunctionFunction);\r
-}\r
-\r
-/*\r
- * exsltFuncRegisterImportFunc\r
- * @data:    the exsltFuncFunctionData for the function\r
- * @ch:             structure containing context and hash table\r
- * @URI:     the function namespace URI\r
- * @name:    the function name\r
- *\r
- * Checks if imported function is already registered in top-level\r
- * stylesheet.  If not, copies function data and registers function\r
- */\r
-static void\r
-exsltFuncRegisterImportFunc (exsltFuncFunctionData *data,\r
-                            exsltFuncImportRegData *ch,\r
-                            const xmlChar *URI, const xmlChar *name,\r
-                            ATTRIBUTE_UNUSED const xmlChar *ignored) {\r
-    exsltFuncFunctionData *func=NULL;\r
-\r
-    if ((data == NULL) || (ch == NULL) || (URI == NULL) || (name == NULL))\r
-            return;\r
-\r
-    if (ch->ctxt == NULL || ch->hash == NULL)\r
-       return;\r
-\r
-    /* Check if already present */\r
-    func = (exsltFuncFunctionData*)xmlHashLookup2(ch->hash, URI, name);\r
-    if (func == NULL) {                /* Not yet present - copy it in */\r
-       func = exsltFuncNewFunctionData();\r
-       memcpy(func, data, sizeof(exsltFuncFunctionData));\r
-       if (xmlHashAddEntry2(ch->hash, URI, name, func) < 0) {\r
-           xsltGenericError(xsltGenericErrorContext,\r
-                   "Failed to register function {%s}%s\n",\r
-                   URI, name);\r
-       } else {                /* Do the registration */\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-                   "exsltFuncRegisterImportFunc: register {%s}%s\n",\r
-                   URI, name);\r
-           xsltRegisterExtFunction(ch->ctxt, name, URI,\r
-                   exsltFuncFunctionFunction);\r
-       }\r
-    }\r
-}\r
-\r
-/**\r
- * exsltFuncInit:\r
- * @ctxt: an XSLT transformation context\r
- * @URI: the namespace URI for the extension\r
- *\r
- * Initializes the EXSLT - Functions module.\r
- * Called at transformation-time; merges all\r
- * functions declared in the import tree taking\r
- * import precedence into account, i.e. overriding\r
- * functions with lower import precedence.\r
- *\r
- * Returns the data for this transformation\r
- */\r
-static exsltFuncData *\r
-exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {\r
-    exsltFuncData *ret;\r
-    xsltStylesheetPtr tmp;\r
-    exsltFuncImportRegData ch;\r
-    xmlHashTablePtr hash;\r
-    \r
-    ret = (exsltFuncData *) xmlMalloc (sizeof(exsltFuncData));\r
-    if (ret == NULL) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-                        "exsltFuncInit: not enough memory\n");\r
-       return(NULL);\r
-    }\r
-    memset(ret, 0, sizeof(exsltFuncData));\r
-\r
-    ret->result = NULL;\r
-    ret->error = 0;\r
-\r
-    ch.hash = (xmlHashTablePtr) xsltStyleGetExtData(ctxt->style, URI);\r
-    ret->funcs = ch.hash;\r
-    xmlHashScanFull(ch.hash, (xmlHashScannerFull) exsltFuncRegisterFunc, ctxt);\r
-    tmp = ctxt->style;\r
-    ch.ctxt = ctxt;\r
-    while ((tmp=xsltNextImport(tmp))!=NULL) {\r
-       hash = xsltGetExtInfo(tmp, URI);\r
-       if (hash != NULL) {\r
-           xmlHashScanFull(hash, \r
-                   (xmlHashScannerFull) exsltFuncRegisterImportFunc, &ch);\r
-       }\r
-    }\r
-\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * exsltFuncShutdown:\r
- * @ctxt: an XSLT transformation context\r
- * @URI: the namespace URI for the extension\r
- * @data: the module data to free up\r
- *  \r
- * Shutdown the EXSLT - Functions module\r
- * Called at transformation-time.\r
- */\r
-static void\r
-exsltFuncShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,\r
-                  const xmlChar *URI ATTRIBUTE_UNUSED,\r
-                  exsltFuncData *data) {\r
-    if (data->result != NULL)\r
-       xmlXPathFreeObject(data->result);\r
-    xmlFree(data);\r
-}\r
-\r
-/**\r
- * exsltFuncStyleInit:\r
- * @style: an XSLT stylesheet\r
- * @URI: the namespace URI for the extension\r
- *\r
- * Allocates the stylesheet data for EXSLT - Function\r
- * Called at compile-time.\r
- *\r
- * Returns the allocated data\r
- */\r
-static xmlHashTablePtr\r
-exsltFuncStyleInit (xsltStylesheetPtr style ATTRIBUTE_UNUSED,\r
-                   const xmlChar *URI ATTRIBUTE_UNUSED) {\r
-    return xmlHashCreate(1);\r
-}\r
-\r
-/**\r
- * exsltFuncStyleShutdown:\r
- * @style: an XSLT stylesheet\r
- * @URI: the namespace URI for the extension\r
- * @data: the stylesheet data to free up \r
- *\r
- * Shutdown the EXSLT - Function module\r
- * Called at compile-time.\r
- */\r
-static void\r
-exsltFuncStyleShutdown (xsltStylesheetPtr style ATTRIBUTE_UNUSED,\r
-                       const xmlChar *URI ATTRIBUTE_UNUSED,\r
-                       xmlHashTablePtr data) {\r
-    xmlHashFree(data, (xmlHashDeallocator) xmlFree);\r
-}\r
-\r
-/**\r
- * exsltFuncNewFunctionData:\r
- *\r
- * Allocates an #exslFuncFunctionData object\r
- *\r
- * Returns the new structure\r
- */\r
-static exsltFuncFunctionData *\r
-exsltFuncNewFunctionData (void) {\r
-    exsltFuncFunctionData *ret;\r
-\r
-    ret = (exsltFuncFunctionData *) xmlMalloc (sizeof(exsltFuncFunctionData));\r
-    if (ret == NULL) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-                        "exsltFuncNewFunctionData: not enough memory\n");\r
-       return (NULL);\r
-    }\r
-    memset(ret, 0, sizeof(exsltFuncFunctionData));\r
-\r
-    ret->nargs = 0;\r
-    ret->content = NULL;\r
-\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * exsltFreeFuncResultPreComp:\r
- * @comp:  the #exsltFuncResultPreComp to free up\r
- *\r
- * Deallocates an #exsltFuncResultPreComp\r
- */\r
-static void\r
-exsltFreeFuncResultPreComp (exsltFuncResultPreComp *comp) {\r
-    if (comp == NULL)\r
-       return;\r
-\r
-    if (comp->select != NULL)\r
-       xmlXPathFreeCompExpr (comp->select);\r
-    if (comp->nsList != NULL)\r
-        xmlFree(comp->nsList);\r
-    xmlFree(comp);\r
-}\r
-\r
-/**\r
- * exsltFuncFunctionFunction:\r
- * @ctxt:  an XPath parser context\r
- * @nargs:  the number of arguments\r
- *\r
- * Evaluates the func:function element that defines the called function.\r
- */\r
-static void\r
-exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {\r
-    xmlXPathObjectPtr obj, oldResult, ret;\r
-    exsltFuncData *data;\r
-    exsltFuncFunctionData *func;\r
-    xmlNodePtr paramNode, oldInsert, fake;\r
-    int oldBase;\r
-    xsltStackElemPtr params = NULL, param;\r
-    xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);\r
-    int i;\r
-\r
-    /*\r
-     * retrieve func:function template\r
-     */\r
-    data = (exsltFuncData *) xsltGetExtData (tctxt,\r
-                                            EXSLT_FUNCTIONS_NAMESPACE);\r
-    oldResult = data->result;\r
-    data->result = NULL;\r
-\r
-    func = (exsltFuncFunctionData*) xmlHashLookup2 (data->funcs,\r
-                                                   ctxt->context->functionURI,\r
-                                                   ctxt->context->function);\r
-\r
-    /*\r
-     * params handling\r
-     */\r
-    if (nargs > func->nargs) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-                        "{%s}%s: called with too many arguments\n",\r
-                        ctxt->context->functionURI, ctxt->context->function);\r
-       ctxt->error = XPATH_INVALID_ARITY;\r
-       return;\r
-    }\r
-    if (func->content != NULL) {\r
-       paramNode = func->content->prev;\r
-    }\r
-    else\r
-       paramNode = NULL;\r
-    if ((paramNode == NULL) && (func->nargs != 0)) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-                        "exsltFuncFunctionFunction: nargs != 0 and "\r
-                        "param == NULL\n");\r
-       return;\r
-    }\r
-    /*\r
-    * Process xsl:param instructions which were not set by the\r
-    * invoking function call.\r
-    */\r
-    for (i = func->nargs; (i > nargs) && (paramNode != NULL); i--) {\r
-       /*\r
-       * Those are the xsl:param instructions, which were not\r
-       * set by the calling function.  \r
-       */\r
-       param = xsltParseStylesheetCallerParam (tctxt, paramNode);\r
-       param->next = params;\r
-       params = param;\r
-       paramNode = paramNode->prev;\r
-    }\r
-    /*\r
-    * Process xsl:param instructions which are set by the\r
-    * invoking function call.\r
-    */\r
-    while ((i-- > 0) && (paramNode != NULL)) {\r
-       obj = valuePop(ctxt);\r
-       /*\r
-       * TODO: Using xsltParseStylesheetCallerParam() is actually\r
-       * not correct, since we are processing an xsl:param; but\r
-       * using xsltParseStylesheetParam() won't work, as it puts\r
-       * the param on the varible stack and does not give access to\r
-       * the created xsltStackElemPtr.\r
-       * It's also not correct, as xsltParseStylesheetCallerParam()\r
-       * will report error messages indicating an "xsl:with-param" and\r
-       * not the actual "xsl:param".\r
-       */\r
-       param = xsltParseStylesheetCallerParam (tctxt, paramNode);\r
-       param->computed = 1;\r
-       if (param->value != NULL)\r
-           xmlXPathFreeObject(param->value);\r
-       param->value = obj;\r
-       param->next = params;\r
-       params = param;\r
-       paramNode = paramNode->prev;\r
-    }\r
-    \r
-    /*\r
-     * actual processing\r
-     */\r
-    fake = xmlNewDocNode(tctxt->output, NULL,\r
-                        (const xmlChar *)"fake", NULL);\r
-    oldInsert = tctxt->insert;\r
-    tctxt->insert = fake;\r
-    /* \r
-     * In order to give the function variables a new 'scope' we\r
-     * change varsBase in the context.\r
-     */\r
-    oldBase = tctxt->varsBase;\r
-    tctxt->varsBase = tctxt->varsNr;\r
-    xsltApplyOneTemplate (tctxt, xmlXPathGetContextNode(ctxt),\r
-                         func->content, NULL, params);\r
-    tctxt->insert = oldInsert;\r
-    tctxt->varsBase = oldBase; /* restore original scope */\r
-    if (params != NULL)\r
-       xsltFreeStackElemList(params);    \r
-\r
-    if (data->error != 0)\r
-       goto error;\r
-\r
-    if (data->result != NULL) {\r
-       ret = data->result;\r
-    } else\r
-       ret = xmlXPathNewCString("");\r
-\r
-    data->result = oldResult;\r
-\r
-    /*\r
-     * It is an error if the instantiation of the template results in\r
-     * the generation of result nodes.\r
-     */\r
-    if (fake->children != NULL) {\r
-#ifdef LIBXML_DEBUG_ENABLED\r
-       xmlDebugDumpNode (stderr, fake, 1);\r
-#endif\r
-       xsltGenericError(xsltGenericErrorContext,\r
-                        "{%s}%s: cannot write to result tree while "\r
-                        "executing a function\n",\r
-                        ctxt->context->functionURI, ctxt->context->function);\r
-       xmlFreeNode(fake);\r
-       goto error;\r
-    }\r
-    xmlFreeNode(fake);\r
-    valuePush(ctxt, ret);\r
-\r
-error:\r
-    /*\r
-    * IMPORTANT: This enables previously tree fragments marked as\r
-    * being results of a function, to be garbage-collected after\r
-    * the calling process exits.\r
-    */\r
-    xsltExtensionInstructionResultFinalize(tctxt);\r
-}\r
-\r
-\r
-static void\r
-exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) {\r
-    xmlChar *name, *prefix;\r
-    xmlNsPtr ns;\r
-    xmlHashTablePtr data;\r
-    exsltFuncFunctionData *func;\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-\r
-    {\r
-       xmlChar *qname;\r
-\r
-       qname = xmlGetProp(inst, (const xmlChar *) "name");\r
-       name = xmlSplitQName2 (qname, &prefix);\r
-       xmlFree(qname);\r
-    }\r
-    if ((name == NULL) || (prefix == NULL)) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-                        "func:function: not a QName\n");\r
-       if (name != NULL)\r
-           xmlFree(name);\r
-       return;\r
-    }\r
-    /* namespace lookup */\r
-    ns = xmlSearchNs (inst->doc, inst, prefix);\r
-    if (ns == NULL) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-                        "func:function: undeclared prefix %s\n",\r
-                        prefix);\r
-       xmlFree(name);\r
-       xmlFree(prefix);\r
-       return;\r
-    }\r
-    xmlFree(prefix);\r
-\r
-    /*\r
-     * Create function data\r
-     */\r
-    func = exsltFuncNewFunctionData();\r
-    func->content = inst->children;\r
-    while (IS_XSLT_ELEM(func->content) &&\r
-          IS_XSLT_NAME(func->content, "param")) {\r
-       func->content = func->content->next;\r
-       func->nargs++;\r
-    }\r
-\r
-    xsltParseTemplateContent(style, inst);\r
-\r
-    /*\r
-     * Register the function data such that it can be retrieved\r
-     * by exslFuncFunctionFunction\r
-     */\r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * Ensure that the hash table will be stored in the *current*\r
-    * stylesheet level in order to correctly evaluate the\r
-    * import precedence.\r
-    */\r
-    data = (xmlHashTablePtr)\r
-       xsltStyleStylesheetLevelGetExtData(style,\r
-           EXSLT_FUNCTIONS_NAMESPACE);\r
-#else\r
-    data = (xmlHashTablePtr)\r
-       xsltStyleGetExtData (style, EXSLT_FUNCTIONS_NAMESPACE);\r
-#endif\r
-    if (data == NULL) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-                        "exsltFuncFunctionComp: no stylesheet data\n");\r
-       xmlFree(name);\r
-       return;\r
-    }\r
-\r
-    if (xmlHashAddEntry2 (data, ns->href, name, func) < 0) {\r
-       xsltTransformError(NULL, style, inst,\r
-           "Failed to register function {%s}%s\n",\r
-                        ns->href, name);\r
-       style->errors++;\r
-    } else {\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-                        "exsltFuncFunctionComp: register {%s}%s\n",\r
-                        ns->href, name);\r
-    }\r
-    xmlFree(name);\r
-}\r
-\r
-static xsltElemPreCompPtr\r
-exsltFuncResultComp (xsltStylesheetPtr style, xmlNodePtr inst,\r
-                    xsltTransformFunction function) {\r
-    xmlNodePtr test;\r
-    xmlChar *sel;\r
-    exsltFuncResultPreComp *ret;\r
-\r
-    /*\r
-     * "Validity" checking\r
-     */\r
-    /* it is an error to have any following sibling elements aside\r
-     * from the xsl:fallback element.\r
-     */\r
-    for (test = inst->next; test != NULL; test = test->next) {\r
-       if (test->type != XML_ELEMENT_NODE)\r
-           continue;\r
-       if (IS_XSLT_ELEM(test) && IS_XSLT_NAME(test, "fallback"))\r
-           continue;\r
-       xsltGenericError(xsltGenericErrorContext,\r
-                        "exsltFuncResultElem: only xsl:fallback is "\r
-                        "allowed to follow func:result\n");\r
-       return (NULL);\r
-    }\r
-    /* it is an error for a func:result element to not be a descendant\r
-     * of func:function.\r
-     * it is an error if a func:result occurs within a func:result\r
-     * element.\r
-     * it is an error if instanciating the content of a variable\r
-     * binding element (i.e. xsl:variable, xsl:param) results in the \r
-     * instanciation of a func:result element.\r
-     */\r
-    for (test = inst->parent; test != NULL; test = test->parent) {\r
-       if ((test->ns != NULL) &&\r
-           (xmlStrEqual(test->ns->href, EXSLT_FUNCTIONS_NAMESPACE))) {\r
-           if (xmlStrEqual(test->name, (const xmlChar *) "function")) {\r
-               break;\r
-           }\r
-           if (xmlStrEqual(test->name, (const xmlChar *) "result")) {\r
-               xsltGenericError(xsltGenericErrorContext,\r
-                                "func:result element not allowed within"\r
-                                " another func:result element\n");\r
-               return (NULL);\r
-           }\r
-       }\r
-       if (IS_XSLT_ELEM(test) &&\r
-           (IS_XSLT_NAME(test, "variable") ||\r
-            IS_XSLT_NAME(test, "param"))) {\r
-           xsltGenericError(xsltGenericErrorContext,\r
-                            "func:result element not allowed within"\r
-                            " a variable binding element\n");\r
-           return (NULL);\r
-       }\r
-    }\r
-\r
-    /*\r
-     * Precomputation\r
-     */\r
-    ret = (exsltFuncResultPreComp *)\r
-       xmlMalloc (sizeof(exsltFuncResultPreComp));\r
-    if (ret == NULL) {\r
-       xsltPrintErrorContext(NULL, NULL, NULL);\r
-        xsltGenericError(xsltGenericErrorContext,\r
-                         "exsltFuncResultComp : malloc failed\n");\r
-        return (NULL);\r
-    }\r
-    memset(ret, 0, sizeof(exsltFuncResultPreComp));\r
-\r
-    xsltInitElemPreComp ((xsltElemPreCompPtr) ret, style, inst, function,\r
-                (xsltElemPreCompDeallocator) exsltFreeFuncResultPreComp);\r
-    ret->select = NULL;\r
-\r
-    /*\r
-     * Precompute the select attribute\r
-     */\r
-    sel = xmlGetNsProp(inst, (const xmlChar *) "select", NULL);\r
-    if (sel != NULL) {\r
-       ret->select = xmlXPathCompile (sel);\r
-       xmlFree(sel);\r
-    }\r
-    /*\r
-     * Precompute the namespace list\r
-     */\r
-    ret->nsList = xmlGetNsList(inst->doc, inst);\r
-    if (ret->nsList != NULL) {\r
-        int i = 0;\r
-        while (ret->nsList[i] != NULL)\r
-           i++;\r
-       ret->nsNr = i;\r
-    }\r
-    return ((xsltElemPreCompPtr) ret);\r
-}\r
-\r
-static void\r
-exsltFuncResultElem (xsltTransformContextPtr ctxt,\r
-                    xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst,\r
-                    exsltFuncResultPreComp *comp) {\r
-    exsltFuncData *data;\r
-    xmlXPathObjectPtr ret;\r
-    \r
-\r
-    /* It is an error if instantiating the content of the\r
-     * func:function element results in the instantiation of more than\r
-     * one func:result elements.\r
-     */\r
-    data = (exsltFuncData *) xsltGetExtData (ctxt, EXSLT_FUNCTIONS_NAMESPACE);\r
-    if (data == NULL) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-                        "exsltFuncReturnElem: data == NULL\n");\r
-       return;\r
-    }\r
-    if (data->result != NULL) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-                        "func:result already instanciated\n");\r
-       data->error = 1;\r
-       return;\r
-    }\r
-    /*\r
-     * Processing\r
-     */\r
-    if (comp->select != NULL) {\r
-       xmlNsPtr *oldXPNsList;\r
-       int oldXPNsNr;\r
-       xmlNodePtr oldXPContextNode;\r
-       /* If the func:result element has a select attribute, then the\r
-        * value of the attribute must be an expression and the\r
-        * returned value is the object that results from evaluating\r
-        * the expression. In this case, the content must be empty.\r
-        */\r
-       if (inst->children != NULL) {\r
-           xsltGenericError(xsltGenericErrorContext,\r
-                            "func:result content must be empty if it"\r
-                            " has a select attribute\n");\r
-           data->error = 1;\r
-           return;\r
-       }\r
-       oldXPNsList = ctxt->xpathCtxt->namespaces;\r
-       oldXPNsNr = ctxt->xpathCtxt->nsNr;\r
-       oldXPContextNode = ctxt->xpathCtxt->node;\r
-\r
-       ctxt->xpathCtxt->namespaces = comp->nsList;\r
-       ctxt->xpathCtxt->nsNr = comp->nsNr;\r
-\r
-       ret = xmlXPathCompiledEval(comp->select, ctxt->xpathCtxt);\r
-\r
-       ctxt->xpathCtxt->node = oldXPContextNode;\r
-       ctxt->xpathCtxt->nsNr = oldXPNsNr;\r
-       ctxt->xpathCtxt->namespaces = oldXPNsList;\r
-\r
-       if (ret == NULL) {\r
-           xsltGenericError(xsltGenericErrorContext,\r
-                            "exsltFuncResultElem: ret == NULL\n");\r
-           return;\r
-       }\r
-       /*\r
-       * Mark it as a function result in order to avoid garbage\r
-       * collecting of tree fragments before the function exits.\r
-       */\r
-       xsltExtensionInstructionResultRegister(ctxt, ret);\r
-    } else if (inst->children != NULL) {\r
-       /* If the func:result element does not have a select attribute\r
-        * and has non-empty content (i.e. the func:result element has\r
-        * one or more child nodes), then the content of the\r
-        * func:result element specifies the value.\r
-        */\r
-       xmlNodePtr oldInsert;\r
-       xmlDocPtr container;\r
-\r
-       container = xsltCreateRVT(ctxt);\r
-       if (container == NULL) {\r
-           xsltGenericError(xsltGenericErrorContext,\r
-                            "exsltFuncResultElem: out of memory\n");\r
-           data->error = 1;\r
-           return;\r
-       }\r
-       xsltRegisterLocalRVT(ctxt, container);  \r
-\r
-       oldInsert = ctxt->insert;\r
-       ctxt->insert = (xmlNodePtr) container;\r
-       xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node,\r
-                             inst->children, NULL, NULL);\r
-       ctxt->insert = oldInsert;\r
-\r
-       ret = xmlXPathNewValueTree((xmlNodePtr) container);\r
-       if (ret == NULL) {\r
-           xsltGenericError(xsltGenericErrorContext,\r
-                            "exsltFuncResultElem: ret == NULL\n");\r
-           data->error = 1;\r
-       } else {\r
-           ret->boolval = 0; /* Freeing is not handled there anymore */\r
-           /*\r
-           * Mark it as a function result in order to avoid garbage\r
-           * collecting of tree fragments before the function exits.\r
-           */\r
-           xsltExtensionInstructionResultRegister(ctxt, ret);\r
-       }\r
-    } else {\r
-       /* If the func:result element has empty content and does not\r
-        * have a select attribute, then the returned value is an\r
-        * empty string.\r
-        */\r
-       ret = xmlXPathNewCString("");\r
-    }\r
-    data->result = ret;\r
-}\r
-\r
-/**\r
- * exsltFuncRegister:\r
- *\r
- * Registers the EXSLT - Functions module\r
- */\r
-void\r
-exsltFuncRegister (void) {\r
-    xsltRegisterExtModuleFull (EXSLT_FUNCTIONS_NAMESPACE,\r
-                      (xsltExtInitFunction) exsltFuncInit,\r
-                      (xsltExtShutdownFunction) exsltFuncShutdown,\r
-                      (xsltStyleExtInitFunction) exsltFuncStyleInit,\r
-                      (xsltStyleExtShutdownFunction) exsltFuncStyleShutdown);\r
-\r
-    xsltRegisterExtModuleTopLevel ((const xmlChar *) "function",\r
-                                  EXSLT_FUNCTIONS_NAMESPACE,\r
-                                  exsltFuncFunctionComp);\r
-    xsltRegisterExtModuleElement ((const xmlChar *) "result",\r
-                         EXSLT_FUNCTIONS_NAMESPACE,\r
-                         (xsltPreComputeFunction)exsltFuncResultComp,\r
-                         (xsltTransformFunction) exsltFuncResultElem);\r
-}\r
+#define IN_LIBEXSLT
+#include "libexslt/libexslt.h"
+
+#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
+#include <win32config.h>
+#else
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/hash.h>
+#include <libxml/debugXML.h>
+
+#include <libxslt/xsltutils.h>
+#include <libxslt/variables.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/extensions.h>
+#include <libxslt/transform.h>
+#include <libxslt/imports.h>
+
+#include "exslt.h"
+
+typedef struct _exsltFuncFunctionData exsltFuncFunctionData;
+struct _exsltFuncFunctionData {
+    int nargs;                 /* number of arguments to the function */
+    xmlNodePtr content;                /* the func:fuction template content */
+};
+
+typedef struct _exsltFuncData exsltFuncData;
+struct _exsltFuncData {
+    xmlHashTablePtr funcs;     /* pointer to the stylesheet module data */
+    xmlXPathObjectPtr result;  /* returned by func:result */
+    int error;                 /* did an error occur? */
+    xmlDocPtr RVT;   /* result tree fragment */
+};
+
+typedef struct _exsltFuncResultPreComp exsltFuncResultPreComp;
+struct _exsltFuncResultPreComp {
+    xsltElemPreComp comp;
+    xmlXPathCompExprPtr select;
+    xmlNsPtr *nsList;
+    int nsNr;
+};
+
+/* Used for callback function in exsltInitFunc */
+typedef struct _exsltFuncImportRegData exsltFuncImportRegData;
+struct _exsltFuncImportRegData {
+    xsltTransformContextPtr ctxt;
+    xmlHashTablePtr hash;
+};
+
+static void exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt,
+                                      int nargs);
+static exsltFuncFunctionData *exsltFuncNewFunctionData(void);
+
+static const xmlChar *exsltResultDataID = (const xmlChar *) "EXSLT Result";
+
+/**
+ * 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,
+                      ATTRIBUTE_UNUSED const xmlChar *ignored) {
+    if ((data == NULL) || (ctxt == NULL) || (URI == NULL) || (name == NULL))
+       return;
+
+    xsltGenericDebug(xsltGenericDebugContext,
+                    "exsltFuncRegisterFunc: register {%s}%s\n",
+                    URI, name);
+    xsltRegisterExtFunction(ctxt, name, URI,
+                           exsltFuncFunctionFunction);
+}
+
+/*
+ * exsltFuncRegisterImportFunc
+ * @data:    the exsltFuncFunctionData for the function
+ * @ch:             structure containing context and hash table
+ * @URI:     the function namespace URI
+ * @name:    the function name
+ *
+ * Checks if imported function is already registered in top-level
+ * stylesheet.  If not, copies function data and registers function
+ */
+static void
+exsltFuncRegisterImportFunc (exsltFuncFunctionData *data,
+                            exsltFuncImportRegData *ch,
+                            const xmlChar *URI, const xmlChar *name,
+                            ATTRIBUTE_UNUSED const xmlChar *ignored) {
+    exsltFuncFunctionData *func=NULL;
+
+    if ((data == NULL) || (ch == NULL) || (URI == NULL) || (name == NULL))
+            return;
+
+    if (ch->ctxt == NULL || ch->hash == NULL)
+       return;
+
+    /* Check if already present */
+    func = (exsltFuncFunctionData*)xmlHashLookup2(ch->hash, URI, name);
+    if (func == NULL) {                /* Not yet present - copy it in */
+       func = exsltFuncNewFunctionData();
+       memcpy(func, data, sizeof(exsltFuncFunctionData));
+       if (xmlHashAddEntry2(ch->hash, URI, name, func) < 0) {
+           xsltGenericError(xsltGenericErrorContext,
+                   "Failed to register function {%s}%s\n",
+                   URI, name);
+       } else {                /* Do the registration */
+           xsltGenericDebug(xsltGenericDebugContext,
+                   "exsltFuncRegisterImportFunc: register {%s}%s\n",
+                   URI, name);
+           xsltRegisterExtFunction(ch->ctxt, name, URI,
+                   exsltFuncFunctionFunction);
+       }
+    }
+}
+
+/**
+ * exsltFuncInit:
+ * @ctxt: an XSLT transformation context
+ * @URI: the namespace URI for the extension
+ *
+ * Initializes the EXSLT - Functions module.
+ * Called at transformation-time; merges all
+ * functions declared in the import tree taking
+ * import precedence into account, i.e. overriding
+ * functions with lower import precedence.
+ *
+ * Returns the data for this transformation
+ */
+static exsltFuncData *
+exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
+    exsltFuncData *ret;
+    xsltStylesheetPtr tmp;
+    exsltFuncImportRegData ch;
+    xmlHashTablePtr hash;
+    
+    ret = (exsltFuncData *) xmlMalloc (sizeof(exsltFuncData));
+    if (ret == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+                        "exsltFuncInit: not enough memory\n");
+       return(NULL);
+    }
+    memset(ret, 0, sizeof(exsltFuncData));
+
+    ret->result = NULL;
+    ret->error = 0;
+
+    ch.hash = (xmlHashTablePtr) xsltStyleGetExtData(ctxt->style, URI);
+    ret->funcs = ch.hash;
+    xmlHashScanFull(ch.hash, (xmlHashScannerFull) exsltFuncRegisterFunc, ctxt);
+    tmp = ctxt->style;
+    ch.ctxt = ctxt;
+    while ((tmp=xsltNextImport(tmp))!=NULL) {
+       hash = xsltGetExtInfo(tmp, URI);
+       if (hash != NULL) {
+           xmlHashScanFull(hash, 
+                   (xmlHashScannerFull) exsltFuncRegisterImportFunc, &ch);
+       }
+    }
+
+    return(ret);
+}
+
+/**
+ * exsltFuncShutdown:
+ * @ctxt: an XSLT transformation context
+ * @URI: the namespace URI for the extension
+ * @data: the module data to free up
+ *  
+ * Shutdown the EXSLT - Functions module
+ * Called at transformation-time.
+ */
+static void
+exsltFuncShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
+                  const xmlChar *URI ATTRIBUTE_UNUSED,
+                  exsltFuncData *data) {
+    if (data->result != NULL)
+       xmlXPathFreeObject(data->result);
+    xmlFree(data);
+}
+
+/**
+ * exsltFuncStyleInit:
+ * @style: an XSLT stylesheet
+ * @URI: the namespace URI for the extension
+ *
+ * Allocates the stylesheet data for EXSLT - Function
+ * Called at compile-time.
+ *
+ * Returns the allocated data
+ */
+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
+ * Called at compile-time.
+ */
+static void
+exsltFuncStyleShutdown (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
+                       const xmlChar *URI ATTRIBUTE_UNUSED,
+                       xmlHashTablePtr data) {
+    xmlHashFree(data, (xmlHashDeallocator) xmlFree);
+}
+
+/**
+ * exsltFuncNewFunctionData:
+ *
+ * Allocates an #exslFuncFunctionData object
+ *
+ * Returns the new structure
+ */
+static exsltFuncFunctionData *
+exsltFuncNewFunctionData (void) {
+    exsltFuncFunctionData *ret;
+
+    ret = (exsltFuncFunctionData *) xmlMalloc (sizeof(exsltFuncFunctionData));
+    if (ret == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+                        "exsltFuncNewFunctionData: not enough memory\n");
+       return (NULL);
+    }
+    memset(ret, 0, sizeof(exsltFuncFunctionData));
+
+    ret->nargs = 0;
+    ret->content = NULL;
+
+    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);
+    if (comp->nsList != NULL)
+        xmlFree(comp->nsList);
+    xmlFree(comp);
+}
+
+/**
+ * exsltFuncFunctionFunction:
+ * @ctxt:  an XPath parser context
+ * @nargs:  the number of arguments
+ *
+ * Evaluates the func:function element that defines the called function.
+ */
+static void
+exsltFuncFunctionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+    xmlXPathObjectPtr obj, oldResult, ret;
+    exsltFuncData *data;
+    exsltFuncFunctionData *func;
+    xmlNodePtr paramNode, oldInsert, fake;
+    int oldBase;
+    xsltStackElemPtr params = NULL, param;
+    xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt);
+    int i;
+
+    /*
+     * retrieve func:function template
+     */
+    data = (exsltFuncData *) xsltGetExtData (tctxt,
+                                            EXSLT_FUNCTIONS_NAMESPACE);
+    oldResult = data->result;
+    data->result = NULL;
+
+    func = (exsltFuncFunctionData*) xmlHashLookup2 (data->funcs,
+                                                   ctxt->context->functionURI,
+                                                   ctxt->context->function);
+
+    /*
+     * params handling
+     */
+    if (nargs > func->nargs) {
+       xsltGenericError(xsltGenericErrorContext,
+                        "{%s}%s: called with too many arguments\n",
+                        ctxt->context->functionURI, ctxt->context->function);
+       ctxt->error = XPATH_INVALID_ARITY;
+       return;
+    }
+    if (func->content != NULL) {
+       paramNode = func->content->prev;
+    }
+    else
+       paramNode = NULL;
+    if ((paramNode == NULL) && (func->nargs != 0)) {
+       xsltGenericError(xsltGenericErrorContext,
+                        "exsltFuncFunctionFunction: nargs != 0 and "
+                        "param == NULL\n");
+       return;
+    }
+    /*
+    * Process xsl:param instructions which were not set by the
+    * invoking function call.
+    */
+    for (i = func->nargs; (i > nargs) && (paramNode != NULL); i--) {
+       /*
+       * Those are the xsl:param instructions, which were not
+       * set by the calling function.  
+       */
+       param = xsltParseStylesheetCallerParam (tctxt, paramNode);
+       param->next = params;
+       params = param;
+       paramNode = paramNode->prev;
+    }
+    /*
+    * Process xsl:param instructions which are set by the
+    * invoking function call.
+    */
+    while ((i-- > 0) && (paramNode != NULL)) {
+       obj = valuePop(ctxt);
+       /*
+       * TODO: Using xsltParseStylesheetCallerParam() is actually
+       * not correct, since we are processing an xsl:param; but
+       * using xsltParseStylesheetParam() won't work, as it puts
+       * the param on the varible stack and does not give access to
+       * the created xsltStackElemPtr.
+       * It's also not correct, as xsltParseStylesheetCallerParam()
+       * will report error messages indicating an "xsl:with-param" and
+       * not the actual "xsl:param".
+       */
+       param = xsltParseStylesheetCallerParam (tctxt, paramNode);
+       param->computed = 1;
+       if (param->value != NULL)
+           xmlXPathFreeObject(param->value);
+       param->value = obj;
+       param->next = params;
+       params = param;
+       paramNode = paramNode->prev;
+    }
+    
+    /*
+     * actual processing
+     */
+    fake = xmlNewDocNode(tctxt->output, NULL,
+                        (const xmlChar *)"fake", NULL);
+    oldInsert = tctxt->insert;
+    tctxt->insert = fake;
+    /* 
+     * In order to give the function variables a new 'scope' we
+     * change varsBase in the context.
+     */
+    oldBase = tctxt->varsBase;
+    tctxt->varsBase = tctxt->varsNr;
+    xsltApplyOneTemplate (tctxt, xmlXPathGetContextNode(ctxt),
+                         func->content, NULL, params);
+    tctxt->insert = oldInsert;
+    tctxt->varsBase = oldBase; /* restore original scope */
+    if (params != NULL)
+       xsltFreeStackElemList(params);    
+
+    if (data->error != 0)
+       goto error;
+
+    if (data->result != NULL) {
+       ret = data->result;
+    } else
+       ret = xmlXPathNewCString("");
+
+    data->result = oldResult;
+
+    /*
+     * It is an error if the instantiation of the template results in
+     * the generation of result nodes.
+     */
+    if (fake->children != NULL) {
+#ifdef LIBXML_DEBUG_ENABLED
+       xmlDebugDumpNode (stderr, fake, 1);
+#endif
+       xsltGenericError(xsltGenericErrorContext,
+                        "{%s}%s: cannot write to result tree while "
+                        "executing a function\n",
+                        ctxt->context->functionURI, ctxt->context->function);
+       xmlFreeNode(fake);
+       goto error;
+    }
+    xmlFreeNode(fake);
+    valuePush(ctxt, ret);
+
+error:
+    /*
+    * IMPORTANT: This enables previously tree fragments marked as
+    * being results of a function, to be garbage-collected after
+    * the calling process exits.
+    */
+    xsltExtensionInstructionResultFinalize(tctxt);
+}
+
+
+static void
+exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) {
+    xmlChar *name, *prefix;
+    xmlNsPtr ns;
+    xmlHashTablePtr data;
+    exsltFuncFunctionData *func;
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+
+    {
+       xmlChar *qname;
+
+       qname = xmlGetProp(inst, (const xmlChar *) "name");
+       name = xmlSplitQName2 (qname, &prefix);
+       xmlFree(qname);
+    }
+    if ((name == NULL) || (prefix == NULL)) {
+       xsltGenericError(xsltGenericErrorContext,
+                        "func:function: not a QName\n");
+       if (name != NULL)
+           xmlFree(name);
+       return;
+    }
+    /* namespace lookup */
+    ns = xmlSearchNs (inst->doc, inst, prefix);
+    if (ns == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+                        "func:function: undeclared prefix %s\n",
+                        prefix);
+       xmlFree(name);
+       xmlFree(prefix);
+       return;
+    }
+    xmlFree(prefix);
+
+    /*
+     * Create function data
+     */
+    func = exsltFuncNewFunctionData();
+    func->content = inst->children;
+    while (IS_XSLT_ELEM(func->content) &&
+          IS_XSLT_NAME(func->content, "param")) {
+       func->content = func->content->next;
+       func->nargs++;
+    }
+
+    xsltParseTemplateContent(style, inst);
+
+    /*
+     * Register the function data such that it can be retrieved
+     * by exslFuncFunctionFunction
+     */
+#ifdef XSLT_REFACTORED
+    /*
+    * Ensure that the hash table will be stored in the *current*
+    * stylesheet level in order to correctly evaluate the
+    * import precedence.
+    */
+    data = (xmlHashTablePtr)
+       xsltStyleStylesheetLevelGetExtData(style,
+           EXSLT_FUNCTIONS_NAMESPACE);
+#else
+    data = (xmlHashTablePtr)
+       xsltStyleGetExtData (style, EXSLT_FUNCTIONS_NAMESPACE);
+#endif
+    if (data == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+                        "exsltFuncFunctionComp: no stylesheet data\n");
+       xmlFree(name);
+       return;
+    }
+
+    if (xmlHashAddEntry2 (data, ns->href, name, func) < 0) {
+       xsltTransformError(NULL, style, inst,
+           "Failed to register function {%s}%s\n",
+                        ns->href, name);
+       style->errors++;
+    } else {
+       xsltGenericDebug(xsltGenericDebugContext,
+                        "exsltFuncFunctionComp: register {%s}%s\n",
+                        ns->href, name);
+    }
+    xmlFree(name);
+}
+
+static xsltElemPreCompPtr
+exsltFuncResultComp (xsltStylesheetPtr style, xmlNodePtr inst,
+                    xsltTransformFunction function) {
+    xmlNodePtr test;
+    xmlChar *sel;
+    exsltFuncResultPreComp *ret;
+
+    /*
+     * "Validity" checking
+     */
+    /* it is an error to have any following sibling elements aside
+     * from the xsl:fallback element.
+     */
+    for (test = inst->next; test != NULL; test = test->next) {
+       if (test->type != XML_ELEMENT_NODE)
+           continue;
+       if (IS_XSLT_ELEM(test) && IS_XSLT_NAME(test, "fallback"))
+           continue;
+       xsltGenericError(xsltGenericErrorContext,
+                        "exsltFuncResultElem: only xsl:fallback is "
+                        "allowed to follow func:result\n");
+       return (NULL);
+    }
+    /* it is an error for a func:result element to not be a descendant
+     * of func:function.
+     * it is an error if a func:result occurs within a func:result
+     * element.
+     * it is an error if instanciating the content of a variable
+     * binding element (i.e. xsl:variable, xsl:param) results in the 
+     * instanciation of a func:result element.
+     */
+    for (test = inst->parent; test != NULL; test = test->parent) {
+       if ((test->ns != NULL) &&
+           (xmlStrEqual(test->ns->href, EXSLT_FUNCTIONS_NAMESPACE))) {
+           if (xmlStrEqual(test->name, (const xmlChar *) "function")) {
+               break;
+           }
+           if (xmlStrEqual(test->name, (const xmlChar *) "result")) {
+               xsltGenericError(xsltGenericErrorContext,
+                                "func:result element not allowed within"
+                                " another func:result element\n");
+               return (NULL);
+           }
+       }
+       if (IS_XSLT_ELEM(test) &&
+           (IS_XSLT_NAME(test, "variable") ||
+            IS_XSLT_NAME(test, "param"))) {
+           xsltGenericError(xsltGenericErrorContext,
+                            "func:result element not allowed within"
+                            " a variable binding element\n");
+           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
+     */
+    sel = xmlGetNsProp(inst, (const xmlChar *) "select", NULL);
+    if (sel != NULL) {
+       ret->select = xmlXPathCompile (sel);
+       xmlFree(sel);
+    }
+    /*
+     * Precompute the namespace list
+     */
+    ret->nsList = xmlGetNsList(inst->doc, inst);
+    if (ret->nsList != NULL) {
+        int i = 0;
+        while (ret->nsList[i] != NULL)
+           i++;
+       ret->nsNr = i;
+    }
+    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
+     * func:function element results in the instantiation of more than
+     * one func:result elements.
+     */
+    data = (exsltFuncData *) xsltGetExtData (ctxt, EXSLT_FUNCTIONS_NAMESPACE);
+    if (data == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+                        "exsltFuncReturnElem: data == NULL\n");
+       return;
+    }
+    if (data->result != NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+                        "func:result already instanciated\n");
+       data->error = 1;
+       return;
+    }
+    /*
+     * Processing
+     */
+    if (comp->select != NULL) {
+       xmlNsPtr *oldXPNsList;
+       int oldXPNsNr;
+       xmlNodePtr oldXPContextNode;
+       /* If the func:result element has a select attribute, then the
+        * value of the attribute must be an expression and the
+        * returned value is the object that results from evaluating
+        * the expression. In this case, the content must be empty.
+        */
+       if (inst->children != NULL) {
+           xsltGenericError(xsltGenericErrorContext,
+                            "func:result content must be empty if it"
+                            " has a select attribute\n");
+           data->error = 1;
+           return;
+       }
+       oldXPNsList = ctxt->xpathCtxt->namespaces;
+       oldXPNsNr = ctxt->xpathCtxt->nsNr;
+       oldXPContextNode = ctxt->xpathCtxt->node;
+
+       ctxt->xpathCtxt->namespaces = comp->nsList;
+       ctxt->xpathCtxt->nsNr = comp->nsNr;
+
+       ret = xmlXPathCompiledEval(comp->select, ctxt->xpathCtxt);
+
+       ctxt->xpathCtxt->node = oldXPContextNode;
+       ctxt->xpathCtxt->nsNr = oldXPNsNr;
+       ctxt->xpathCtxt->namespaces = oldXPNsList;
+
+       if (ret == NULL) {
+           xsltGenericError(xsltGenericErrorContext,
+                            "exsltFuncResultElem: ret == NULL\n");
+           return;
+       }
+       /*
+       * Mark it as a function result in order to avoid garbage
+       * collecting of tree fragments before the function exits.
+       */
+       xsltExtensionInstructionResultRegister(ctxt, ret);
+    } else if (inst->children != NULL) {
+       /* If the func:result element does not have a select attribute
+        * and has non-empty content (i.e. the func:result element has
+        * one or more child nodes), then the content of the
+        * func:result element specifies the value.
+        */
+       xmlNodePtr oldInsert;
+       xmlDocPtr container;
+
+       container = xsltCreateRVT(ctxt);
+       if (container == NULL) {
+           xsltGenericError(xsltGenericErrorContext,
+                            "exsltFuncResultElem: out of memory\n");
+           data->error = 1;
+           return;
+       }
+       xsltRegisterLocalRVT(ctxt, container);  
+
+       oldInsert = ctxt->insert;
+       ctxt->insert = (xmlNodePtr) container;
+       xsltApplyOneTemplate (ctxt, ctxt->xpathCtxt->node,
+                             inst->children, NULL, NULL);
+       ctxt->insert = oldInsert;
+
+       ret = xmlXPathNewValueTree((xmlNodePtr) container);
+       if (ret == NULL) {
+           xsltGenericError(xsltGenericErrorContext,
+                            "exsltFuncResultElem: ret == NULL\n");
+           data->error = 1;
+       } else {
+           ret->boolval = 0; /* Freeing is not handled there anymore */
+           /*
+           * Mark it as a function result in order to avoid garbage
+           * collecting of tree fragments before the function exits.
+           */
+           xsltExtensionInstructionResultRegister(ctxt, ret);
+       }
+    } else {
+       /* If the func:result element has empty content and does not
+        * have a select attribute, then the returned value is an
+        * empty string.
+        */
+       ret = xmlXPathNewCString("");
+    }
+    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,
+                         (xsltPreComputeFunction)exsltFuncResultComp,
+                         (xsltTransformFunction) exsltFuncResultElem);
+}
index 484310a..c867f9c 100644 (file)
-#define IN_LIBEXSLT\r
-#include "libexslt/libexslt.h"\r
-\r
-#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)\r
-#include <win32config.h>\r
-#else\r
-#include "config.h"\r
-#endif\r
-\r
-#include <libxml/tree.h>\r
-#include <libxml/xpath.h>\r
-#include <libxml/xpathInternals.h>\r
-#include <libxml/parser.h>\r
-#include <libxml/encoding.h>\r
-#include <libxml/uri.h>\r
-\r
-#include <libxslt/xsltconfig.h>\r
-#include <libxslt/xsltutils.h>\r
-#include <libxslt/xsltInternals.h>\r
-#include <libxslt/extensions.h>\r
-\r
-#include "exslt.h"\r
-\r
-/**\r
- * exsltStrTokenizeFunction:\r
- * @ctxt: an XPath parser context\r
- * @nargs: the number of arguments\r
- *\r
- * Splits up a string on the characters of the delimiter string and returns a\r
- * node set of token elements, each containing one token from the string. \r
- */\r
-static void\r
-exsltStrTokenizeFunction(xmlXPathParserContextPtr ctxt, int nargs)\r
-{\r
-    xsltTransformContextPtr tctxt;\r
-    xmlChar *str, *delimiters, *cur;\r
-    const xmlChar *token, *delimiter;\r
-    xmlNodePtr node;\r
-    xmlDocPtr container;\r
-    xmlXPathObjectPtr ret = NULL;\r
-    int clen;\r
-\r
-    if ((nargs < 1) || (nargs > 2)) {\r
-        xmlXPathSetArityError(ctxt);\r
-        return;\r
-    }\r
-\r
-    if (nargs == 2) {\r
-        delimiters = xmlXPathPopString(ctxt);\r
-        if (xmlXPathCheckError(ctxt))\r
-            return;\r
-    } else {\r
-        delimiters = xmlStrdup((const xmlChar *) "\t\r\n ");\r
-    }\r
-    if (delimiters == NULL)\r
-        return;\r
-\r
-    str = xmlXPathPopString(ctxt);\r
-    if (xmlXPathCheckError(ctxt) || (str == NULL)) {\r
-        xmlFree(delimiters);\r
-        return;\r
-    }\r
-\r
-    /* Return a result tree fragment */\r
-    tctxt = xsltXPathGetTransformContext(ctxt);\r
-    if (tctxt == NULL) {\r
-        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-             "exslt:tokenize : internal error tctxt == NULL\n");\r
-       goto fail;\r
-    }\r
-\r
-    container = xsltCreateRVT(tctxt);\r
-    if (container != NULL) {\r
-        xsltRegisterLocalRVT(tctxt, container);\r
-        ret = xmlXPathNewNodeSet(NULL);\r
-        if (ret != NULL) {\r
-            for (cur = str, token = str; *cur != 0; cur += clen) {\r
-               clen = xmlUTF8Size(cur);\r
-               if (*delimiters == 0) { /* empty string case */\r
-                   xmlChar ctmp;\r
-                   ctmp = *(cur+clen);\r
-                   *(cur+clen) = 0;\r
-                    node = xmlNewDocRawNode(container, NULL,\r
-                                       (const xmlChar *) "token", cur);\r
-                   xmlAddChild((xmlNodePtr) container, node);\r
-                   xmlXPathNodeSetAddUnique(ret->nodesetval, node);\r
-                    *(cur+clen) = ctmp; /* restore the changed byte */\r
-                    token = cur + clen;\r
-                } else for (delimiter = delimiters; *delimiter != 0;\r
-                               delimiter += xmlUTF8Size(delimiter)) {\r
-                    if (!xmlUTF8Charcmp(cur, delimiter)) {\r
-                        if (cur == token) {\r
-                            /* discard empty tokens */\r
-                            token = cur + clen;\r
-                            break;\r
-                        }\r
-                        *cur = 0;      /* terminate the token */\r
-                        node = xmlNewDocRawNode(container, NULL,\r
-                                           (const xmlChar *) "token", token);\r
-                       xmlAddChild((xmlNodePtr) container, node);\r
-                       xmlXPathNodeSetAddUnique(ret->nodesetval, node);\r
-                        *cur = *delimiter; /* restore the changed byte */\r
-                        token = cur + clen;\r
-                        break;\r
-                    }\r
-                }\r
-            }\r
-            if (token != cur) {\r
-               node = xmlNewDocRawNode(container, NULL,\r
-                                   (const xmlChar *) "token", token);\r
-                xmlAddChild((xmlNodePtr) container, node);\r
-               xmlXPathNodeSetAddUnique(ret->nodesetval, node);\r
-            }\r
-        }\r
-    }\r
-\r
-fail:\r
-    if (str != NULL)\r
-        xmlFree(str);\r
-    if (delimiters != NULL)\r
-        xmlFree(delimiters);\r
-    if (ret != NULL)\r
-        valuePush(ctxt, ret);\r
-    else\r
-        valuePush(ctxt, xmlXPathNewNodeSet(NULL));\r
-}\r
-\r
-/**\r
- * exsltStrSplitFunction:\r
- * @ctxt: an XPath parser context\r
- * @nargs: the number of arguments\r
- *\r
- * Splits up a string on a delimiting string and returns a node set of token\r
- * elements, each containing one token from the string. \r
- */\r
-static void\r
-exsltStrSplitFunction(xmlXPathParserContextPtr ctxt, int nargs) {\r
-    xsltTransformContextPtr tctxt;\r
-    xmlChar *str, *delimiter, *cur;\r
-    const xmlChar *token;\r
-    xmlNodePtr node;\r
-    xmlDocPtr container;\r
-    xmlXPathObjectPtr ret = NULL;\r
-    int delimiterLength;\r
-\r
-    if ((nargs < 1) || (nargs > 2)) {\r
-        xmlXPathSetArityError(ctxt);\r
-        return;\r
-    }\r
-\r
-    if (nargs == 2) {\r
-        delimiter = xmlXPathPopString(ctxt);\r
-        if (xmlXPathCheckError(ctxt))\r
-            return;\r
-    } else {\r
-        delimiter = xmlStrdup((const xmlChar *) " ");\r
-    }\r
-    if (delimiter == NULL)\r
-        return;\r
-    delimiterLength = xmlStrlen (delimiter);\r
-\r
-    str = xmlXPathPopString(ctxt);\r
-    if (xmlXPathCheckError(ctxt) || (str == NULL)) {\r
-        xmlFree(delimiter);\r
-        return;\r
-    }\r
-\r
-    /* Return a result tree fragment */\r
-    tctxt = xsltXPathGetTransformContext(ctxt);\r
-    if (tctxt == NULL) {\r
-        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-             "exslt:tokenize : internal error tctxt == NULL\n");\r
-       goto fail;\r
-    }\r
-\r
-    /*\r
-    * OPTIMIZE TODO: We are creating an xmlDoc for every split!\r
-    */\r
-    container = xsltCreateRVT(tctxt);\r
-    if (container != NULL) {\r
-        xsltRegisterLocalRVT(tctxt, container);\r
-        ret = xmlXPathNewNodeSet(NULL);\r
-        if (ret != NULL) {\r
-            for (cur = str, token = str; *cur != 0; cur++) {\r
-               if (delimiterLength == 0) {\r
-                   if (cur != token) {\r
-                       xmlChar tmp = *cur;\r
-                       *cur = 0;\r
-                        node = xmlNewDocRawNode(container, NULL,\r
-                                           (const xmlChar *) "token", token);\r
-                       xmlAddChild((xmlNodePtr) container, node);\r
-                       xmlXPathNodeSetAddUnique(ret->nodesetval, node);\r
-                       *cur = tmp;\r
-                       token++;\r
-                   }\r
-               }\r
-               else if (!xmlStrncasecmp(cur, delimiter, delimiterLength)) {\r
-                   if (cur == token) {\r
-                       /* discard empty tokens */\r
-                       cur = cur + delimiterLength - 1;\r
-                       token = cur + 1;\r
-                       continue;\r
-                   }\r
-                   *cur = 0;\r
-                   node = xmlNewDocRawNode(container, NULL,\r
-                                      (const xmlChar *) "token", token);\r
-                   xmlAddChild((xmlNodePtr) container, node);\r
-                   xmlXPathNodeSetAddUnique(ret->nodesetval, node);\r
-                   *cur = *delimiter;\r
-                   cur = cur + delimiterLength - 1;\r
-                   token = cur + 1;\r
-                }\r
-            }\r
-           if (token != cur) {\r
-               node = xmlNewDocRawNode(container, NULL,\r
-                                  (const xmlChar *) "token", token);\r
-               xmlAddChild((xmlNodePtr) container, node);\r
-               xmlXPathNodeSetAddUnique(ret->nodesetval, node);\r
-           }\r
-        }\r
-    }\r
-\r
-fail:\r
-    if (str != NULL)\r
-        xmlFree(str);\r
-    if (delimiter != NULL)\r
-        xmlFree(delimiter);\r
-    if (ret != NULL)\r
-        valuePush(ctxt, ret);\r
-    else\r
-        valuePush(ctxt, xmlXPathNewNodeSet(NULL));\r
-}\r
-\r
-/**\r
- * exsltStrEncodeUriFunction:\r
- * @ctxt: an XPath parser context\r
- * @nargs: the number of arguments\r
- *\r
- * URI-Escapes a string\r
- */\r
-static void\r
-exsltStrEncodeUriFunction (xmlXPathParserContextPtr ctxt, int nargs) {\r
-    int escape_all = 1, str_len = 0;\r
-    xmlChar *str = NULL, *ret = NULL, *tmp;\r
-\r
-    if ((nargs < 2) || (nargs > 3)) {\r
-       xmlXPathSetArityError(ctxt);\r
-       return;\r
-    }\r
-\r
-    if (nargs >= 3) {\r
-        /* check for UTF-8 if encoding was explicitly given;\r
-           we don't support anything else yet */\r
-        tmp = xmlXPathPopString(ctxt);\r
-        if (xmlUTF8Strlen(tmp) != 5 || xmlStrcmp((const xmlChar *)"UTF-8",tmp)) {\r
-           xmlXPathReturnEmptyString(ctxt);\r
-           xmlFree(tmp);\r
-           return;\r
-       }\r
-       xmlFree(tmp);\r
-    }\r
-\r
-    escape_all = xmlXPathPopBoolean(ctxt);\r
-\r
-    str = xmlXPathPopString(ctxt);\r
-    str_len = xmlUTF8Strlen(str);\r
-\r
-    if (str_len == 0) {\r
-       xmlXPathReturnEmptyString(ctxt);\r
-       xmlFree(str);\r
-       return;\r
-    }\r
-\r
-    ret = xmlURIEscapeStr(str,(const xmlChar *)(escape_all?"-_.!~*'()":"-_.!~*'();/?:@&=+$,[]"));\r
-    xmlXPathReturnString(ctxt, ret);\r
-\r
-    if (str != NULL)\r
-       xmlFree(str);\r
-}\r
-\r
-/**\r
- * exsltStrDecodeUriFunction:\r
- * @ctxt: an XPath parser context\r
- * @nargs: the number of arguments\r
- *\r
- * reverses URI-Escaping of a string\r
- */\r
-static void\r
-exsltStrDecodeUriFunction (xmlXPathParserContextPtr ctxt, int nargs) {\r
-    int str_len = 0;\r
-    xmlChar *str = NULL, *ret = NULL, *tmp;\r
-\r
-    if ((nargs < 1) || (nargs > 2)) {\r
-       xmlXPathSetArityError(ctxt);\r
-       return;\r
-    }\r
-\r
-    if (nargs >= 2) {\r
-        /* check for UTF-8 if encoding was explicitly given;\r
-           we don't support anything else yet */\r
-        tmp = xmlXPathPopString(ctxt);\r
-        if (xmlUTF8Strlen(tmp) != 5 || xmlStrcmp((const xmlChar *)"UTF-8",tmp)) {\r
-           xmlXPathReturnEmptyString(ctxt);\r
-           xmlFree(tmp);\r
-           return;\r
-       }\r
-       xmlFree(tmp);\r
-    }\r
-\r
-    str = xmlXPathPopString(ctxt);\r
-    str_len = xmlUTF8Strlen(str);\r
-\r
-    if (str_len == 0) {\r
-       xmlXPathReturnEmptyString(ctxt);\r
-       xmlFree(str);\r
-       return;\r
-    }\r
-\r
-    ret = (xmlChar *) xmlURIUnescapeString((const char *)str,0,NULL);\r
-    if (!xmlCheckUTF8(ret)) {\r
-       /* FIXME: instead of throwing away the whole URI, we should\r
-        only discard the invalid sequence(s). How to do that? */\r
-       xmlXPathReturnEmptyString(ctxt);\r
-       xmlFree(str);\r
-       xmlFree(ret);\r
-       return;\r
-    }\r
-    \r
-    xmlXPathReturnString(ctxt, ret);\r
-\r
-    if (str != NULL)\r
-       xmlFree(str);\r
-}\r
-\r
-/**\r
- * exsltStrPaddingFunction:\r
- * @ctxt: an XPath parser context\r
- * @nargs: the number of arguments\r
- *\r
- * Creates a padding string of a certain length.\r
- */\r
-static void\r
-exsltStrPaddingFunction (xmlXPathParserContextPtr ctxt, int nargs) {\r
-    int number, str_len = 0;\r
-    xmlChar *str = NULL, *ret = NULL, *tmp;\r
-\r
-    if ((nargs < 1) || (nargs > 2)) {\r
-       xmlXPathSetArityError(ctxt);\r
-       return;\r
-    }\r
-\r
-    if (nargs == 2) {\r
-       str = xmlXPathPopString(ctxt);\r
-       str_len = xmlUTF8Strlen(str);\r
-    }\r
-    if (str_len == 0) {\r
-       if (str != NULL) xmlFree(str);\r
-       str = xmlStrdup((const xmlChar *) " ");\r
-       str_len = 1;\r
-    }\r
-\r
-    number = (int) xmlXPathPopNumber(ctxt);\r
-\r
-    if (number <= 0) {\r
-       xmlXPathReturnEmptyString(ctxt);\r
-       xmlFree(str);\r
-       return;\r
-    }\r
-\r
-    while (number >= str_len) {\r
-       ret = xmlStrncat(ret, str, str_len);\r
-       number -= str_len;\r
-    }\r
-    tmp = xmlUTF8Strndup (str, number);\r
-    ret = xmlStrcat(ret, tmp);\r
-    if (tmp != NULL)\r
-       xmlFree (tmp);\r
-\r
-    xmlXPathReturnString(ctxt, ret);\r
-\r
-    if (str != NULL)\r
-       xmlFree(str);\r
-}\r
-\r
-/**\r
- * exsltStrAlignFunction:\r
- * @ctxt: an XPath parser context\r
- * @nargs: the number of arguments\r
- *\r
- * Aligns a string within another string.\r
- */\r
-static void\r
-exsltStrAlignFunction (xmlXPathParserContextPtr ctxt, int nargs) {\r
-    xmlChar *str, *padding, *alignment, *ret;\r
-    int str_l, padding_l;\r
-\r
-    if ((nargs < 2) || (nargs > 3)) {\r
-       xmlXPathSetArityError(ctxt);\r
-       return;\r
-    }\r
-\r
-    if (nargs == 3)\r
-       alignment = xmlXPathPopString(ctxt);\r
-    else\r
-       alignment = NULL;\r
-\r
-    padding = xmlXPathPopString(ctxt);\r
-    str = xmlXPathPopString(ctxt);\r
-\r
-    str_l = xmlUTF8Strlen (str);\r
-    padding_l = xmlUTF8Strlen (padding);\r
-\r
-    if (str_l == padding_l) {\r
-       xmlXPathReturnString (ctxt, str);\r
-       xmlFree(padding);\r
-       xmlFree(alignment);\r
-       return;\r
-    }\r
-\r
-    if (str_l > padding_l) {\r
-       ret = xmlUTF8Strndup (str, padding_l);\r
-    } else {\r
-       if (xmlStrEqual(alignment, (const xmlChar *) "right")) {\r
-           ret = xmlUTF8Strndup (padding, padding_l - str_l);\r
-           ret = xmlStrcat (ret, str);\r
-       } else if (xmlStrEqual(alignment, (const xmlChar *) "center")) {\r
-           int left = (padding_l - str_l) / 2;\r
-           int right_start;\r
-\r
-           ret = xmlUTF8Strndup (padding, left);\r
-           ret = xmlStrcat (ret, str);\r
-\r
-           right_start = xmlUTF8Strsize (padding, left + str_l);\r
-           ret = xmlStrcat (ret, padding + right_start);\r
-       } else {\r
-           int str_s;\r
-\r
-           str_s = xmlStrlen (str);\r
-           ret = xmlStrdup (str);\r
-           ret = xmlStrcat (ret, padding + str_s);\r
-       }\r
-    }\r
-\r
-    xmlXPathReturnString (ctxt, ret);\r
-\r
-    xmlFree(str);\r
-    xmlFree(padding);\r
-    xmlFree(alignment);\r
-}\r
-\r
-/**\r
- * exsltStrConcatFunction:\r
- * @ctxt: an XPath parser context\r
- * @nargs: the number of arguments\r
- *\r
- * Takes a node set and returns the concatenation of the string values\r
- * of the nodes in that node set.  If the node set is empty, it\r
- * returns an empty string.\r
- */\r
-static void\r
-exsltStrConcatFunction (xmlXPathParserContextPtr ctxt, int nargs) {\r
-    xmlXPathObjectPtr obj;\r
-    xmlChar *ret = NULL;\r
-    int i;\r
-\r
-    if (nargs  != 1) {\r
-       xmlXPathSetArityError(ctxt);\r
-       return;\r
-    }\r
-\r
-    if (!xmlXPathStackIsNodeSet(ctxt)) {\r
-       xmlXPathSetTypeError(ctxt);\r
-       return;\r
-    }\r
-\r
-    obj = valuePop (ctxt);\r
-\r
-    if (xmlXPathNodeSetIsEmpty(obj->nodesetval)) {\r
-       xmlXPathReturnEmptyString(ctxt);\r
-       return;\r
-    }\r
-\r
-    for (i = 0; i < obj->nodesetval->nodeNr; i++) {\r
-       xmlChar *tmp;\r
-       tmp = xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);\r
-\r
-       ret = xmlStrcat (ret, tmp);\r
-\r
-       xmlFree(tmp);\r
-    }\r
-\r
-    xmlXPathFreeObject (obj);\r
-\r
-    xmlXPathReturnString(ctxt, ret);\r
-}\r
-\r
-/**\r
- * exsltStrRegister:\r
- *\r
- * Registers the EXSLT - Strings module\r
- */\r
-\r
-void\r
-exsltStrRegister (void) {\r
-    xsltRegisterExtModuleFunction ((const xmlChar *) "tokenize",\r
-                                  EXSLT_STRINGS_NAMESPACE,\r
-                                  exsltStrTokenizeFunction);\r
-    xsltRegisterExtModuleFunction ((const xmlChar *) "split",\r
-                                  EXSLT_STRINGS_NAMESPACE,\r
-                                  exsltStrSplitFunction);\r
-    xsltRegisterExtModuleFunction ((const xmlChar *) "encode-uri",\r
-                                  EXSLT_STRINGS_NAMESPACE,\r
-                                  exsltStrEncodeUriFunction);\r
-    xsltRegisterExtModuleFunction ((const xmlChar *) "decode-uri",\r
-                                  EXSLT_STRINGS_NAMESPACE,\r
-                                  exsltStrDecodeUriFunction);\r
-    xsltRegisterExtModuleFunction ((const xmlChar *) "padding",\r
-                                  EXSLT_STRINGS_NAMESPACE,\r
-                                  exsltStrPaddingFunction);\r
-    xsltRegisterExtModuleFunction ((const xmlChar *) "align",\r
-                                  EXSLT_STRINGS_NAMESPACE,\r
-                                  exsltStrAlignFunction);\r
-    xsltRegisterExtModuleFunction ((const xmlChar *) "concat",\r
-                                  EXSLT_STRINGS_NAMESPACE,\r
-                                  exsltStrConcatFunction);\r
-}\r
+#define IN_LIBEXSLT
+#include "libexslt/libexslt.h"
+
+#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
+#include <win32config.h>
+#else
+#include "config.h"
+#endif
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/parser.h>
+#include <libxml/encoding.h>
+#include <libxml/uri.h>
+
+#include <libxslt/xsltconfig.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/extensions.h>
+
+#include "exslt.h"
+
+/**
+ * exsltStrTokenizeFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Splits up a string on the characters of the delimiter string and returns a
+ * node set of token elements, each containing one token from the string. 
+ */
+static void
+exsltStrTokenizeFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+    xsltTransformContextPtr tctxt;
+    xmlChar *str, *delimiters, *cur;
+    const xmlChar *token, *delimiter;
+    xmlNodePtr node;
+    xmlDocPtr container;
+    xmlXPathObjectPtr ret = NULL;
+    int clen;
+
+    if ((nargs < 1) || (nargs > 2)) {
+        xmlXPathSetArityError(ctxt);
+        return;
+    }
+
+    if (nargs == 2) {
+        delimiters = xmlXPathPopString(ctxt);
+        if (xmlXPathCheckError(ctxt))
+            return;
+    } else {
+        delimiters = xmlStrdup((const xmlChar *) "\t\r\n ");
+    }
+    if (delimiters == NULL)
+        return;
+
+    str = xmlXPathPopString(ctxt);
+    if (xmlXPathCheckError(ctxt) || (str == NULL)) {
+        xmlFree(delimiters);
+        return;
+    }
+
+    /* Return a result tree fragment */
+    tctxt = xsltXPathGetTransformContext(ctxt);
+    if (tctxt == NULL) {
+        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+             "exslt:tokenize : internal error tctxt == NULL\n");
+       goto fail;
+    }
+
+    container = xsltCreateRVT(tctxt);
+    if (container != NULL) {
+        xsltRegisterLocalRVT(tctxt, container);
+        ret = xmlXPathNewNodeSet(NULL);
+        if (ret != NULL) {
+            for (cur = str, token = str; *cur != 0; cur += clen) {
+               clen = xmlUTF8Size(cur);
+               if (*delimiters == 0) { /* empty string case */
+                   xmlChar ctmp;
+                   ctmp = *(cur+clen);
+                   *(cur+clen) = 0;
+                    node = xmlNewDocRawNode(container, NULL,
+                                       (const xmlChar *) "token", cur);
+                   xmlAddChild((xmlNodePtr) container, node);
+                   xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+                    *(cur+clen) = ctmp; /* restore the changed byte */
+                    token = cur + clen;
+                } else for (delimiter = delimiters; *delimiter != 0;
+                               delimiter += xmlUTF8Size(delimiter)) {
+                    if (!xmlUTF8Charcmp(cur, delimiter)) {
+                        if (cur == token) {
+                            /* discard empty tokens */
+                            token = cur + clen;
+                            break;
+                        }
+                        *cur = 0;      /* terminate the token */
+                        node = xmlNewDocRawNode(container, NULL,
+                                           (const xmlChar *) "token", token);
+                       xmlAddChild((xmlNodePtr) container, node);
+                       xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+                        *cur = *delimiter; /* restore the changed byte */
+                        token = cur + clen;
+                        break;
+                    }
+                }
+            }
+            if (token != cur) {
+               node = xmlNewDocRawNode(container, NULL,
+                                   (const xmlChar *) "token", token);
+                xmlAddChild((xmlNodePtr) container, node);
+               xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+            }
+        }
+    }
+
+fail:
+    if (str != NULL)
+        xmlFree(str);
+    if (delimiters != NULL)
+        xmlFree(delimiters);
+    if (ret != NULL)
+        valuePush(ctxt, ret);
+    else
+        valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+}
+
+/**
+ * exsltStrSplitFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Splits up a string on a delimiting string and returns a node set of token
+ * elements, each containing one token from the string. 
+ */
+static void
+exsltStrSplitFunction(xmlXPathParserContextPtr ctxt, int nargs) {
+    xsltTransformContextPtr tctxt;
+    xmlChar *str, *delimiter, *cur;
+    const xmlChar *token;
+    xmlNodePtr node;
+    xmlDocPtr container;
+    xmlXPathObjectPtr ret = NULL;
+    int delimiterLength;
+
+    if ((nargs < 1) || (nargs > 2)) {
+        xmlXPathSetArityError(ctxt);
+        return;
+    }
+
+    if (nargs == 2) {
+        delimiter = xmlXPathPopString(ctxt);
+        if (xmlXPathCheckError(ctxt))
+            return;
+    } else {
+        delimiter = xmlStrdup((const xmlChar *) " ");
+    }
+    if (delimiter == NULL)
+        return;
+    delimiterLength = xmlStrlen (delimiter);
+
+    str = xmlXPathPopString(ctxt);
+    if (xmlXPathCheckError(ctxt) || (str == NULL)) {
+        xmlFree(delimiter);
+        return;
+    }
+
+    /* Return a result tree fragment */
+    tctxt = xsltXPathGetTransformContext(ctxt);
+    if (tctxt == NULL) {
+        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+             "exslt:tokenize : internal error tctxt == NULL\n");
+       goto fail;
+    }
+
+    /*
+    * OPTIMIZE TODO: We are creating an xmlDoc for every split!
+    */
+    container = xsltCreateRVT(tctxt);
+    if (container != NULL) {
+        xsltRegisterLocalRVT(tctxt, container);
+        ret = xmlXPathNewNodeSet(NULL);
+        if (ret != NULL) {
+            for (cur = str, token = str; *cur != 0; cur++) {
+               if (delimiterLength == 0) {
+                   if (cur != token) {
+                       xmlChar tmp = *cur;
+                       *cur = 0;
+                        node = xmlNewDocRawNode(container, NULL,
+                                           (const xmlChar *) "token", token);
+                       xmlAddChild((xmlNodePtr) container, node);
+                       xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+                       *cur = tmp;
+                       token++;
+                   }
+               }
+               else if (!xmlStrncasecmp(cur, delimiter, delimiterLength)) {
+                   if (cur == token) {
+                       /* discard empty tokens */
+                       cur = cur + delimiterLength - 1;
+                       token = cur + 1;
+                       continue;
+                   }
+                   *cur = 0;
+                   node = xmlNewDocRawNode(container, NULL,
+                                      (const xmlChar *) "token", token);
+                   xmlAddChild((xmlNodePtr) container, node);
+                   xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+                   *cur = *delimiter;
+                   cur = cur + delimiterLength - 1;
+                   token = cur + 1;
+                }
+            }
+           if (token != cur) {
+               node = xmlNewDocRawNode(container, NULL,
+                                  (const xmlChar *) "token", token);
+               xmlAddChild((xmlNodePtr) container, node);
+               xmlXPathNodeSetAddUnique(ret->nodesetval, node);
+           }
+        }
+    }
+
+fail:
+    if (str != NULL)
+        xmlFree(str);
+    if (delimiter != NULL)
+        xmlFree(delimiter);
+    if (ret != NULL)
+        valuePush(ctxt, ret);
+    else
+        valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+}
+
+/**
+ * exsltStrEncodeUriFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * URI-Escapes a string
+ */
+static void
+exsltStrEncodeUriFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+    int escape_all = 1, str_len = 0;
+    xmlChar *str = NULL, *ret = NULL, *tmp;
+
+    if ((nargs < 2) || (nargs > 3)) {
+       xmlXPathSetArityError(ctxt);
+       return;
+    }
+
+    if (nargs >= 3) {
+        /* check for UTF-8 if encoding was explicitly given;
+           we don't support anything else yet */
+        tmp = xmlXPathPopString(ctxt);
+        if (xmlUTF8Strlen(tmp) != 5 || xmlStrcmp((const xmlChar *)"UTF-8",tmp)) {
+           xmlXPathReturnEmptyString(ctxt);
+           xmlFree(tmp);
+           return;
+       }
+       xmlFree(tmp);
+    }
+
+    escape_all = xmlXPathPopBoolean(ctxt);
+
+    str = xmlXPathPopString(ctxt);
+    str_len = xmlUTF8Strlen(str);
+
+    if (str_len == 0) {
+       xmlXPathReturnEmptyString(ctxt);
+       xmlFree(str);
+       return;
+    }
+
+    ret = xmlURIEscapeStr(str,(const xmlChar *)(escape_all?"-_.!~*'()":"-_.!~*'();/?:@&=+$,[]"));
+    xmlXPathReturnString(ctxt, ret);
+
+    if (str != NULL)
+       xmlFree(str);
+}
+
+/**
+ * exsltStrDecodeUriFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * reverses URI-Escaping of a string
+ */
+static void
+exsltStrDecodeUriFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+    int str_len = 0;
+    xmlChar *str = NULL, *ret = NULL, *tmp;
+
+    if ((nargs < 1) || (nargs > 2)) {
+       xmlXPathSetArityError(ctxt);
+       return;
+    }
+
+    if (nargs >= 2) {
+        /* check for UTF-8 if encoding was explicitly given;
+           we don't support anything else yet */
+        tmp = xmlXPathPopString(ctxt);
+        if (xmlUTF8Strlen(tmp) != 5 || xmlStrcmp((const xmlChar *)"UTF-8",tmp)) {
+           xmlXPathReturnEmptyString(ctxt);
+           xmlFree(tmp);
+           return;
+       }
+       xmlFree(tmp);
+    }
+
+    str = xmlXPathPopString(ctxt);
+    str_len = xmlUTF8Strlen(str);
+
+    if (str_len == 0) {
+       xmlXPathReturnEmptyString(ctxt);
+       xmlFree(str);
+       return;
+    }
+
+    ret = (xmlChar *) xmlURIUnescapeString((const char *)str,0,NULL);
+    if (!xmlCheckUTF8(ret)) {
+       /* FIXME: instead of throwing away the whole URI, we should
+        only discard the invalid sequence(s). How to do that? */
+       xmlXPathReturnEmptyString(ctxt);
+       xmlFree(str);
+       xmlFree(ret);
+       return;
+    }
+    
+    xmlXPathReturnString(ctxt, ret);
+
+    if (str != NULL)
+       xmlFree(str);
+}
+
+/**
+ * exsltStrPaddingFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Creates a padding string of a certain length.
+ */
+static void
+exsltStrPaddingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+    int number, str_len = 0;
+    xmlChar *str = NULL, *ret = NULL, *tmp;
+
+    if ((nargs < 1) || (nargs > 2)) {
+       xmlXPathSetArityError(ctxt);
+       return;
+    }
+
+    if (nargs == 2) {
+       str = xmlXPathPopString(ctxt);
+       str_len = xmlUTF8Strlen(str);
+    }
+    if (str_len == 0) {
+       if (str != NULL) xmlFree(str);
+       str = xmlStrdup((const xmlChar *) " ");
+       str_len = 1;
+    }
+
+    number = (int) xmlXPathPopNumber(ctxt);
+
+    if (number <= 0) {
+       xmlXPathReturnEmptyString(ctxt);
+       xmlFree(str);
+       return;
+    }
+
+    while (number >= str_len) {
+       ret = xmlStrncat(ret, str, str_len);
+       number -= str_len;
+    }
+    tmp = xmlUTF8Strndup (str, number);
+    ret = xmlStrcat(ret, tmp);
+    if (tmp != NULL)
+       xmlFree (tmp);
+
+    xmlXPathReturnString(ctxt, ret);
+
+    if (str != NULL)
+       xmlFree(str);
+}
+
+/**
+ * exsltStrAlignFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Aligns a string within another string.
+ */
+static void
+exsltStrAlignFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+    xmlChar *str, *padding, *alignment, *ret;
+    int str_l, padding_l;
+
+    if ((nargs < 2) || (nargs > 3)) {
+       xmlXPathSetArityError(ctxt);
+       return;
+    }
+
+    if (nargs == 3)
+       alignment = xmlXPathPopString(ctxt);
+    else
+       alignment = NULL;
+
+    padding = xmlXPathPopString(ctxt);
+    str = xmlXPathPopString(ctxt);
+
+    str_l = xmlUTF8Strlen (str);
+    padding_l = xmlUTF8Strlen (padding);
+
+    if (str_l == padding_l) {
+       xmlXPathReturnString (ctxt, str);
+       xmlFree(padding);
+       xmlFree(alignment);
+       return;
+    }
+
+    if (str_l > padding_l) {
+       ret = xmlUTF8Strndup (str, padding_l);
+    } else {
+       if (xmlStrEqual(alignment, (const xmlChar *) "right")) {
+           ret = xmlUTF8Strndup (padding, padding_l - str_l);
+           ret = xmlStrcat (ret, str);
+       } else if (xmlStrEqual(alignment, (const xmlChar *) "center")) {
+           int left = (padding_l - str_l) / 2;
+           int right_start;
+
+           ret = xmlUTF8Strndup (padding, left);
+           ret = xmlStrcat (ret, str);
+
+           right_start = xmlUTF8Strsize (padding, left + str_l);
+           ret = xmlStrcat (ret, padding + right_start);
+       } else {
+           int str_s;
+
+           str_s = xmlStrlen (str);
+           ret = xmlStrdup (str);
+           ret = xmlStrcat (ret, padding + str_s);
+       }
+    }
+
+    xmlXPathReturnString (ctxt, ret);
+
+    xmlFree(str);
+    xmlFree(padding);
+    xmlFree(alignment);
+}
+
+/**
+ * exsltStrConcatFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Takes a node set and returns the concatenation of the string values
+ * of the nodes in that node set.  If the node set is empty, it
+ * returns an empty string.
+ */
+static void
+exsltStrConcatFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+    xmlXPathObjectPtr obj;
+    xmlChar *ret = NULL;
+    int i;
+
+    if (nargs  != 1) {
+       xmlXPathSetArityError(ctxt);
+       return;
+    }
+
+    if (!xmlXPathStackIsNodeSet(ctxt)) {
+       xmlXPathSetTypeError(ctxt);
+       return;
+    }
+
+    obj = valuePop (ctxt);
+
+    if (xmlXPathNodeSetIsEmpty(obj->nodesetval)) {
+       xmlXPathReturnEmptyString(ctxt);
+       return;
+    }
+
+    for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+       xmlChar *tmp;
+       tmp = xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
+
+       ret = xmlStrcat (ret, tmp);
+
+       xmlFree(tmp);
+    }
+
+    xmlXPathFreeObject (obj);
+
+    xmlXPathReturnString(ctxt, ret);
+}
+
+/**
+ * exsltStrRegister:
+ *
+ * Registers the EXSLT - Strings module
+ */
+
+void
+exsltStrRegister (void) {
+    xsltRegisterExtModuleFunction ((const xmlChar *) "tokenize",
+                                  EXSLT_STRINGS_NAMESPACE,
+                                  exsltStrTokenizeFunction);
+    xsltRegisterExtModuleFunction ((const xmlChar *) "split",
+                                  EXSLT_STRINGS_NAMESPACE,
+                                  exsltStrSplitFunction);
+    xsltRegisterExtModuleFunction ((const xmlChar *) "encode-uri",
+                                  EXSLT_STRINGS_NAMESPACE,
+                                  exsltStrEncodeUriFunction);
+    xsltRegisterExtModuleFunction ((const xmlChar *) "decode-uri",
+                                  EXSLT_STRINGS_NAMESPACE,
+                                  exsltStrDecodeUriFunction);
+    xsltRegisterExtModuleFunction ((const xmlChar *) "padding",
+                                  EXSLT_STRINGS_NAMESPACE,
+                                  exsltStrPaddingFunction);
+    xsltRegisterExtModuleFunction ((const xmlChar *) "align",
+                                  EXSLT_STRINGS_NAMESPACE,
+                                  exsltStrAlignFunction);
+    xsltRegisterExtModuleFunction ((const xmlChar *) "concat",
+                                  EXSLT_STRINGS_NAMESPACE,
+                                  exsltStrConcatFunction);
+}
index 795e797..168dae6 100644 (file)
-/*\r
- * attributes.c: Implementation of the XSLT attributes handling\r
- *\r
- * Reference:\r
- *   http://www.w3.org/TR/1999/REC-xslt-19991116\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * daniel@veillard.com\r
- */\r
-\r
-#define IN_LIBXSLT\r
-#include "libxslt.h"\r
-\r
-#include <string.h>\r
-\r
-#ifdef HAVE_SYS_TYPES_H\r
-#include <sys/types.h>\r
-#endif\r
-#ifdef HAVE_MATH_H\r
-#include <math.h>\r
-#endif\r
-#ifdef HAVE_FLOAT_H\r
-#include <float.h>\r
-#endif\r
-#ifdef HAVE_IEEEFP_H\r
-#include <ieeefp.h>\r
-#endif\r
-#ifdef HAVE_NAN_H\r
-#include <nan.h>\r
-#endif\r
-#ifdef HAVE_CTYPE_H\r
-#include <ctype.h>\r
-#endif\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/tree.h>\r
-#include <libxml/hash.h>\r
-#include <libxml/xmlerror.h>\r
-#include <libxml/uri.h>\r
-#include <libxml/parserInternals.h>\r
-#include "xslt.h"\r
-#include "xsltInternals.h"\r
-#include "xsltutils.h"\r
-#include "attributes.h"\r
-#include "namespaces.h"\r
-#include "templates.h"\r
-#include "imports.h"\r
-#include "transform.h"\r
-#include "preproc.h"\r
-\r
-#define WITH_XSLT_DEBUG_ATTRIBUTES\r
-#ifdef WITH_XSLT_DEBUG\r
-#define WITH_XSLT_DEBUG_ATTRIBUTES\r
-#endif\r
-\r
-/*\r
- * TODO: merge attribute sets from different import precedence.\r
- *       all this should be precomputed just before the transformation\r
- *       starts or at first hit with a cache in the context.\r
- *       The simple way for now would be to not allow redefinition of\r
- *       attributes once generated in the output tree, possibly costlier.\r
- */\r
-\r
-/*\r
- * Useful macros\r
- */\r
-#ifdef IS_BLANK\r
-#undef IS_BLANK\r
-#endif\r
-\r
-#define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \\r
-                     ((c) == 0x0D))\r
-\r
-#define IS_BLANK_NODE(n)                                               \\r
-    (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))\r
-\r
-\r
-/*\r
- * The in-memory structure corresponding to an XSLT Attribute in\r
- * an attribute set\r
- */\r
-\r
-\r
-typedef struct _xsltAttrElem xsltAttrElem;\r
-typedef xsltAttrElem *xsltAttrElemPtr;\r
-struct _xsltAttrElem {\r
-    struct _xsltAttrElem *next;/* chained list */\r
-    xmlNodePtr attr;   /* the xsl:attribute definition */\r
-    const xmlChar *set; /* or the attribute set */\r
-    const xmlChar *ns;  /* and its namespace */\r
-};\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     XSLT Attribute handling                         *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltNewAttrElem:\r
- * @attr:  the new xsl:attribute node\r
- *\r
- * Create a new XSLT AttrElem\r
- *\r
- * Returns the newly allocated xsltAttrElemPtr or NULL in case of error\r
- */\r
-static xsltAttrElemPtr\r
-xsltNewAttrElem(xmlNodePtr attr) {\r
-    xsltAttrElemPtr cur;\r
-\r
-    cur = (xsltAttrElemPtr) xmlMalloc(sizeof(xsltAttrElem));\r
-    if (cur == NULL) {\r
-        xsltGenericError(xsltGenericErrorContext,\r
-               "xsltNewAttrElem : malloc failed\n");\r
-       return(NULL);\r
-    }\r
-    memset(cur, 0, sizeof(xsltAttrElem));\r
-    cur->attr = attr;\r
-    return(cur);\r
-}\r
-\r
-/**\r
- * xsltFreeAttrElem:\r
- * @attr:  an XSLT AttrElem\r
- *\r
- * Free up the memory allocated by @attr\r
- */\r
-static void\r
-xsltFreeAttrElem(xsltAttrElemPtr attr) {\r
-    xmlFree(attr);\r
-}\r
-\r
-/**\r
- * xsltFreeAttrElemList:\r
- * @list:  an XSLT AttrElem list\r
- *\r
- * Free up the memory allocated by @list\r
- */\r
-static void\r
-xsltFreeAttrElemList(xsltAttrElemPtr list) {\r
-    xsltAttrElemPtr next;\r
-    \r
-    while (list != NULL) {\r
-       next = list->next;\r
-       xsltFreeAttrElem(list);\r
-       list = next;\r
-    }\r
-}\r
-\r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * This was moved to xsltParseStylesheetAttributeSet().\r
-    */\r
-#else\r
-/**\r
- * xsltAddAttrElemList:\r
- * @list:  an XSLT AttrElem list\r
- * @attr:  the new xsl:attribute node\r
- *\r
- * Add the new attribute to the list.\r
- *\r
- * Returns the new list pointer\r
- */\r
-static xsltAttrElemPtr\r
-xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) {\r
-    xsltAttrElemPtr next, cur;\r
-\r
-    if (attr == NULL)\r
-       return(list);\r
-    if (list == NULL)\r
-       return(xsltNewAttrElem(attr));\r
-    cur = list;\r
-    while (cur != NULL) {      \r
-       next = cur->next;\r
-       if (cur->attr == attr)\r
-           return(cur);\r
-       if (cur->next == NULL) {\r
-           cur->next = xsltNewAttrElem(attr);\r
-           return(list);\r
-       }\r
-       cur = next;\r
-    }\r
-    return(list);\r
-}\r
-#endif /* XSLT_REFACTORED */\r
-\r
-/**\r
- * xsltMergeAttrElemList:\r
- * @list:  an XSLT AttrElem list\r
- * @old:  another XSLT AttrElem list\r
- *\r
- * Add all the attributes from list @old to list @list,\r
- * but drop redefinition of existing values.\r
- *\r
- * Returns the new list pointer\r
- */\r
-static xsltAttrElemPtr\r
-xsltMergeAttrElemList(xsltStylesheetPtr style,\r
-                     xsltAttrElemPtr list, xsltAttrElemPtr old) {\r
-    xsltAttrElemPtr cur;\r
-    int add;\r
-\r
-    while (old != NULL) {\r
-       if ((old->attr == NULL) && (old->set == NULL)) {\r
-           old = old->next;\r
-           continue;\r
-       }\r
-       /*\r
-        * Check that the attribute is not yet in the list\r
-        */\r
-       cur = list;\r
-       add = 1;\r
-       while (cur != NULL) {\r
-           if ((cur->attr == NULL) && (cur->set == NULL)) {\r
-               if (cur->next == NULL)\r
-                   break;\r
-               cur = cur->next;\r
-               continue;\r
-           }\r
-           if ((cur->set != NULL) && (cur->set == old->set)) {\r
-               add = 0;\r
-               break;\r
-           }\r
-           if (cur->set != NULL) {\r
-               if (cur->next == NULL)\r
-                   break;\r
-               cur = cur->next;\r
-               continue;\r
-           }\r
-           if (old->set != NULL) {\r
-               if (cur->next == NULL)\r
-                   break;\r
-               cur = cur->next;\r
-               continue;\r
-           }\r
-           if (cur->attr == old->attr) {\r
-               xsltGenericError(xsltGenericErrorContext,\r
-            "xsl:attribute-set : use-attribute-sets recursion detected\n");\r
-               return(list);\r
-           }\r
-           if (cur->next == NULL)\r
-               break;\r
-            cur = cur->next;\r
-       }\r
-\r
-       if (add == 1) {\r
-           /*\r
-           * Changed to use the string-dict, rather than duplicating\r
-           * @set and @ns; this fixes bug #340400.\r
-           */\r
-           if (cur == NULL) {\r
-               list = xsltNewAttrElem(old->attr);\r
-               if (old->set != NULL) {\r
-                   list->set = xmlDictLookup(style->dict, old->set, -1);\r
-                   if (old->ns != NULL)\r
-                       list->ns = xmlDictLookup(style->dict, old->ns, -1);\r
-               }\r
-           } else if (add) {\r
-               cur->next = xsltNewAttrElem(old->attr);\r
-               if (old->set != NULL) {\r
-                   cur->next->set = xmlDictLookup(style->dict, old->set, -1);\r
-                   if (old->ns != NULL)\r
-                       cur->next->ns = xmlDictLookup(style->dict, old->ns, -1);\r
-               }\r
-           }\r
-       }\r
-\r
-       old = old->next;\r
-    }\r
-    return(list);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Module interfaces                               *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltParseStylesheetAttributeSet:\r
- * @style:  the XSLT stylesheet\r
- * @cur:  the "attribute-set" element\r
- *\r
- * parse an XSLT stylesheet attribute-set element\r
- */\r
-\r
-void\r
-xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {\r
-    const xmlChar *ncname;\r
-    const xmlChar *prefix;\r
-    xmlChar *value;\r
-    xmlNodePtr child;\r
-    xsltAttrElemPtr attrItems;\r
-\r
-    if ((cur == NULL) || (style == NULL))\r
-       return;\r
-\r
-    value = xmlGetNsProp(cur, (const xmlChar *)"name", NULL);\r
-    if (value == NULL) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-            "xsl:attribute-set : name is missing\n");\r
-       return;\r
-    }\r
-\r
-    ncname = xsltSplitQName(style->dict, value, &prefix);\r
-    xmlFree(value);\r
-    value = NULL;\r
-\r
-    if (style->attributeSets == NULL) {\r
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-           "creating attribute set table\n");\r
-#endif\r
-       style->attributeSets = xmlHashCreate(10);\r
-    }\r
-    if (style->attributeSets == NULL)\r
-       return;\r
-\r
-    attrItems = xmlHashLookup2(style->attributeSets, ncname, prefix);\r
-\r
-    /*\r
-    * Parse the content. Only xsl:attribute elements are allowed.\r
-    */\r
-    child = cur->children;\r
-    while (child != NULL) {\r
-       /*\r
-       * Report invalid nodes.\r
-       */\r
-       if ((child->type != XML_ELEMENT_NODE) ||\r
-           (child->ns == NULL) ||\r
-           (! IS_XSLT_ELEM(child)))\r
-       {\r
-           if (child->type == XML_ELEMENT_NODE)\r
-               xsltTransformError(NULL, style, child,\r
-                       "xsl:attribute-set : unexpected child %s\n",\r
-                                child->name);\r
-           else\r
-               xsltTransformError(NULL, style, child,\r
-                       "xsl:attribute-set : child of unexpected type\n");\r
-       } else if (!IS_XSLT_NAME(child, "attribute")) {\r
-           xsltTransformError(NULL, style, child,\r
-               "xsl:attribute-set : unexpected child xsl:%s\n",\r
-               child->name);\r
-       } else {\r
-#ifdef XSLT_REFACTORED\r
-           xsltAttrElemPtr nextAttr, curAttr;\r
-\r
-           /*\r
-           * Process xsl:attribute\r
-           * ---------------------\r
-           */\r
-\r
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-               "add attribute to list %s\n", ncname);\r
-#endif\r
-           /*\r
-           * The following was taken over from\r
-           * xsltAddAttrElemList().\r
-           */\r
-           if (attrItems == NULL) {\r
-               attrItems = xsltNewAttrElem(child);\r
-           } else {\r
-               curAttr = attrItems;\r
-               while (curAttr != NULL) {\r
-                   nextAttr = curAttr->next;\r
-                   if (curAttr->attr == child) {\r
-                       /*\r
-                       * URGENT TODO: Can somebody explain\r
-                       *  why attrItems is set to curAttr\r
-                       *  here? Is this somehow related to\r
-                       *  avoidance of recursions?\r
-                       */\r
-                       attrItems = curAttr;\r
-                       goto next_child;\r
-                   }\r
-                   if (curAttr->next == NULL)                  \r
-                       curAttr->next = xsltNewAttrElem(child);\r
-                   curAttr = nextAttr;\r
-               }\r
-           }\r
-           /*\r
-           * Parse the xsl:attribute and its content.\r
-           */\r
-           xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);\r
-#else\r
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-               "add attribute to list %s\n", ncname);\r
-#endif\r
-           /*\r
-           * OLD behaviour:\r
-           */\r
-           attrItems = xsltAddAttrElemList(attrItems, child);\r
-#endif\r
-       }\r
-\r
-#ifdef XSLT_REFACTORED\r
-next_child:\r
-#endif\r
-       child = child->next;\r
-    }\r
-\r
-    /*\r
-    * Process attribue "use-attribute-sets".\r
-    */\r
-    /* TODO check recursion */    \r
-    value = xmlGetNsProp(cur, (const xmlChar *)"use-attribute-sets",\r
-       NULL);\r
-    if (value != NULL) {\r
-       const xmlChar *curval, *endval;\r
-       curval = value;\r
-       while (*curval != 0) {\r
-           while (IS_BLANK(*curval)) curval++;\r
-           if (*curval == 0)\r
-               break;\r
-           endval = curval;\r
-           while ((*endval != 0) && (!IS_BLANK(*endval))) endval++;\r
-           curval = xmlDictLookup(style->dict, curval, endval - curval);\r
-           if (curval) {\r
-               const xmlChar *ncname2 = NULL;\r
-               const xmlChar *prefix2 = NULL;\r
-               xsltAttrElemPtr refAttrItems;\r
-               \r
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES\r
-               xsltGenericDebug(xsltGenericDebugContext,\r
-                   "xsl:attribute-set : %s adds use %s\n", ncname, curval);\r
-#endif\r
-               ncname2 = xsltSplitQName(style->dict, curval, &prefix2);\r
-               refAttrItems = xsltNewAttrElem(NULL);\r
-               if (refAttrItems != NULL) {\r
-                   refAttrItems->set = ncname2;\r
-                   refAttrItems->ns = prefix2;\r
-                   attrItems = xsltMergeAttrElemList(style,\r
-                       attrItems, refAttrItems);\r
-                   xsltFreeAttrElem(refAttrItems);\r
-               }\r
-           }\r
-           curval = endval;\r
-       }\r
-       xmlFree(value);\r
-       value = NULL;\r
-    }\r
-\r
-    /*\r
-     * Update the value\r
-     */\r
-    /*\r
-    * TODO: Why is this dummy entry needed.?\r
-    */\r
-    if (attrItems == NULL)\r
-       attrItems = xsltNewAttrElem(NULL);\r
-    xmlHashUpdateEntry2(style->attributeSets, ncname, prefix, attrItems, NULL);\r
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "updated attribute list %s\n", ncname);\r
-#endif\r
-}\r
-\r
-/**\r
- * xsltGetSAS:\r
- * @style:  the XSLT stylesheet\r
- * @name:  the attribute list name\r
- * @ns:  the attribute list namespace\r
- *\r
- * lookup an attribute set based on the style cascade\r
- *\r
- * Returns the attribute set or NULL\r
- */\r
-static xsltAttrElemPtr\r
-xsltGetSAS(xsltStylesheetPtr style, const xmlChar *name, const xmlChar *ns) {\r
-    xsltAttrElemPtr values;\r
-\r
-    while (style != NULL) {\r
-       values = xmlHashLookup2(style->attributeSets, name, ns);\r
-       if (values != NULL)\r
-           return(values);\r
-       style = xsltNextImport(style);\r
-    }\r
-    return(NULL);\r
-}\r
-\r
-/**\r
- * xsltResolveSASCallback,:\r
- * @style:  the XSLT stylesheet\r
- *\r
- * resolve the references in an attribute set.\r
- */\r
-static void\r
-xsltResolveSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,\r
-                      const xmlChar *name, const xmlChar *ns,\r
-                      ATTRIBUTE_UNUSED const xmlChar *ignored) {\r
-    xsltAttrElemPtr tmp;\r
-    xsltAttrElemPtr refs;\r
-\r
-    tmp = values;\r
-    while (tmp != NULL) {\r
-       if (tmp->set != NULL) {\r
-           /*\r
-            * Check against cycles !\r
-            */\r
-           if ((xmlStrEqual(name, tmp->set)) && (xmlStrEqual(ns, tmp->ns))) {\r
-               xsltGenericError(xsltGenericErrorContext,\r
-     "xsl:attribute-set : use-attribute-sets recursion detected on %s\n",\r
-                                 name);\r
-           } else {\r
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES\r
-               xsltGenericDebug(xsltGenericDebugContext,\r
-                       "Importing attribute list %s\n", tmp->set);\r
-#endif\r
-\r
-               refs = xsltGetSAS(style, tmp->set, tmp->ns);\r
-               if (refs == NULL) {\r
-                   xsltGenericError(xsltGenericErrorContext,\r
-     "xsl:attribute-set : use-attribute-sets %s reference missing %s\n",\r
-                                    name, tmp->set);\r
-               } else {\r
-                   /*\r
-                    * recurse first for cleanup\r
-                    */\r
-                   xsltResolveSASCallback(refs, style, name, ns, NULL);\r
-                   /*\r
-                    * Then merge\r
-                    */\r
-                   xsltMergeAttrElemList(style, values, refs);\r
-                   /*\r
-                    * Then suppress the reference\r
-                    */\r
-                   tmp->set = NULL;\r
-                   tmp->ns = NULL;\r
-               }\r
-           }\r
-       }\r
-       tmp = tmp->next;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltMergeSASCallback,:\r
- * @style:  the XSLT stylesheet\r
- *\r
- * Merge an attribute set from an imported stylesheet.\r
- */\r
-static void\r
-xsltMergeSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,\r
-                      const xmlChar *name, const xmlChar *ns,\r
-                      ATTRIBUTE_UNUSED const xmlChar *ignored) {\r
-    int ret;\r
-    xsltAttrElemPtr topSet;\r
-\r
-    ret = xmlHashAddEntry2(style->attributeSets, name, ns, values);\r
-    if (ret < 0) {\r
-       /*\r
-        * Add failed, this attribute set can be removed.\r
-        */\r
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-               "attribute set %s present already in top stylesheet"\r
-               " - merging\n", name);\r
-#endif\r
-       topSet = xmlHashLookup2(style->attributeSets, name, ns);\r
-       if (topSet==NULL) {\r
-           xsltGenericError(xsltGenericErrorContext,\r
-               "xsl:attribute-set : logic error merging from imports for"\r
-               " attribute-set %s\n", name);\r
-       } else {\r
-           topSet = xsltMergeAttrElemList(style, topSet, values);\r
-           xmlHashUpdateEntry2(style->attributeSets, name, ns, topSet, NULL);\r
-       }\r
-       xsltFreeAttrElemList(values);\r
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES\r
-    } else {\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-               "attribute set %s moved to top stylesheet\n",\r
-                        name);\r
-#endif\r
-    }\r
-}\r
-\r
-/**\r
- * xsltResolveStylesheetAttributeSet:\r
- * @style:  the XSLT stylesheet\r
- *\r
- * resolve the references between attribute sets.\r
- */\r
-void\r
-xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style) {\r
-    xsltStylesheetPtr cur;\r
-\r
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-           "Resolving attribute sets references\n");\r
-#endif\r
-    /*\r
-     * First aggregate all the attribute sets definitions from the imports\r
-     */\r
-    cur = xsltNextImport(style);\r
-    while (cur != NULL) {\r
-       if (cur->attributeSets != NULL) {\r
-           if (style->attributeSets == NULL) {\r
-#ifdef WITH_XSLT_DEBUG_ATTRIBUTES\r
-               xsltGenericDebug(xsltGenericDebugContext,\r
-                   "creating attribute set table\n");\r
-#endif\r
-               style->attributeSets = xmlHashCreate(10);\r
-           }\r
-           xmlHashScanFull(cur->attributeSets, \r
-               (xmlHashScannerFull) xsltMergeSASCallback, style);\r
-           /*\r
-            * the attribute lists have either been migrated to style\r
-            * or freed directly in xsltMergeSASCallback()\r
-            */\r
-           xmlHashFree(cur->attributeSets, NULL);\r
-           cur->attributeSets = NULL;\r
-       }\r
-       cur = xsltNextImport(cur);\r
-    }\r
-\r
-    /*\r
-     * Then resolve all the references and computes the resulting sets\r
-     */\r
-    if (style->attributeSets != NULL) {\r
-       xmlHashScanFull(style->attributeSets, \r
-               (xmlHashScannerFull) xsltResolveSASCallback, style);\r
-    }\r
-}\r
-\r
-/**\r
- * xsltAttributeInternal:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the current node in the source tree\r
- * @inst:  the xsl:attribute element\r
- * @comp:  precomputed information\r
- * @fromAttributeSet:  the attribute comes from an attribute-set\r
- *\r
- * Process the xslt attribute node on the source node\r
- */\r
-static void\r
-xsltAttributeInternal(xsltTransformContextPtr ctxt,\r
-                     xmlNodePtr contextNode,\r
-                      xmlNodePtr inst,\r
-                     xsltStylePreCompPtr castedComp,\r
-                      int fromAttributeSet)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemAttributePtr comp =\r
-       (xsltStyleItemAttributePtr) castedComp;   \r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif\r
-    xmlNodePtr targetElem;\r
-    xmlChar *prop = NULL;    \r
-    const xmlChar *name = NULL, *prefix = NULL, *nsName = NULL;\r
-    xmlChar *value = NULL;\r
-    xmlNsPtr ns = NULL;\r
-    xmlAttrPtr attr;    \r
-\r
-    if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))\r
-        return;\r
-\r
-    /* \r
-    * A comp->has_name == 0 indicates that we need to skip this instruction,\r
-    * since it was evaluated to be invalid already during compilation.\r
-    */\r
-    if (!comp->has_name)\r
-        return;\r
-    /*\r
-    * BIG NOTE: This previously used xsltGetSpecialNamespace() and\r
-    *  xsltGetNamespace(), but since both are not appropriate, we\r
-    *  will process namespace lookup here to avoid adding yet another\r
-    *  ns-lookup function to namespaces.c.\r
-    */\r
-    /*\r
-    * SPEC XSLT 1.0: Error cases:\r
-    * - Creating nodes other than text nodes during the instantiation of\r
-    *   the content of the xsl:attribute element; implementations may\r
-    *   either signal the error or ignore the offending nodes."\r
-    */\r
-\r
-    if (comp == NULL) {\r
-        xsltTransformError(ctxt, NULL, inst,\r
-           "Internal error in xsltAttributeInternal(): "\r
-           "The XSLT 'attribute' instruction was not compiled.\n");\r
-        return;\r
-    }\r
-    /*\r
-    * TODO: Shouldn't ctxt->insert == NULL be treated as an internal error?\r
-    *   So report an internal error?\r
-    */\r
-    if (ctxt->insert == NULL)\r
-        return;    \r
-    /*\r
-    * SPEC XSLT 1.0:\r
-    *  "Adding an attribute to a node that is not an element;\r
-    *  implementations may either signal the error or ignore the attribute."\r
-    *\r
-    * TODO: I think we should signal such errors in the future, and maybe\r
-    *  provide an option to ignore such errors.\r
-    */\r
-    targetElem = ctxt->insert;\r
-    if (targetElem->type != XML_ELEMENT_NODE)\r
-       return;\r
-    \r
-    /*\r
-    * SPEC XSLT 1.0:\r
-    * "Adding an attribute to an element after children have been added\r
-    *  to it; implementations may either signal the error or ignore the\r
-    *  attribute."\r
-    *\r
-    * TODO: We should decide whether not to report such errors or\r
-    *  to ignore them; note that we *ignore* if the parent is not an\r
-    *  element, but here we report an error.\r
-    */\r
-    if (targetElem->children != NULL) {\r
-       /*\r
-       * NOTE: Ah! This seems to be intended to support streamed\r
-       *  result generation!.\r
-       */\r
-        xsltTransformError(ctxt, NULL, inst,\r
-           "xsl:attribute: Cannot add attributes to an "\r
-           "element if children have been already added "\r
-           "to the element.\n");\r
-        return;\r
-    }\r
-\r
-    /*\r
-    * Process the name\r
-    * ----------------\r
-    */    \r
-\r
-#ifdef WITH_DEBUGGER\r
-    if (ctxt->debugStatus != XSLT_DEBUG_NONE)\r
-        xslHandleDebugger(inst, contextNode, NULL, ctxt);\r
-#endif\r
-\r
-    if (comp->name == NULL) {\r
-       /* TODO: fix attr acquisition wrt to the XSLT namespace */\r
-        prop = xsltEvalAttrValueTemplate(ctxt, inst,\r
-           (const xmlChar *) "name", XSLT_NAMESPACE);\r
-        if (prop == NULL) {\r
-            xsltTransformError(ctxt, NULL, inst,\r
-               "xsl:attribute: The attribute 'name' is missing.\n");\r
-            goto error;\r
-        }\r
-       if (xmlValidateQName(prop, 0)) {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-               "xsl:attribute: The effective name '%s' is not a "\r
-               "valid QName.\n", prop);\r
-           /* we fall through to catch any further errors, if possible */\r
-       }\r
-       name = xsltSplitQName(ctxt->dict, prop, &prefix);\r
-       xmlFree(prop);\r
-\r
-       /*\r
-       * Reject a prefix of "xmlns".\r
-       */\r
-       if ((prefix != NULL) &&\r
-           (!xmlStrncasecmp(prefix, (xmlChar *) "xmlns", 5)))\r
-       {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsltAttribute: xmlns prefix forbidden\n");\r
-#endif\r
-           /*\r
-           * SPEC XSLT 1.0:\r
-           *  "It is an error if the string that results from instantiating\r
-           *  the attribute value template is not a QName or is the string\r
-           *  xmlns. An XSLT processor may signal the error; if it does not\r
-           *  signal the error, it must recover by not adding the attribute\r
-           *  to the result tree."\r
-           * TODO: Decide which way to go here.\r
-           */\r
-           goto error;\r
-       }\r
-\r
-    } else {\r
-       /*\r
-       * The "name" value was static.\r
-       */\r
-#ifdef XSLT_REFACTORED\r
-       prefix = comp->nsPrefix;\r
-       name = comp->name;\r
-#else\r
-       name = xsltSplitQName(ctxt->dict, comp->name, &prefix);\r
-#endif\r
-    }\r
-    \r
-    /*\r
-    * Process namespace semantics\r
-    * ---------------------------\r
-    *\r
-    * Evaluate the namespace name.\r
-    */\r
-    if (comp->has_ns) {\r
-       /*\r
-       * The "namespace" attribute was existent.\r
-       */\r
-       if (comp->ns != NULL) {\r
-           /*\r
-           * No AVT; just plain text for the namespace name.\r
-           */\r
-           if (comp->ns[0] != 0)\r
-               nsName = comp->ns;\r
-       } else {\r
-           xmlChar *tmpNsName;\r
-           /*\r
-           * Eval the AVT.\r
-           */\r
-           /* TODO: check attr acquisition wrt to the XSLT namespace */\r
-           tmpNsName = xsltEvalAttrValueTemplate(ctxt, inst,\r
-               (const xmlChar *) "namespace", XSLT_NAMESPACE); \r
-           /*\r
-           * This fixes bug #302020: The AVT might also evaluate to the \r
-           * empty string; this means that the empty string also indicates\r
-           * "no namespace".\r
-           * SPEC XSLT 1.0:\r
-           *  "If the string is empty, then the expanded-name of the\r
-           *  attribute has a null namespace URI."\r
-           */\r
-           if ((tmpNsName != NULL) && (tmpNsName[0] != 0))\r
-               nsName = xmlDictLookup(ctxt->dict, BAD_CAST tmpNsName, -1);\r
-           xmlFree(tmpNsName);         \r
-       };          \r
-    } else if (prefix != NULL) {\r
-       /*\r
-       * SPEC XSLT 1.0:\r
-       *  "If the namespace attribute is not present, then the QName is\r
-       *  expanded into an expanded-name using the namespace declarations\r
-       *  in effect for the xsl:attribute element, *not* including any\r
-       *  default namespace declaration."\r
-       */      \r
-       ns = xmlSearchNs(inst->doc, inst, prefix);\r
-       if (ns == NULL) {\r
-           /*\r
-           * Note that this is treated as an error now (checked with\r
-           *  Saxon, Xalan-J and MSXML).\r
-           */\r
-           xsltTransformError(ctxt, NULL, inst,\r
-               "xsl:attribute: The QName '%s:%s' has no "\r
-               "namespace binding in scope in the stylesheet; "\r
-               "this is an error, since the namespace was not "\r
-               "specified by the instruction itself.\n", prefix, name);\r
-       } else\r
-           nsName = ns->href;  \r
-    }\r
-\r
-    if (fromAttributeSet) {\r
-       /*\r
-       * This tries to ensure that xsl:attribute(s) coming\r
-       * from an xsl:attribute-set won't override attribute of\r
-       * literal result elements or of explicit xsl:attribute(s).\r
-       * URGENT TODO: This might be buggy, since it will miss to\r
-       *  overwrite two equal attributes both from attribute sets.\r
-       */\r
-       attr = xmlHasNsProp(targetElem, name, nsName);\r
-       if (attr != NULL)\r
-           return;\r
-    }\r
-\r
-    /*\r
-    * Find/create a matching ns-decl in the result tree.\r
-    */\r
-    ns = NULL;\r
-    \r
-#if 0\r
-    if (0) {   \r
-       /*\r
-       * OPTIMIZE TODO: How do we know if we are adding to a\r
-       *  fragment or to the result tree?\r
-       *\r
-       * If we are adding to a result tree fragment (i.e., not to the\r
-       * actual result tree), we'll don't bother searching for the\r
-       * ns-decl, but just store it in the dummy-doc of the result\r
-       * tree fragment.\r
-       */\r
-       if (nsName != NULL) {\r
-           /*\r
-           * TODO: Get the doc of @targetElem.\r
-           */\r
-           ns = xsltTreeAcquireStoredNs(some doc, nsName, prefix);\r
-       }\r
-    }\r
-#endif\r
-\r
-    if (nsName != NULL) {      \r
-       /*\r
-       * Something about ns-prefixes:\r
-       * SPEC XSLT 1.0:\r
-       *  "XSLT processors may make use of the prefix of the QName specified\r
-       *  in the name attribute when selecting the prefix used for outputting\r
-       *  the created attribute as XML; however, they are not required to do\r
-       *  so and, if the prefix is xmlns, they must not do so"\r
-       */\r
-       /*\r
-       * xsl:attribute can produce a scenario where the prefix is NULL,\r
-       * so generate a prefix.\r
-       */\r
-       if (prefix == NULL) {\r
-           xmlChar *pref = xmlStrdup(BAD_CAST "ns_1");\r
-\r
-           ns = xsltGetSpecialNamespace(ctxt, inst, nsName, BAD_CAST pref,\r
-               targetElem);\r
-\r
-           xmlFree(pref);\r
-       } else {\r
-           ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix,\r
-               targetElem);\r
-       }\r
-       if (ns == NULL) {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-               "Namespace fixup error: Failed to acquire an in-scope "\r
-               "namespace binding for the generated attribute '{%s}%s'.\n",\r
-               nsName, name);\r
-           goto error;\r
-       }\r
-    }\r
-    /*\r
-    * Construction of the value\r
-    * -------------------------\r
-    */\r
-    if (inst->children == NULL) {\r
-       /*\r
-       * No content.\r
-       * TODO: Do we need to put the empty string in ?\r
-       */\r
-       attr = xmlSetNsProp(ctxt->insert, ns, name, (const xmlChar *) "");\r
-    } else if ((inst->children->next == NULL) && \r
-           ((inst->children->type == XML_TEXT_NODE) ||\r
-            (inst->children->type == XML_CDATA_SECTION_NODE)))\r
-    {\r
-       xmlNodePtr copyTxt;\r
-       \r
-       /*\r
-       * xmlSetNsProp() will take care of duplicates.\r
-       */\r
-       attr = xmlSetNsProp(ctxt->insert, ns, name, NULL);\r
-       if (attr == NULL) /* TODO: report error ? */\r
-           goto error;\r
-       /*\r
-       * This was taken over from xsltCopyText() (transform.c).\r
-       */\r
-       if (ctxt->internalized &&\r
-           (ctxt->insert->doc != NULL) &&\r
-           (ctxt->insert->doc->dict == ctxt->dict))\r
-       {\r
-           copyTxt = xmlNewText(NULL);\r
-           if (copyTxt == NULL) /* TODO: report error */\r
-               goto error;\r
-           /*\r
-           * This is a safe scenario where we don't need to lookup\r
-           * the dict.\r
-           */\r
-           copyTxt->content = inst->children->content;\r
-           /*\r
-           * Copy "disable-output-escaping" information.\r
-           * TODO: Does this have any effect for attribute values\r
-           *  anyway?\r
-           */\r
-           if (inst->children->name == xmlStringTextNoenc)\r
-               copyTxt->name = xmlStringTextNoenc;\r
-       } else {\r
-           /*\r
-           * Copy the value.\r
-           */\r
-           copyTxt = xmlNewText(inst->children->content);\r
-           if (copyTxt == NULL) /* TODO: report error */\r
-               goto error;                 \r
-       }\r
-       attr->children = attr->last = copyTxt;\r
-       copyTxt->parent = (xmlNodePtr) attr;\r
-       copyTxt->doc = attr->doc;\r
-       /*\r
-       * Copy "disable-output-escaping" information.\r
-       * TODO: Does this have any effect for attribute values\r
-       *  anyway?\r
-       */\r
-       if (inst->children->name == xmlStringTextNoenc)\r
-           copyTxt->name = xmlStringTextNoenc; \r
-\r
-    } else {\r
-       /*\r
-       * The sequence constructor might be complex, so instantiate it.\r
-       */\r
-       value = xsltEvalTemplateString(ctxt, contextNode, inst);\r
-       if (value != NULL) {\r
-           attr = xmlSetNsProp(ctxt->insert, ns, name, value);\r
-           xmlFree(value);\r
-       } else {\r
-           /*\r
-           * TODO: Do we have to add the empty string to the attr?\r
-           * TODO: Does a  value of NULL indicate an\r
-           *  error in xsltEvalTemplateString() ?\r
-           */\r
-           attr = xmlSetNsProp(ctxt->insert, ns, name,\r
-               (const xmlChar *) "");\r
-       }\r
-    }\r
-\r
-error:\r
-    return;    \r
-}\r
-\r
-/**\r
- * xsltAttribute:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the node in the source tree.\r
- * @inst:  the xslt attribute node\r
- * @comp:  precomputed information\r
- *\r
- * Process the xslt attribute node on the source node\r
- */\r
-void\r
-xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-             xmlNodePtr inst, xsltStylePreCompPtr comp) {\r
-    xsltAttributeInternal(ctxt, node, inst, comp, 0);\r
-}\r
-\r
-/**\r
- * xsltApplyAttributeSet:\r
- * @ctxt:  the XSLT stylesheet\r
- * @node:  the node in the source tree.\r
- * @inst:  the attribute node "xsl:use-attribute-sets"\r
- * @attrSets:  the list of QNames of the attribute-sets to be applied\r
- *\r
- * Apply the xsl:use-attribute-sets.\r
- * If @attrSets is NULL, then @inst will be used to exctract this\r
- * value.\r
- * If both, @attrSets and @inst, are NULL, then this will do nothing.\r
- */\r
-void\r
-xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                      xmlNodePtr inst,\r
-                      const xmlChar *attrSets)\r
-{\r
-    const xmlChar *ncname = NULL;\r
-    const xmlChar *prefix = NULL;    \r
-    const xmlChar *curstr, *endstr;\r
-    xsltAttrElemPtr attrs;\r
-    xsltStylesheetPtr style;    \r
-\r
-    if (attrSets == NULL) {\r
-       if (inst == NULL)\r
-           return;\r
-       else {\r
-           /*\r
-           * Extract the value from @inst.\r
-           */\r
-           if (inst->type == XML_ATTRIBUTE_NODE) {\r
-               if ( ((xmlAttrPtr) inst)->children != NULL)\r
-                   attrSets = ((xmlAttrPtr) inst)->children->content;\r
-               \r
-           }\r
-           if (attrSets == NULL) {\r
-               /*\r
-               * TODO: Return an error?\r
-               */\r
-               return;\r
-           }\r
-       }\r
-    }\r
-    /*\r
-    * Parse/apply the list of QNames.\r
-    */\r
-    curstr = attrSets;\r
-    while (*curstr != 0) {\r
-        while (IS_BLANK(*curstr))\r
-            curstr++;\r
-        if (*curstr == 0)\r
-            break;\r
-        endstr = curstr;\r
-        while ((*endstr != 0) && (!IS_BLANK(*endstr)))\r
-            endstr++;\r
-        curstr = xmlDictLookup(ctxt->dict, curstr, endstr - curstr);\r
-        if (curstr) {\r
-           /*\r
-           * TODO: Validate the QName.\r
-           */\r
-\r
-#ifdef WITH_XSLT_DEBUG_curstrUTES\r
-            xsltGenericDebug(xsltGenericDebugContext,\r
-                             "apply curstrute set %s\n", curstr);\r
-#endif\r
-            ncname = xsltSplitQName(ctxt->dict, curstr, &prefix);\r
-\r
-            style = ctxt->style;\r
-\r
-#ifdef WITH_DEBUGGER\r
-            if ((style != NULL) &&\r
-               (style->attributeSets != NULL) &&\r
-               (ctxt->debugStatus != XSLT_DEBUG_NONE))\r
-           {\r
-                attrs =\r
-                    xmlHashLookup2(style->attributeSets, ncname, prefix);\r
-                if ((attrs != NULL) && (attrs->attr != NULL))\r
-                    xslHandleDebugger(attrs->attr->parent, node, NULL,\r
-                       ctxt);\r
-            }\r
-#endif\r
-           /*\r
-           * Lookup the referenced curstrute-set.\r
-           */\r
-            while (style != NULL) {\r
-                attrs =\r
-                    xmlHashLookup2(style->attributeSets, ncname, prefix);\r
-                while (attrs != NULL) {\r
-                    if (attrs->attr != NULL) {\r
-                        xsltAttributeInternal(ctxt, node, attrs->attr,\r
-                           attrs->attr->psvi, 1);\r
-                    }\r
-                    attrs = attrs->next;\r
-                }\r
-                style = xsltNextImport(style);\r
-            }\r
-        }\r
-        curstr = endstr;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltFreeAttributeSetsHashes:\r
- * @style: an XSLT stylesheet\r
- *\r
- * Free up the memory used by attribute sets\r
- */\r
-void\r
-xsltFreeAttributeSetsHashes(xsltStylesheetPtr style) {\r
-    if (style->attributeSets != NULL)\r
-       xmlHashFree((xmlHashTablePtr) style->attributeSets,\r
-                   (xmlHashDeallocator) xsltFreeAttrElemList);\r
-    style->attributeSets = NULL;\r
-}\r
+/*
+ * attributes.c: Implementation of the XSLT attributes handling
+ *
+ * Reference:
+ *   http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#endif
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
+#ifdef HAVE_NAN_H
+#include <nan.h>
+#endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/hash.h>
+#include <libxml/xmlerror.h>
+#include <libxml/uri.h>
+#include <libxml/parserInternals.h>
+#include "xslt.h"
+#include "xsltInternals.h"
+#include "xsltutils.h"
+#include "attributes.h"
+#include "namespaces.h"
+#include "templates.h"
+#include "imports.h"
+#include "transform.h"
+#include "preproc.h"
+
+#define WITH_XSLT_DEBUG_ATTRIBUTES
+#ifdef WITH_XSLT_DEBUG
+#define WITH_XSLT_DEBUG_ATTRIBUTES
+#endif
+
+/*
+ * TODO: merge attribute sets from different import precedence.
+ *       all this should be precomputed just before the transformation
+ *       starts or at first hit with a cache in the context.
+ *       The simple way for now would be to not allow redefinition of
+ *       attributes once generated in the output tree, possibly costlier.
+ */
+
+/*
+ * Useful macros
+ */
+#ifdef IS_BLANK
+#undef IS_BLANK
+#endif
+
+#define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \
+                     ((c) == 0x0D))
+
+#define IS_BLANK_NODE(n)                                               \
+    (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
+
+
+/*
+ * The in-memory structure corresponding to an XSLT Attribute in
+ * an attribute set
+ */
+
+
+typedef struct _xsltAttrElem xsltAttrElem;
+typedef xsltAttrElem *xsltAttrElemPtr;
+struct _xsltAttrElem {
+    struct _xsltAttrElem *next;/* chained list */
+    xmlNodePtr attr;   /* the xsl:attribute definition */
+    const xmlChar *set; /* or the attribute set */
+    const xmlChar *ns;  /* and its namespace */
+};
+
+/************************************************************************
+ *                                                                     *
+ *                     XSLT Attribute handling                         *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltNewAttrElem:
+ * @attr:  the new xsl:attribute node
+ *
+ * Create a new XSLT AttrElem
+ *
+ * Returns the newly allocated xsltAttrElemPtr or NULL in case of error
+ */
+static xsltAttrElemPtr
+xsltNewAttrElem(xmlNodePtr attr) {
+    xsltAttrElemPtr cur;
+
+    cur = (xsltAttrElemPtr) xmlMalloc(sizeof(xsltAttrElem));
+    if (cur == NULL) {
+        xsltGenericError(xsltGenericErrorContext,
+               "xsltNewAttrElem : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltAttrElem));
+    cur->attr = attr;
+    return(cur);
+}
+
+/**
+ * xsltFreeAttrElem:
+ * @attr:  an XSLT AttrElem
+ *
+ * Free up the memory allocated by @attr
+ */
+static void
+xsltFreeAttrElem(xsltAttrElemPtr attr) {
+    xmlFree(attr);
+}
+
+/**
+ * xsltFreeAttrElemList:
+ * @list:  an XSLT AttrElem list
+ *
+ * Free up the memory allocated by @list
+ */
+static void
+xsltFreeAttrElemList(xsltAttrElemPtr list) {
+    xsltAttrElemPtr next;
+    
+    while (list != NULL) {
+       next = list->next;
+       xsltFreeAttrElem(list);
+       list = next;
+    }
+}
+
+#ifdef XSLT_REFACTORED
+    /*
+    * This was moved to xsltParseStylesheetAttributeSet().
+    */
+#else
+/**
+ * xsltAddAttrElemList:
+ * @list:  an XSLT AttrElem list
+ * @attr:  the new xsl:attribute node
+ *
+ * Add the new attribute to the list.
+ *
+ * Returns the new list pointer
+ */
+static xsltAttrElemPtr
+xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) {
+    xsltAttrElemPtr next, cur;
+
+    if (attr == NULL)
+       return(list);
+    if (list == NULL)
+       return(xsltNewAttrElem(attr));
+    cur = list;
+    while (cur != NULL) {      
+       next = cur->next;
+       if (cur->attr == attr)
+           return(cur);
+       if (cur->next == NULL) {
+           cur->next = xsltNewAttrElem(attr);
+           return(list);
+       }
+       cur = next;
+    }
+    return(list);
+}
+#endif /* XSLT_REFACTORED */
+
+/**
+ * xsltMergeAttrElemList:
+ * @list:  an XSLT AttrElem list
+ * @old:  another XSLT AttrElem list
+ *
+ * Add all the attributes from list @old to list @list,
+ * but drop redefinition of existing values.
+ *
+ * Returns the new list pointer
+ */
+static xsltAttrElemPtr
+xsltMergeAttrElemList(xsltStylesheetPtr style,
+                     xsltAttrElemPtr list, xsltAttrElemPtr old) {
+    xsltAttrElemPtr cur;
+    int add;
+
+    while (old != NULL) {
+       if ((old->attr == NULL) && (old->set == NULL)) {
+           old = old->next;
+           continue;
+       }
+       /*
+        * Check that the attribute is not yet in the list
+        */
+       cur = list;
+       add = 1;
+       while (cur != NULL) {
+           if ((cur->attr == NULL) && (cur->set == NULL)) {
+               if (cur->next == NULL)
+                   break;
+               cur = cur->next;
+               continue;
+           }
+           if ((cur->set != NULL) && (cur->set == old->set)) {
+               add = 0;
+               break;
+           }
+           if (cur->set != NULL) {
+               if (cur->next == NULL)
+                   break;
+               cur = cur->next;
+               continue;
+           }
+           if (old->set != NULL) {
+               if (cur->next == NULL)
+                   break;
+               cur = cur->next;
+               continue;
+           }
+           if (cur->attr == old->attr) {
+               xsltGenericError(xsltGenericErrorContext,
+            "xsl:attribute-set : use-attribute-sets recursion detected\n");
+               return(list);
+           }
+           if (cur->next == NULL)
+               break;
+            cur = cur->next;
+       }
+
+       if (add == 1) {
+           /*
+           * Changed to use the string-dict, rather than duplicating
+           * @set and @ns; this fixes bug #340400.
+           */
+           if (cur == NULL) {
+               list = xsltNewAttrElem(old->attr);
+               if (old->set != NULL) {
+                   list->set = xmlDictLookup(style->dict, old->set, -1);
+                   if (old->ns != NULL)
+                       list->ns = xmlDictLookup(style->dict, old->ns, -1);
+               }
+           } else if (add) {
+               cur->next = xsltNewAttrElem(old->attr);
+               if (old->set != NULL) {
+                   cur->next->set = xmlDictLookup(style->dict, old->set, -1);
+                   if (old->ns != NULL)
+                       cur->next->ns = xmlDictLookup(style->dict, old->ns, -1);
+               }
+           }
+       }
+
+       old = old->next;
+    }
+    return(list);
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Module interfaces                               *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltParseStylesheetAttributeSet:
+ * @style:  the XSLT stylesheet
+ * @cur:  the "attribute-set" element
+ *
+ * parse an XSLT stylesheet attribute-set element
+ */
+
+void
+xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
+    const xmlChar *ncname;
+    const xmlChar *prefix;
+    xmlChar *value;
+    xmlNodePtr child;
+    xsltAttrElemPtr attrItems;
+
+    if ((cur == NULL) || (style == NULL))
+       return;
+
+    value = xmlGetNsProp(cur, (const xmlChar *)"name", NULL);
+    if (value == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+            "xsl:attribute-set : name is missing\n");
+       return;
+    }
+
+    ncname = xsltSplitQName(style->dict, value, &prefix);
+    xmlFree(value);
+    value = NULL;
+
+    if (style->attributeSets == NULL) {
+#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
+       xsltGenericDebug(xsltGenericDebugContext,
+           "creating attribute set table\n");
+#endif
+       style->attributeSets = xmlHashCreate(10);
+    }
+    if (style->attributeSets == NULL)
+       return;
+
+    attrItems = xmlHashLookup2(style->attributeSets, ncname, prefix);
+
+    /*
+    * Parse the content. Only xsl:attribute elements are allowed.
+    */
+    child = cur->children;
+    while (child != NULL) {
+       /*
+       * Report invalid nodes.
+       */
+       if ((child->type != XML_ELEMENT_NODE) ||
+           (child->ns == NULL) ||
+           (! IS_XSLT_ELEM(child)))
+       {
+           if (child->type == XML_ELEMENT_NODE)
+               xsltTransformError(NULL, style, child,
+                       "xsl:attribute-set : unexpected child %s\n",
+                                child->name);
+           else
+               xsltTransformError(NULL, style, child,
+                       "xsl:attribute-set : child of unexpected type\n");
+       } else if (!IS_XSLT_NAME(child, "attribute")) {
+           xsltTransformError(NULL, style, child,
+               "xsl:attribute-set : unexpected child xsl:%s\n",
+               child->name);
+       } else {
+#ifdef XSLT_REFACTORED
+           xsltAttrElemPtr nextAttr, curAttr;
+
+           /*
+           * Process xsl:attribute
+           * ---------------------
+           */
+
+#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
+           xsltGenericDebug(xsltGenericDebugContext,
+               "add attribute to list %s\n", ncname);
+#endif
+           /*
+           * The following was taken over from
+           * xsltAddAttrElemList().
+           */
+           if (attrItems == NULL) {
+               attrItems = xsltNewAttrElem(child);
+           } else {
+               curAttr = attrItems;
+               while (curAttr != NULL) {
+                   nextAttr = curAttr->next;
+                   if (curAttr->attr == child) {
+                       /*
+                       * URGENT TODO: Can somebody explain
+                       *  why attrItems is set to curAttr
+                       *  here? Is this somehow related to
+                       *  avoidance of recursions?
+                       */
+                       attrItems = curAttr;
+                       goto next_child;
+                   }
+                   if (curAttr->next == NULL)                  
+                       curAttr->next = xsltNewAttrElem(child);
+                   curAttr = nextAttr;
+               }
+           }
+           /*
+           * Parse the xsl:attribute and its content.
+           */
+           xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);
+#else
+#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
+           xsltGenericDebug(xsltGenericDebugContext,
+               "add attribute to list %s\n", ncname);
+#endif
+           /*
+           * OLD behaviour:
+           */
+           attrItems = xsltAddAttrElemList(attrItems, child);
+#endif
+       }
+
+#ifdef XSLT_REFACTORED
+next_child:
+#endif
+       child = child->next;
+    }
+
+    /*
+    * Process attribue "use-attribute-sets".
+    */
+    /* TODO check recursion */    
+    value = xmlGetNsProp(cur, (const xmlChar *)"use-attribute-sets",
+       NULL);
+    if (value != NULL) {
+       const xmlChar *curval, *endval;
+       curval = value;
+       while (*curval != 0) {
+           while (IS_BLANK(*curval)) curval++;
+           if (*curval == 0)
+               break;
+           endval = curval;
+           while ((*endval != 0) && (!IS_BLANK(*endval))) endval++;
+           curval = xmlDictLookup(style->dict, curval, endval - curval);
+           if (curval) {
+               const xmlChar *ncname2 = NULL;
+               const xmlChar *prefix2 = NULL;
+               xsltAttrElemPtr refAttrItems;
+               
+#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
+               xsltGenericDebug(xsltGenericDebugContext,
+                   "xsl:attribute-set : %s adds use %s\n", ncname, curval);
+#endif
+               ncname2 = xsltSplitQName(style->dict, curval, &prefix2);
+               refAttrItems = xsltNewAttrElem(NULL);
+               if (refAttrItems != NULL) {
+                   refAttrItems->set = ncname2;
+                   refAttrItems->ns = prefix2;
+                   attrItems = xsltMergeAttrElemList(style,
+                       attrItems, refAttrItems);
+                   xsltFreeAttrElem(refAttrItems);
+               }
+           }
+           curval = endval;
+       }
+       xmlFree(value);
+       value = NULL;
+    }
+
+    /*
+     * Update the value
+     */
+    /*
+    * TODO: Why is this dummy entry needed.?
+    */
+    if (attrItems == NULL)
+       attrItems = xsltNewAttrElem(NULL);
+    xmlHashUpdateEntry2(style->attributeSets, ncname, prefix, attrItems, NULL);
+#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
+    xsltGenericDebug(xsltGenericDebugContext,
+       "updated attribute list %s\n", ncname);
+#endif
+}
+
+/**
+ * xsltGetSAS:
+ * @style:  the XSLT stylesheet
+ * @name:  the attribute list name
+ * @ns:  the attribute list namespace
+ *
+ * lookup an attribute set based on the style cascade
+ *
+ * Returns the attribute set or NULL
+ */
+static xsltAttrElemPtr
+xsltGetSAS(xsltStylesheetPtr style, const xmlChar *name, const xmlChar *ns) {
+    xsltAttrElemPtr values;
+
+    while (style != NULL) {
+       values = xmlHashLookup2(style->attributeSets, name, ns);
+       if (values != NULL)
+           return(values);
+       style = xsltNextImport(style);
+    }
+    return(NULL);
+}
+
+/**
+ * xsltResolveSASCallback,:
+ * @style:  the XSLT stylesheet
+ *
+ * resolve the references in an attribute set.
+ */
+static void
+xsltResolveSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,
+                      const xmlChar *name, const xmlChar *ns,
+                      ATTRIBUTE_UNUSED const xmlChar *ignored) {
+    xsltAttrElemPtr tmp;
+    xsltAttrElemPtr refs;
+
+    tmp = values;
+    while (tmp != NULL) {
+       if (tmp->set != NULL) {
+           /*
+            * Check against cycles !
+            */
+           if ((xmlStrEqual(name, tmp->set)) && (xmlStrEqual(ns, tmp->ns))) {
+               xsltGenericError(xsltGenericErrorContext,
+     "xsl:attribute-set : use-attribute-sets recursion detected on %s\n",
+                                 name);
+           } else {
+#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
+               xsltGenericDebug(xsltGenericDebugContext,
+                       "Importing attribute list %s\n", tmp->set);
+#endif
+
+               refs = xsltGetSAS(style, tmp->set, tmp->ns);
+               if (refs == NULL) {
+                   xsltGenericError(xsltGenericErrorContext,
+     "xsl:attribute-set : use-attribute-sets %s reference missing %s\n",
+                                    name, tmp->set);
+               } else {
+                   /*
+                    * recurse first for cleanup
+                    */
+                   xsltResolveSASCallback(refs, style, name, ns, NULL);
+                   /*
+                    * Then merge
+                    */
+                   xsltMergeAttrElemList(style, values, refs);
+                   /*
+                    * Then suppress the reference
+                    */
+                   tmp->set = NULL;
+                   tmp->ns = NULL;
+               }
+           }
+       }
+       tmp = tmp->next;
+    }
+}
+
+/**
+ * xsltMergeSASCallback,:
+ * @style:  the XSLT stylesheet
+ *
+ * Merge an attribute set from an imported stylesheet.
+ */
+static void
+xsltMergeSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,
+                      const xmlChar *name, const xmlChar *ns,
+                      ATTRIBUTE_UNUSED const xmlChar *ignored) {
+    int ret;
+    xsltAttrElemPtr topSet;
+
+    ret = xmlHashAddEntry2(style->attributeSets, name, ns, values);
+    if (ret < 0) {
+       /*
+        * Add failed, this attribute set can be removed.
+        */
+#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
+       xsltGenericDebug(xsltGenericDebugContext,
+               "attribute set %s present already in top stylesheet"
+               " - merging\n", name);
+#endif
+       topSet = xmlHashLookup2(style->attributeSets, name, ns);
+       if (topSet==NULL) {
+           xsltGenericError(xsltGenericErrorContext,
+               "xsl:attribute-set : logic error merging from imports for"
+               " attribute-set %s\n", name);
+       } else {
+           topSet = xsltMergeAttrElemList(style, topSet, values);
+           xmlHashUpdateEntry2(style->attributeSets, name, ns, topSet, NULL);
+       }
+       xsltFreeAttrElemList(values);
+#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
+    } else {
+       xsltGenericDebug(xsltGenericDebugContext,
+               "attribute set %s moved to top stylesheet\n",
+                        name);
+#endif
+    }
+}
+
+/**
+ * xsltResolveStylesheetAttributeSet:
+ * @style:  the XSLT stylesheet
+ *
+ * resolve the references between attribute sets.
+ */
+void
+xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style) {
+    xsltStylesheetPtr cur;
+
+#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
+    xsltGenericDebug(xsltGenericDebugContext,
+           "Resolving attribute sets references\n");
+#endif
+    /*
+     * First aggregate all the attribute sets definitions from the imports
+     */
+    cur = xsltNextImport(style);
+    while (cur != NULL) {
+       if (cur->attributeSets != NULL) {
+           if (style->attributeSets == NULL) {
+#ifdef WITH_XSLT_DEBUG_ATTRIBUTES
+               xsltGenericDebug(xsltGenericDebugContext,
+                   "creating attribute set table\n");
+#endif
+               style->attributeSets = xmlHashCreate(10);
+           }
+           xmlHashScanFull(cur->attributeSets, 
+               (xmlHashScannerFull) xsltMergeSASCallback, style);
+           /*
+            * the attribute lists have either been migrated to style
+            * or freed directly in xsltMergeSASCallback()
+            */
+           xmlHashFree(cur->attributeSets, NULL);
+           cur->attributeSets = NULL;
+       }
+       cur = xsltNextImport(cur);
+    }
+
+    /*
+     * Then resolve all the references and computes the resulting sets
+     */
+    if (style->attributeSets != NULL) {
+       xmlHashScanFull(style->attributeSets, 
+               (xmlHashScannerFull) xsltResolveSASCallback, style);
+    }
+}
+
+/**
+ * xsltAttributeInternal:
+ * @ctxt:  a XSLT process context
+ * @node:  the current node in the source tree
+ * @inst:  the xsl:attribute element
+ * @comp:  precomputed information
+ * @fromAttributeSet:  the attribute comes from an attribute-set
+ *
+ * Process the xslt attribute node on the source node
+ */
+static void
+xsltAttributeInternal(xsltTransformContextPtr ctxt,
+                     xmlNodePtr contextNode,
+                      xmlNodePtr inst,
+                     xsltStylePreCompPtr castedComp,
+                      int fromAttributeSet)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemAttributePtr comp =
+       (xsltStyleItemAttributePtr) castedComp;   
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif
+    xmlNodePtr targetElem;
+    xmlChar *prop = NULL;    
+    const xmlChar *name = NULL, *prefix = NULL, *nsName = NULL;
+    xmlChar *value = NULL;
+    xmlNsPtr ns = NULL;
+    xmlAttrPtr attr;    
+
+    if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))
+        return;
+
+    /* 
+    * A comp->has_name == 0 indicates that we need to skip this instruction,
+    * since it was evaluated to be invalid already during compilation.
+    */
+    if (!comp->has_name)
+        return;
+    /*
+    * BIG NOTE: This previously used xsltGetSpecialNamespace() and
+    *  xsltGetNamespace(), but since both are not appropriate, we
+    *  will process namespace lookup here to avoid adding yet another
+    *  ns-lookup function to namespaces.c.
+    */
+    /*
+    * SPEC XSLT 1.0: Error cases:
+    * - Creating nodes other than text nodes during the instantiation of
+    *   the content of the xsl:attribute element; implementations may
+    *   either signal the error or ignore the offending nodes."
+    */
+
+    if (comp == NULL) {
+        xsltTransformError(ctxt, NULL, inst,
+           "Internal error in xsltAttributeInternal(): "
+           "The XSLT 'attribute' instruction was not compiled.\n");
+        return;
+    }
+    /*
+    * TODO: Shouldn't ctxt->insert == NULL be treated as an internal error?
+    *   So report an internal error?
+    */
+    if (ctxt->insert == NULL)
+        return;    
+    /*
+    * SPEC XSLT 1.0:
+    *  "Adding an attribute to a node that is not an element;
+    *  implementations may either signal the error or ignore the attribute."
+    *
+    * TODO: I think we should signal such errors in the future, and maybe
+    *  provide an option to ignore such errors.
+    */
+    targetElem = ctxt->insert;
+    if (targetElem->type != XML_ELEMENT_NODE)
+       return;
+    
+    /*
+    * SPEC XSLT 1.0:
+    * "Adding an attribute to an element after children have been added
+    *  to it; implementations may either signal the error or ignore the
+    *  attribute."
+    *
+    * TODO: We should decide whether not to report such errors or
+    *  to ignore them; note that we *ignore* if the parent is not an
+    *  element, but here we report an error.
+    */
+    if (targetElem->children != NULL) {
+       /*
+       * NOTE: Ah! This seems to be intended to support streamed
+       *  result generation!.
+       */
+        xsltTransformError(ctxt, NULL, inst,
+           "xsl:attribute: Cannot add attributes to an "
+           "element if children have been already added "
+           "to the element.\n");
+        return;
+    }
+
+    /*
+    * Process the name
+    * ----------------
+    */    
+
+#ifdef WITH_DEBUGGER
+    if (ctxt->debugStatus != XSLT_DEBUG_NONE)
+        xslHandleDebugger(inst, contextNode, NULL, ctxt);
+#endif
+
+    if (comp->name == NULL) {
+       /* TODO: fix attr acquisition wrt to the XSLT namespace */
+        prop = xsltEvalAttrValueTemplate(ctxt, inst,
+           (const xmlChar *) "name", XSLT_NAMESPACE);
+        if (prop == NULL) {
+            xsltTransformError(ctxt, NULL, inst,
+               "xsl:attribute: The attribute 'name' is missing.\n");
+            goto error;
+        }
+       if (xmlValidateQName(prop, 0)) {
+           xsltTransformError(ctxt, NULL, inst,
+               "xsl:attribute: The effective name '%s' is not a "
+               "valid QName.\n", prop);
+           /* we fall through to catch any further errors, if possible */
+       }
+       name = xsltSplitQName(ctxt->dict, prop, &prefix);
+       xmlFree(prop);
+
+       /*
+       * Reject a prefix of "xmlns".
+       */
+       if ((prefix != NULL) &&
+           (!xmlStrncasecmp(prefix, (xmlChar *) "xmlns", 5)))
+       {
+#ifdef WITH_XSLT_DEBUG_PARSING
+           xsltGenericDebug(xsltGenericDebugContext,
+               "xsltAttribute: xmlns prefix forbidden\n");
+#endif
+           /*
+           * SPEC XSLT 1.0:
+           *  "It is an error if the string that results from instantiating
+           *  the attribute value template is not a QName or is the string
+           *  xmlns. An XSLT processor may signal the error; if it does not
+           *  signal the error, it must recover by not adding the attribute
+           *  to the result tree."
+           * TODO: Decide which way to go here.
+           */
+           goto error;
+       }
+
+    } else {
+       /*
+       * The "name" value was static.
+       */
+#ifdef XSLT_REFACTORED
+       prefix = comp->nsPrefix;
+       name = comp->name;
+#else
+       name = xsltSplitQName(ctxt->dict, comp->name, &prefix);
+#endif
+    }
+    
+    /*
+    * Process namespace semantics
+    * ---------------------------
+    *
+    * Evaluate the namespace name.
+    */
+    if (comp->has_ns) {
+       /*
+       * The "namespace" attribute was existent.
+       */
+       if (comp->ns != NULL) {
+           /*
+           * No AVT; just plain text for the namespace name.
+           */
+           if (comp->ns[0] != 0)
+               nsName = comp->ns;
+       } else {
+           xmlChar *tmpNsName;
+           /*
+           * Eval the AVT.
+           */
+           /* TODO: check attr acquisition wrt to the XSLT namespace */
+           tmpNsName = xsltEvalAttrValueTemplate(ctxt, inst,
+               (const xmlChar *) "namespace", XSLT_NAMESPACE); 
+           /*
+           * This fixes bug #302020: The AVT might also evaluate to the 
+           * empty string; this means that the empty string also indicates
+           * "no namespace".
+           * SPEC XSLT 1.0:
+           *  "If the string is empty, then the expanded-name of the
+           *  attribute has a null namespace URI."
+           */
+           if ((tmpNsName != NULL) && (tmpNsName[0] != 0))
+               nsName = xmlDictLookup(ctxt->dict, BAD_CAST tmpNsName, -1);
+           xmlFree(tmpNsName);         
+       };          
+    } else if (prefix != NULL) {
+       /*
+       * SPEC XSLT 1.0:
+       *  "If the namespace attribute is not present, then the QName is
+       *  expanded into an expanded-name using the namespace declarations
+       *  in effect for the xsl:attribute element, *not* including any
+       *  default namespace declaration."
+       */      
+       ns = xmlSearchNs(inst->doc, inst, prefix);
+       if (ns == NULL) {
+           /*
+           * Note that this is treated as an error now (checked with
+           *  Saxon, Xalan-J and MSXML).
+           */
+           xsltTransformError(ctxt, NULL, inst,
+               "xsl:attribute: The QName '%s:%s' has no "
+               "namespace binding in scope in the stylesheet; "
+               "this is an error, since the namespace was not "
+               "specified by the instruction itself.\n", prefix, name);
+       } else
+           nsName = ns->href;  
+    }
+
+    if (fromAttributeSet) {
+       /*
+       * This tries to ensure that xsl:attribute(s) coming
+       * from an xsl:attribute-set won't override attribute of
+       * literal result elements or of explicit xsl:attribute(s).
+       * URGENT TODO: This might be buggy, since it will miss to
+       *  overwrite two equal attributes both from attribute sets.
+       */
+       attr = xmlHasNsProp(targetElem, name, nsName);
+       if (attr != NULL)
+           return;
+    }
+
+    /*
+    * Find/create a matching ns-decl in the result tree.
+    */
+    ns = NULL;
+    
+#if 0
+    if (0) {   
+       /*
+       * OPTIMIZE TODO: How do we know if we are adding to a
+       *  fragment or to the result tree?
+       *
+       * If we are adding to a result tree fragment (i.e., not to the
+       * actual result tree), we'll don't bother searching for the
+       * ns-decl, but just store it in the dummy-doc of the result
+       * tree fragment.
+       */
+       if (nsName != NULL) {
+           /*
+           * TODO: Get the doc of @targetElem.
+           */
+           ns = xsltTreeAcquireStoredNs(some doc, nsName, prefix);
+       }
+    }
+#endif
+
+    if (nsName != NULL) {      
+       /*
+       * Something about ns-prefixes:
+       * SPEC XSLT 1.0:
+       *  "XSLT processors may make use of the prefix of the QName specified
+       *  in the name attribute when selecting the prefix used for outputting
+       *  the created attribute as XML; however, they are not required to do
+       *  so and, if the prefix is xmlns, they must not do so"
+       */
+       /*
+       * xsl:attribute can produce a scenario where the prefix is NULL,
+       * so generate a prefix.
+       */
+       if (prefix == NULL) {
+           xmlChar *pref = xmlStrdup(BAD_CAST "ns_1");
+
+           ns = xsltGetSpecialNamespace(ctxt, inst, nsName, BAD_CAST pref,
+               targetElem);
+
+           xmlFree(pref);
+       } else {
+           ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix,
+               targetElem);
+       }
+       if (ns == NULL) {
+           xsltTransformError(ctxt, NULL, inst,
+               "Namespace fixup error: Failed to acquire an in-scope "
+               "namespace binding for the generated attribute '{%s}%s'.\n",
+               nsName, name);
+           goto error;
+       }
+    }
+    /*
+    * Construction of the value
+    * -------------------------
+    */
+    if (inst->children == NULL) {
+       /*
+       * No content.
+       * TODO: Do we need to put the empty string in ?
+       */
+       attr = xmlSetNsProp(ctxt->insert, ns, name, (const xmlChar *) "");
+    } else if ((inst->children->next == NULL) && 
+           ((inst->children->type == XML_TEXT_NODE) ||
+            (inst->children->type == XML_CDATA_SECTION_NODE)))
+    {
+       xmlNodePtr copyTxt;
+       
+       /*
+       * xmlSetNsProp() will take care of duplicates.
+       */
+       attr = xmlSetNsProp(ctxt->insert, ns, name, NULL);
+       if (attr == NULL) /* TODO: report error ? */
+           goto error;
+       /*
+       * This was taken over from xsltCopyText() (transform.c).
+       */
+       if (ctxt->internalized &&
+           (ctxt->insert->doc != NULL) &&
+           (ctxt->insert->doc->dict == ctxt->dict))
+       {
+           copyTxt = xmlNewText(NULL);
+           if (copyTxt == NULL) /* TODO: report error */
+               goto error;
+           /*
+           * This is a safe scenario where we don't need to lookup
+           * the dict.
+           */
+           copyTxt->content = inst->children->content;
+           /*
+           * Copy "disable-output-escaping" information.
+           * TODO: Does this have any effect for attribute values
+           *  anyway?
+           */
+           if (inst->children->name == xmlStringTextNoenc)
+               copyTxt->name = xmlStringTextNoenc;
+       } else {
+           /*
+           * Copy the value.
+           */
+           copyTxt = xmlNewText(inst->children->content);
+           if (copyTxt == NULL) /* TODO: report error */
+               goto error;                 
+       }
+       attr->children = attr->last = copyTxt;
+       copyTxt->parent = (xmlNodePtr) attr;
+       copyTxt->doc = attr->doc;
+       /*
+       * Copy "disable-output-escaping" information.
+       * TODO: Does this have any effect for attribute values
+       *  anyway?
+       */
+       if (inst->children->name == xmlStringTextNoenc)
+           copyTxt->name = xmlStringTextNoenc; 
+
+    } else {
+       /*
+       * The sequence constructor might be complex, so instantiate it.
+       */
+       value = xsltEvalTemplateString(ctxt, contextNode, inst);
+       if (value != NULL) {
+           attr = xmlSetNsProp(ctxt->insert, ns, name, value);
+           xmlFree(value);
+       } else {
+           /*
+           * TODO: Do we have to add the empty string to the attr?
+           * TODO: Does a  value of NULL indicate an
+           *  error in xsltEvalTemplateString() ?
+           */
+           attr = xmlSetNsProp(ctxt->insert, ns, name,
+               (const xmlChar *) "");
+       }
+    }
+
+error:
+    return;    
+}
+
+/**
+ * xsltAttribute:
+ * @ctxt:  a XSLT process context
+ * @node:  the node in the source tree.
+ * @inst:  the xslt attribute node
+ * @comp:  precomputed information
+ *
+ * Process the xslt attribute node on the source node
+ */
+void
+xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
+             xmlNodePtr inst, xsltStylePreCompPtr comp) {
+    xsltAttributeInternal(ctxt, node, inst, comp, 0);
+}
+
+/**
+ * xsltApplyAttributeSet:
+ * @ctxt:  the XSLT stylesheet
+ * @node:  the node in the source tree.
+ * @inst:  the attribute node "xsl:use-attribute-sets"
+ * @attrSets:  the list of QNames of the attribute-sets to be applied
+ *
+ * Apply the xsl:use-attribute-sets.
+ * If @attrSets is NULL, then @inst will be used to exctract this
+ * value.
+ * If both, @attrSets and @inst, are NULL, then this will do nothing.
+ */
+void
+xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                      xmlNodePtr inst,
+                      const xmlChar *attrSets)
+{
+    const xmlChar *ncname = NULL;
+    const xmlChar *prefix = NULL;    
+    const xmlChar *curstr, *endstr;
+    xsltAttrElemPtr attrs;
+    xsltStylesheetPtr style;    
+
+    if (attrSets == NULL) {
+       if (inst == NULL)
+           return;
+       else {
+           /*
+           * Extract the value from @inst.
+           */
+           if (inst->type == XML_ATTRIBUTE_NODE) {
+               if ( ((xmlAttrPtr) inst)->children != NULL)
+                   attrSets = ((xmlAttrPtr) inst)->children->content;
+               
+           }
+           if (attrSets == NULL) {
+               /*
+               * TODO: Return an error?
+               */
+               return;
+           }
+       }
+    }
+    /*
+    * Parse/apply the list of QNames.
+    */
+    curstr = attrSets;
+    while (*curstr != 0) {
+        while (IS_BLANK(*curstr))
+            curstr++;
+        if (*curstr == 0)
+            break;
+        endstr = curstr;
+        while ((*endstr != 0) && (!IS_BLANK(*endstr)))
+            endstr++;
+        curstr = xmlDictLookup(ctxt->dict, curstr, endstr - curstr);
+        if (curstr) {
+           /*
+           * TODO: Validate the QName.
+           */
+
+#ifdef WITH_XSLT_DEBUG_curstrUTES
+            xsltGenericDebug(xsltGenericDebugContext,
+                             "apply curstrute set %s\n", curstr);
+#endif
+            ncname = xsltSplitQName(ctxt->dict, curstr, &prefix);
+
+            style = ctxt->style;
+
+#ifdef WITH_DEBUGGER
+            if ((style != NULL) &&
+               (style->attributeSets != NULL) &&
+               (ctxt->debugStatus != XSLT_DEBUG_NONE))
+           {
+                attrs =
+                    xmlHashLookup2(style->attributeSets, ncname, prefix);
+                if ((attrs != NULL) && (attrs->attr != NULL))
+                    xslHandleDebugger(attrs->attr->parent, node, NULL,
+                       ctxt);
+            }
+#endif
+           /*
+           * Lookup the referenced curstrute-set.
+           */
+            while (style != NULL) {
+                attrs =
+                    xmlHashLookup2(style->attributeSets, ncname, prefix);
+                while (attrs != NULL) {
+                    if (attrs->attr != NULL) {
+                        xsltAttributeInternal(ctxt, node, attrs->attr,
+                           attrs->attr->psvi, 1);
+                    }
+                    attrs = attrs->next;
+                }
+                style = xsltNextImport(style);
+            }
+        }
+        curstr = endstr;
+    }
+}
+
+/**
+ * xsltFreeAttributeSetsHashes:
+ * @style: an XSLT stylesheet
+ *
+ * Free up the memory used by attribute sets
+ */
+void
+xsltFreeAttributeSetsHashes(xsltStylesheetPtr style) {
+    if (style->attributeSets != NULL)
+       xmlHashFree((xmlHashTablePtr) style->attributeSets,
+                   (xmlHashDeallocator) xsltFreeAttrElemList);
+    style->attributeSets = NULL;
+}
index c3d5400..038e18a 100644 (file)
-/*\r
- * documents.c: Implementation of the documents handling\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * daniel@veillard.com\r
- */\r
-\r
-#define IN_LIBXSLT\r
-#include "libxslt.h"\r
-\r
-#include <string.h>\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/tree.h>\r
-#include <libxml/hash.h>\r
-#include <libxml/parser.h>\r
-#include <libxml/parserInternals.h>\r
-#include "xslt.h"\r
-#include "xsltInternals.h"\r
-#include "xsltutils.h"\r
-#include "documents.h"\r
-#include "transform.h"\r
-#include "imports.h"\r
-#include "keys.h"\r
-#include "security.h"\r
-\r
-#ifdef LIBXML_XINCLUDE_ENABLED\r
-#include <libxml/xinclude.h>\r
-#endif\r
-\r
-#define WITH_XSLT_DEBUG_DOCUMENTS\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
-#define WITH_XSLT_DEBUG_DOCUMENTS\r
-#endif\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Hooks for the document loader                           *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltDocDefaultLoaderFunc:\r
- * @URI: the URI of the document to load\r
- * @dict: the dictionnary to use when parsing that document\r
- * @options: parsing options, a set of xmlParserOption\r
- * @ctxt: the context, either a stylesheet or a transformation context\r
- * @type: the xsltLoadType indicating the kind of loading required\r
- *\r
- * Default function to load document not provided by the compilation or\r
- * transformation API themselve, for example when an xsl:import,\r
- * xsl:include is found at compilation time or when a document()\r
- * call is made at runtime.\r
- *\r
- * Returns the pointer to the document (which will be modified and\r
- * freed by the engine later), or NULL in case of error.\r
- */\r
-static xmlDocPtr\r
-xsltDocDefaultLoaderFunc(const xmlChar * URI, xmlDictPtr dict, int options,\r
-                         void *ctxt ATTRIBUTE_UNUSED,\r
-                        xsltLoadType type ATTRIBUTE_UNUSED)\r
-{\r
-    xmlParserCtxtPtr pctxt;\r
-    xmlParserInputPtr inputStream;\r
-    xmlDocPtr doc;\r
-\r
-    pctxt = xmlNewParserCtxt();\r
-    if (pctxt == NULL)\r
-        return(NULL);\r
-    if ((dict != NULL) && (pctxt->dict != NULL)) {\r
-        xmlDictFree(pctxt->dict);\r
-       pctxt->dict = NULL;\r
-    }\r
-    if (dict != NULL) {\r
-       pctxt->dict = dict;\r
-       xmlDictReference(pctxt->dict);\r
-#ifdef WITH_XSLT_DEBUG\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-                     "Reusing dictionary for document\n");\r
-#endif\r
-    }\r
-    xmlCtxtUseOptions(pctxt, options);\r
-    inputStream = xmlLoadExternalEntity((const char *) URI, NULL, pctxt);\r
-    if (inputStream == NULL) {\r
-        xmlFreeParserCtxt(pctxt);\r
-       return(NULL);\r
-    }\r
-    inputPush(pctxt, inputStream);\r
-    if (pctxt->directory == NULL)\r
-        pctxt->directory = xmlParserGetDirectory((const char *) URI);\r
-\r
-    xmlParseDocument(pctxt);\r
-\r
-    if (pctxt->wellFormed) {\r
-        doc = pctxt->myDoc;\r
-    }\r
-    else {\r
-        doc = NULL;\r
-        xmlFreeDoc(pctxt->myDoc);\r
-        pctxt->myDoc = NULL;\r
-    }\r
-    xmlFreeParserCtxt(pctxt);\r
-\r
-    return(doc);\r
-}\r
-\r
-\r
-xsltDocLoaderFunc xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;\r
-\r
-/**\r
- * xsltSetLoaderFunc:\r
- * @f: the new function to handle document loading.\r
- *\r
- * Set the new function to load document, if NULL it resets it to the\r
- * default function.\r
- */\r
\r
-void\r
-xsltSetLoaderFunc(xsltDocLoaderFunc f) {\r
-    if (f == NULL)\r
-        xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;\r
-    else\r
-        xsltDocDefaultLoader = f;\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Module interfaces                               *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltNewDocument:\r
- * @ctxt: an XSLT transformation context (or NULL)\r
- * @doc:  a parsed XML document\r
- *\r
- * Register a new document, apply key computations\r
- *\r
- * Returns a handler to the document\r
- */\r
-xsltDocumentPtr        \r
-xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc) {\r
-    xsltDocumentPtr cur;\r
-\r
-    cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));\r
-    if (cur == NULL) {\r
-       xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,\r
-               "xsltNewDocument : malloc failed\n");\r
-       return(NULL);\r
-    }\r
-    memset(cur, 0, sizeof(xsltDocument));\r
-    cur->doc = doc;\r
-    if (ctxt != NULL) {\r
-        if (! XSLT_IS_RES_TREE_FRAG(doc)) {\r
-           cur->next = ctxt->docList;\r
-           ctxt->docList = cur;\r
-       }\r
-#ifdef XSLT_REFACTORED_KEYCOMP\r
-       /*\r
-       * A key with a specific name for a specific document\r
-       * will only be computed if there's a call to the key()\r
-       * function using that specific name for that specific\r
-       * document. I.e. computation of keys will be done in\r
-       * xsltGetKey() (keys.c) on an on-demand basis.\r
-       */\r
-#else\r
-       /*\r
-       * Old behaviour.\r
-       */\r
-       xsltInitCtxtKeys(ctxt, cur);\r
-#endif\r
-    }\r
-    return(cur);\r
-}\r
-\r
-/**\r
- * xsltNewStyleDocument:\r
- * @style: an XSLT style sheet\r
- * @doc:  a parsed XML document\r
- *\r
- * Register a new document, apply key computations\r
- *\r
- * Returns a handler to the document\r
- */\r
-xsltDocumentPtr        \r
-xsltNewStyleDocument(xsltStylesheetPtr style, xmlDocPtr doc) {\r
-    xsltDocumentPtr cur;\r
-\r
-    cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));\r
-    if (cur == NULL) {\r
-       xsltTransformError(NULL, style, (xmlNodePtr) doc,\r
-               "xsltNewStyleDocument : malloc failed\n");\r
-       return(NULL);\r
-    }\r
-    memset(cur, 0, sizeof(xsltDocument));\r
-    cur->doc = doc;\r
-    if (style != NULL) {\r
-       cur->next = style->docList;\r
-       style->docList = cur;\r
-    }\r
-    return(cur);\r
-}\r
-\r
-/**\r
- * xsltFreeStyleDocuments:\r
- * @style: an XSLT stylesheet (representing a stylesheet-level)\r
- *\r
- * Frees the node-trees (and xsltDocument structures) of all\r
- * stylesheet-modules of the stylesheet-level represented by\r
- * the given @style. \r
- */\r
-void   \r
-xsltFreeStyleDocuments(xsltStylesheetPtr style) {\r
-    xsltDocumentPtr doc, cur;\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-    xsltNsMapPtr nsMap;\r
-#endif\r
-    \r
-    if (style == NULL)\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-    if (XSLT_HAS_INTERNAL_NSMAP(style))\r
-       nsMap = XSLT_GET_INTERNAL_NSMAP(style);\r
-    else\r
-       nsMap = NULL;    \r
-#endif   \r
-\r
-    cur = style->docList;\r
-    while (cur != NULL) {\r
-       doc = cur;\r
-       cur = cur->next;\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-       /*\r
-       * Restore all changed namespace URIs of ns-decls.\r
-       */\r
-       if (nsMap)\r
-           xsltRestoreDocumentNamespaces(nsMap, doc->doc);\r
-#endif\r
-       xsltFreeDocumentKeys(doc);\r
-       if (!doc->main)\r
-           xmlFreeDoc(doc->doc);\r
-        xmlFree(doc);\r
-    }\r
-}\r
-\r
-/**\r
- * xsltFreeDocuments:\r
- * @ctxt: an XSLT transformation context\r
- *\r
- * Free up all the space used by the loaded documents\r
- */\r
-void   \r
-xsltFreeDocuments(xsltTransformContextPtr ctxt) {\r
-    xsltDocumentPtr doc, cur;\r
-\r
-    cur = ctxt->docList;\r
-    while (cur != NULL) {\r
-       doc = cur;\r
-       cur = cur->next;\r
-       xsltFreeDocumentKeys(doc);\r
-       if (!doc->main)\r
-           xmlFreeDoc(doc->doc);\r
-        xmlFree(doc);\r
-    }\r
-    cur = ctxt->styleList;\r
-    while (cur != NULL) {\r
-       doc = cur;\r
-       cur = cur->next;\r
-       xsltFreeDocumentKeys(doc);\r
-       if (!doc->main)\r
-           xmlFreeDoc(doc->doc);\r
-        xmlFree(doc);\r
-    }\r
-}\r
-\r
-/**\r
- * xsltLoadDocument:\r
- * @ctxt: an XSLT transformation context\r
- * @URI:  the computed URI of the document\r
- *\r
- * Try to load a document (not a stylesheet)\r
- * within the XSLT transformation context\r
- *\r
- * Returns the new xsltDocumentPtr or NULL in case of error\r
- */\r
-xsltDocumentPtr        \r
-xsltLoadDocument(xsltTransformContextPtr ctxt, const xmlChar *URI) {\r
-    xsltDocumentPtr ret;\r
-    xmlDocPtr doc;\r
-\r
-    if ((ctxt == NULL) || (URI == NULL))\r
-       return(NULL);\r
-\r
-    /*\r
-     * Security framework check\r
-     */\r
-    if (ctxt->sec != NULL) {\r
-       int res;\r
-       \r
-       res = xsltCheckRead(ctxt->sec, ctxt, URI);\r
-       if (res == 0) {\r
-           xsltTransformError(ctxt, NULL, NULL,\r
-                "xsltLoadDocument: read rights for %s denied\n",\r
-                            URI);\r
-           return(NULL);\r
-       }\r
-    }\r
-\r
-    /*\r
-     * Walk the context list to find the document if preparsed\r
-     */\r
-    ret = ctxt->docList;\r
-    while (ret != NULL) {\r
-       if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&\r
-           (xmlStrEqual(ret->doc->URL, URI)))\r
-           return(ret);\r
-       ret = ret->next;\r
-    }\r
-\r
-    doc = xsltDocDefaultLoader(URI, ctxt->dict, ctxt->parserOptions,\r
-                               (void *) ctxt, XSLT_LOAD_DOCUMENT);\r
-\r
-    if (doc == NULL)\r
-       return(NULL);\r
-\r
-    if (ctxt->xinclude != 0) {\r
-#ifdef LIBXML_XINCLUDE_ENABLED\r
-#if LIBXML_VERSION >= 20603\r
-       xmlXIncludeProcessFlags(doc, ctxt->parserOptions);\r
-#else\r
-       xmlXIncludeProcess(doc);\r
-#endif\r
-#else\r
-       xsltTransformError(ctxt, NULL, NULL,\r
-           "xsltLoadDocument(%s) : XInclude processing not compiled in\n",\r
-                        URI);\r
-#endif\r
-    }\r
-    /*\r
-     * Apply white-space stripping if asked for\r
-     */\r
-    if (xsltNeedElemSpaceHandling(ctxt))\r
-       xsltApplyStripSpaces(ctxt, xmlDocGetRootElement(doc));\r
-    if (ctxt->debugStatus == XSLT_DEBUG_NONE)\r
-       xmlXPathOrderDocElems(doc);\r
-\r
-    ret = xsltNewDocument(ctxt, doc);\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltLoadStyleDocument:\r
- * @style: an XSLT style sheet\r
- * @URI:  the computed URI of the document\r
- *\r
- * Try to load a stylesheet document within the XSLT transformation context\r
- *\r
- * Returns the new xsltDocumentPtr or NULL in case of error\r
- */\r
-xsltDocumentPtr        \r
-xsltLoadStyleDocument(xsltStylesheetPtr style, const xmlChar *URI) {\r
-    xsltDocumentPtr ret;\r
-    xmlDocPtr doc;\r
-    xsltSecurityPrefsPtr sec;\r
-\r
-    if ((style == NULL) || (URI == NULL))\r
-       return(NULL);\r
-\r
-    /*\r
-     * Security framework check\r
-     */\r
-    sec = xsltGetDefaultSecurityPrefs();\r
-    if (sec != NULL) {\r
-       int res;\r
-\r
-       res = xsltCheckRead(sec, NULL, URI);\r
-       if (res == 0) {\r
-           xsltTransformError(NULL, NULL, NULL,\r
-                "xsltLoadStyleDocument: read rights for %s denied\n",\r
-                            URI);\r
-           return(NULL);\r
-       }\r
-    }\r
-\r
-    /*\r
-     * Walk the context list to find the document if preparsed\r
-     */\r
-    ret = style->docList;\r
-    while (ret != NULL) {\r
-       if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&\r
-           (xmlStrEqual(ret->doc->URL, URI)))\r
-           return(ret);\r
-       ret = ret->next;\r
-    }\r
-\r
-    doc = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,\r
-                               (void *) style, XSLT_LOAD_STYLESHEET);\r
-    if (doc == NULL)\r
-       return(NULL);\r
-\r
-    ret = xsltNewStyleDocument(style, doc);\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltFindDocument:\r
- * @ctxt: an XSLT transformation context\r
- * @doc: a parsed XML document\r
- *\r
- * Try to find a document within the XSLT transformation context.\r
- * This will not find document infos for temporary\r
- * Result Tree Fragments.\r
- *\r
- * Returns the desired xsltDocumentPtr or NULL in case of error\r
- */\r
-xsltDocumentPtr\r
-xsltFindDocument (xsltTransformContextPtr ctxt, xmlDocPtr doc) {\r
-    xsltDocumentPtr ret;\r
-\r
-    if ((ctxt == NULL) || (doc == NULL))\r
-       return(NULL);\r
-\r
-    /*\r
-     * Walk the context list to find the document\r
-     */\r
-    ret = ctxt->docList;\r
-    while (ret != NULL) {\r
-       if (ret->doc == doc)\r
-           return(ret);\r
-       ret = ret->next;\r
-    }\r
-    if (doc == ctxt->style->doc)\r
-       return(ctxt->document);\r
-    return(NULL);\r
-}\r
-\r
+/*
+ * documents.c: Implementation of the documents handling
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/hash.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include "xslt.h"
+#include "xsltInternals.h"
+#include "xsltutils.h"
+#include "documents.h"
+#include "transform.h"
+#include "imports.h"
+#include "keys.h"
+#include "security.h"
+
+#ifdef LIBXML_XINCLUDE_ENABLED
+#include <libxml/xinclude.h>
+#endif
+
+#define WITH_XSLT_DEBUG_DOCUMENTS
+
+#ifdef WITH_XSLT_DEBUG
+#define WITH_XSLT_DEBUG_DOCUMENTS
+#endif
+
+/************************************************************************
+ *                                                                     *
+ *             Hooks for the document loader                           *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltDocDefaultLoaderFunc:
+ * @URI: the URI of the document to load
+ * @dict: the dictionnary to use when parsing that document
+ * @options: parsing options, a set of xmlParserOption
+ * @ctxt: the context, either a stylesheet or a transformation context
+ * @type: the xsltLoadType indicating the kind of loading required
+ *
+ * Default function to load document not provided by the compilation or
+ * transformation API themselve, for example when an xsl:import,
+ * xsl:include is found at compilation time or when a document()
+ * call is made at runtime.
+ *
+ * Returns the pointer to the document (which will be modified and
+ * freed by the engine later), or NULL in case of error.
+ */
+static xmlDocPtr
+xsltDocDefaultLoaderFunc(const xmlChar * URI, xmlDictPtr dict, int options,
+                         void *ctxt ATTRIBUTE_UNUSED,
+                        xsltLoadType type ATTRIBUTE_UNUSED)
+{
+    xmlParserCtxtPtr pctxt;
+    xmlParserInputPtr inputStream;
+    xmlDocPtr doc;
+
+    pctxt = xmlNewParserCtxt();
+    if (pctxt == NULL)
+        return(NULL);
+    if ((dict != NULL) && (pctxt->dict != NULL)) {
+        xmlDictFree(pctxt->dict);
+       pctxt->dict = NULL;
+    }
+    if (dict != NULL) {
+       pctxt->dict = dict;
+       xmlDictReference(pctxt->dict);
+#ifdef WITH_XSLT_DEBUG
+       xsltGenericDebug(xsltGenericDebugContext,
+                     "Reusing dictionary for document\n");
+#endif
+    }
+    xmlCtxtUseOptions(pctxt, options);
+    inputStream = xmlLoadExternalEntity((const char *) URI, NULL, pctxt);
+    if (inputStream == NULL) {
+        xmlFreeParserCtxt(pctxt);
+       return(NULL);
+    }
+    inputPush(pctxt, inputStream);
+    if (pctxt->directory == NULL)
+        pctxt->directory = xmlParserGetDirectory((const char *) URI);
+
+    xmlParseDocument(pctxt);
+
+    if (pctxt->wellFormed) {
+        doc = pctxt->myDoc;
+    }
+    else {
+        doc = NULL;
+        xmlFreeDoc(pctxt->myDoc);
+        pctxt->myDoc = NULL;
+    }
+    xmlFreeParserCtxt(pctxt);
+
+    return(doc);
+}
+
+
+xsltDocLoaderFunc xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;
+
+/**
+ * xsltSetLoaderFunc:
+ * @f: the new function to handle document loading.
+ *
+ * Set the new function to load document, if NULL it resets it to the
+ * default function.
+ */
+void
+xsltSetLoaderFunc(xsltDocLoaderFunc f) {
+    if (f == NULL)
+        xsltDocDefaultLoader = xsltDocDefaultLoaderFunc;
+    else
+        xsltDocDefaultLoader = f;
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Module interfaces                               *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltNewDocument:
+ * @ctxt: an XSLT transformation context (or NULL)
+ * @doc:  a parsed XML document
+ *
+ * Register a new document, apply key computations
+ *
+ * Returns a handler to the document
+ */
+xsltDocumentPtr        
+xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc) {
+    xsltDocumentPtr cur;
+
+    cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));
+    if (cur == NULL) {
+       xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
+               "xsltNewDocument : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltDocument));
+    cur->doc = doc;
+    if (ctxt != NULL) {
+        if (! XSLT_IS_RES_TREE_FRAG(doc)) {
+           cur->next = ctxt->docList;
+           ctxt->docList = cur;
+       }
+#ifdef XSLT_REFACTORED_KEYCOMP
+       /*
+       * A key with a specific name for a specific document
+       * will only be computed if there's a call to the key()
+       * function using that specific name for that specific
+       * document. I.e. computation of keys will be done in
+       * xsltGetKey() (keys.c) on an on-demand basis.
+       */
+#else
+       /*
+       * Old behaviour.
+       */
+       xsltInitCtxtKeys(ctxt, cur);
+#endif
+    }
+    return(cur);
+}
+
+/**
+ * xsltNewStyleDocument:
+ * @style: an XSLT style sheet
+ * @doc:  a parsed XML document
+ *
+ * Register a new document, apply key computations
+ *
+ * Returns a handler to the document
+ */
+xsltDocumentPtr        
+xsltNewStyleDocument(xsltStylesheetPtr style, xmlDocPtr doc) {
+    xsltDocumentPtr cur;
+
+    cur = (xsltDocumentPtr) xmlMalloc(sizeof(xsltDocument));
+    if (cur == NULL) {
+       xsltTransformError(NULL, style, (xmlNodePtr) doc,
+               "xsltNewStyleDocument : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltDocument));
+    cur->doc = doc;
+    if (style != NULL) {
+       cur->next = style->docList;
+       style->docList = cur;
+    }
+    return(cur);
+}
+
+/**
+ * xsltFreeStyleDocuments:
+ * @style: an XSLT stylesheet (representing a stylesheet-level)
+ *
+ * Frees the node-trees (and xsltDocument structures) of all
+ * stylesheet-modules of the stylesheet-level represented by
+ * the given @style. 
+ */
+void   
+xsltFreeStyleDocuments(xsltStylesheetPtr style) {
+    xsltDocumentPtr doc, cur;
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+    xsltNsMapPtr nsMap;
+#endif
+    
+    if (style == NULL)
+       return;
+
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+    if (XSLT_HAS_INTERNAL_NSMAP(style))
+       nsMap = XSLT_GET_INTERNAL_NSMAP(style);
+    else
+       nsMap = NULL;    
+#endif   
+
+    cur = style->docList;
+    while (cur != NULL) {
+       doc = cur;
+       cur = cur->next;
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+       /*
+       * Restore all changed namespace URIs of ns-decls.
+       */
+       if (nsMap)
+           xsltRestoreDocumentNamespaces(nsMap, doc->doc);
+#endif
+       xsltFreeDocumentKeys(doc);
+       if (!doc->main)
+           xmlFreeDoc(doc->doc);
+        xmlFree(doc);
+    }
+}
+
+/**
+ * xsltFreeDocuments:
+ * @ctxt: an XSLT transformation context
+ *
+ * Free up all the space used by the loaded documents
+ */
+void   
+xsltFreeDocuments(xsltTransformContextPtr ctxt) {
+    xsltDocumentPtr doc, cur;
+
+    cur = ctxt->docList;
+    while (cur != NULL) {
+       doc = cur;
+       cur = cur->next;
+       xsltFreeDocumentKeys(doc);
+       if (!doc->main)
+           xmlFreeDoc(doc->doc);
+        xmlFree(doc);
+    }
+    cur = ctxt->styleList;
+    while (cur != NULL) {
+       doc = cur;
+       cur = cur->next;
+       xsltFreeDocumentKeys(doc);
+       if (!doc->main)
+           xmlFreeDoc(doc->doc);
+        xmlFree(doc);
+    }
+}
+
+/**
+ * xsltLoadDocument:
+ * @ctxt: an XSLT transformation context
+ * @URI:  the computed URI of the document
+ *
+ * Try to load a document (not a stylesheet)
+ * within the XSLT transformation context
+ *
+ * Returns the new xsltDocumentPtr or NULL in case of error
+ */
+xsltDocumentPtr        
+xsltLoadDocument(xsltTransformContextPtr ctxt, const xmlChar *URI) {
+    xsltDocumentPtr ret;
+    xmlDocPtr doc;
+
+    if ((ctxt == NULL) || (URI == NULL))
+       return(NULL);
+
+    /*
+     * Security framework check
+     */
+    if (ctxt->sec != NULL) {
+       int res;
+       
+       res = xsltCheckRead(ctxt->sec, ctxt, URI);
+       if (res == 0) {
+           xsltTransformError(ctxt, NULL, NULL,
+                "xsltLoadDocument: read rights for %s denied\n",
+                            URI);
+           return(NULL);
+       }
+    }
+
+    /*
+     * Walk the context list to find the document if preparsed
+     */
+    ret = ctxt->docList;
+    while (ret != NULL) {
+       if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
+           (xmlStrEqual(ret->doc->URL, URI)))
+           return(ret);
+       ret = ret->next;
+    }
+
+    doc = xsltDocDefaultLoader(URI, ctxt->dict, ctxt->parserOptions,
+                               (void *) ctxt, XSLT_LOAD_DOCUMENT);
+
+    if (doc == NULL)
+       return(NULL);
+
+    if (ctxt->xinclude != 0) {
+#ifdef LIBXML_XINCLUDE_ENABLED
+#if LIBXML_VERSION >= 20603
+       xmlXIncludeProcessFlags(doc, ctxt->parserOptions);
+#else
+       xmlXIncludeProcess(doc);
+#endif
+#else
+       xsltTransformError(ctxt, NULL, NULL,
+           "xsltLoadDocument(%s) : XInclude processing not compiled in\n",
+                        URI);
+#endif
+    }
+    /*
+     * Apply white-space stripping if asked for
+     */
+    if (xsltNeedElemSpaceHandling(ctxt))
+       xsltApplyStripSpaces(ctxt, xmlDocGetRootElement(doc));
+    if (ctxt->debugStatus == XSLT_DEBUG_NONE)
+       xmlXPathOrderDocElems(doc);
+
+    ret = xsltNewDocument(ctxt, doc);
+    return(ret);
+}
+
+/**
+ * xsltLoadStyleDocument:
+ * @style: an XSLT style sheet
+ * @URI:  the computed URI of the document
+ *
+ * Try to load a stylesheet document within the XSLT transformation context
+ *
+ * Returns the new xsltDocumentPtr or NULL in case of error
+ */
+xsltDocumentPtr        
+xsltLoadStyleDocument(xsltStylesheetPtr style, const xmlChar *URI) {
+    xsltDocumentPtr ret;
+    xmlDocPtr doc;
+    xsltSecurityPrefsPtr sec;
+
+    if ((style == NULL) || (URI == NULL))
+       return(NULL);
+
+    /*
+     * Security framework check
+     */
+    sec = xsltGetDefaultSecurityPrefs();
+    if (sec != NULL) {
+       int res;
+
+       res = xsltCheckRead(sec, NULL, URI);
+       if (res == 0) {
+           xsltTransformError(NULL, NULL, NULL,
+                "xsltLoadStyleDocument: read rights for %s denied\n",
+                            URI);
+           return(NULL);
+       }
+    }
+
+    /*
+     * Walk the context list to find the document if preparsed
+     */
+    ret = style->docList;
+    while (ret != NULL) {
+       if ((ret->doc != NULL) && (ret->doc->URL != NULL) &&
+           (xmlStrEqual(ret->doc->URL, URI)))
+           return(ret);
+       ret = ret->next;
+    }
+
+    doc = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS,
+                               (void *) style, XSLT_LOAD_STYLESHEET);
+    if (doc == NULL)
+       return(NULL);
+
+    ret = xsltNewStyleDocument(style, doc);
+    return(ret);
+}
+
+/**
+ * xsltFindDocument:
+ * @ctxt: an XSLT transformation context
+ * @doc: a parsed XML document
+ *
+ * Try to find a document within the XSLT transformation context.
+ * This will not find document infos for temporary
+ * Result Tree Fragments.
+ *
+ * Returns the desired xsltDocumentPtr or NULL in case of error
+ */
+xsltDocumentPtr
+xsltFindDocument (xsltTransformContextPtr ctxt, xmlDocPtr doc) {
+    xsltDocumentPtr ret;
+
+    if ((ctxt == NULL) || (doc == NULL))
+       return(NULL);
+
+    /*
+     * Walk the context list to find the document
+     */
+    ret = ctxt->docList;
+    while (ret != NULL) {
+       if (ret->doc == doc)
+           return(ret);
+       ret = ret->next;
+    }
+    if (doc == ctxt->style->doc)
+       return(ctxt->document);
+    return(NULL);
+}
+
index f03d71c..9e120a9 100644 (file)
-/*\r
- * functions.c: Implementation of the XSLT extra functions\r
- *\r
- * Reference:\r
- *   http://www.w3.org/TR/1999/REC-xslt-19991116\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * daniel@veillard.com\r
- * Bjorn Reese <breese@users.sourceforge.net> for number formatting\r
- */\r
-\r
-#define IN_LIBXSLT\r
-#include "libxslt.h"\r
-\r
-#include <string.h>\r
-\r
-#ifdef HAVE_SYS_TYPES_H\r
-#include <sys/types.h>\r
-#endif\r
-#ifdef HAVE_CTYPE_H\r
-#include <ctype.h>\r
-#endif\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/parser.h>\r
-#include <libxml/tree.h>\r
-#include <libxml/valid.h>\r
-#include <libxml/hash.h>\r
-#include <libxml/xmlerror.h>\r
-#include <libxml/xpath.h>\r
-#include <libxml/xpathInternals.h>\r
-#include <libxml/parserInternals.h>\r
-#include <libxml/uri.h>\r
-#include <libxml/xpointer.h>\r
-#include "xslt.h"\r
-#include "xsltInternals.h"\r
-#include "xsltutils.h"\r
-#include "functions.h"\r
-#include "extensions.h"\r
-#include "numbersInternals.h"\r
-#include "keys.h"\r
-#include "documents.h"\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
-#define WITH_XSLT_DEBUG_FUNCTION\r
-#endif\r
-\r
-/*\r
- * Some versions of DocBook XSL use the vendor string to detect\r
- * supporting chunking, this is a workaround to be considered\r
- * in the list of decent XSLT processors <grin/>\r
- */\r
-#define DOCBOOK_XSL_HACK\r
-\r
-/**\r
- * xsltXPathFunctionLookup:\r
- * @ctxt:  a void * but the XSLT transformation context actually\r
- * @name:  the function name\r
- * @ns_uri:  the function namespace URI\r
- *\r
- * This is the entry point when a function is needed by the XPath\r
- * interpretor.\r
- *\r
- * Returns the callback function or NULL if not found\r
- */\r
-xmlXPathFunction\r
-xsltXPathFunctionLookup (xmlXPathContextPtr ctxt,\r
-                        const xmlChar *name, const xmlChar *ns_uri) {\r
-    xmlXPathFunction ret;\r
-\r
-    if ((ctxt == NULL) || (name == NULL) || (ns_uri == NULL))\r
-       return (NULL);\r
-\r
-#ifdef WITH_XSLT_DEBUG_FUNCTION\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-            "Lookup function {%s}%s\n", ns_uri, name);\r
-#endif\r
-\r
-    /* give priority to context-level functions */\r
-    /*\r
-    ret = (xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri);\r
-    */\r
-    XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->funcHash, name, ns_uri);\r
-\r
-    if (ret == NULL)\r
-       ret = xsltExtModuleFunctionLookup(name, ns_uri);\r
-\r
-#ifdef WITH_XSLT_DEBUG_FUNCTION\r
-    if (ret != NULL)\r
-        xsltGenericDebug(xsltGenericDebugContext,\r
-            "found function %s\n", name);\r
-#endif\r
-    return(ret);\r
-}\r
-\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Module interfaces                               *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-static void\r
-xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI)\r
-{\r
-    xsltTransformContextPtr tctxt;\r
-    xmlURIPtr uri;\r
-    xmlChar *fragment;\r
-    xsltDocumentPtr idoc; /* document info */\r
-    xmlDocPtr doc;\r
-    xmlXPathContextPtr xptrctxt = NULL;\r
-    xmlXPathObjectPtr resObj = NULL;\r
-\r
-    tctxt = xsltXPathGetTransformContext(ctxt);\r
-    if (tctxt == NULL) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-           "document() : internal error tctxt == NULL\n");\r
-       valuePush(ctxt, xmlXPathNewNodeSet(NULL));\r
-       return;\r
-    } \r
-       \r
-    uri = xmlParseURI((const char *) URI);\r
-    if (uri == NULL) {\r
-       xsltTransformError(tctxt, NULL, NULL,\r
-           "document() : failed to parse URI\n");\r
-       valuePush(ctxt, xmlXPathNewNodeSet(NULL));\r
-       return;\r
-    } \r
-    \r
-    /*\r
-     * check for and remove fragment identifier\r
-     */\r
-    fragment = (xmlChar *)uri->fragment;\r
-    if (fragment != NULL) {\r
-       uri->fragment = NULL;\r
-       URI = xmlSaveUri(uri);\r
-       idoc = xsltLoadDocument(tctxt, URI);\r
-       xmlFree(URI);\r
-    } else\r
-       idoc = xsltLoadDocument(tctxt, URI);\r
-    xmlFreeURI(uri);\r
-    \r
-    if (idoc == NULL) {\r
-       if ((URI == NULL) ||\r
-           (URI[0] == '#') ||\r
-           (xmlStrEqual(tctxt->style->doc->URL, URI))) \r
-       {\r
-           /*\r
-           * This selects the stylesheet's doc itself.\r
-           */\r
-           doc = tctxt->style->doc;\r
-       } else {\r
-           valuePush(ctxt, xmlXPathNewNodeSet(NULL));\r
-\r
-           if (fragment != NULL)\r
-               xmlFree(fragment);\r
-\r
-           return;\r
-       }\r
-    } else\r
-       doc = idoc->doc;\r
-\r
-    if (fragment == NULL) {\r
-       valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc));\r
-       return;\r
-    }\r
-       \r
-    /* use XPointer of HTML location for fragment ID */\r
-#ifdef LIBXML_XPTR_ENABLED\r
-    xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);\r
-    if (xptrctxt == NULL) {\r
-       xsltTransformError(tctxt, NULL, NULL,\r
-           "document() : internal error xptrctxt == NULL\n");\r
-       goto out_fragment;\r
-    }\r
-\r
-    resObj = xmlXPtrEval(fragment, xptrctxt);\r
-    xmlXPathFreeContext(xptrctxt);\r
-#endif\r
-    xmlFree(fragment); \r
-\r
-    if (resObj == NULL)\r
-       goto out_fragment;\r
-       \r
-    switch (resObj->type) {\r
-       case XPATH_NODESET:\r
-           break;\r
-       case XPATH_UNDEFINED:\r
-       case XPATH_BOOLEAN:\r
-       case XPATH_NUMBER:\r
-       case XPATH_STRING:\r
-       case XPATH_POINT:\r
-       case XPATH_USERS:\r
-       case XPATH_XSLT_TREE:\r
-       case XPATH_RANGE:\r
-       case XPATH_LOCATIONSET:\r
-           xsltTransformError(tctxt, NULL, NULL,\r
-               "document() : XPointer does not select a node set: #%s\n", \r
-               fragment);\r
-       goto out_object;\r
-    }\r
-    \r
-    valuePush(ctxt, resObj);\r
-    return;\r
-\r
-out_object:\r
-    xmlXPathFreeObject(resObj);\r
-\r
-out_fragment:\r
-    valuePush(ctxt, xmlXPathNewNodeSet(NULL));\r
-}\r
-\r
-/**\r
- * xsltDocumentFunction:\r
- * @ctxt:  the XPath Parser context\r
- * @nargs:  the number of arguments\r
- *\r
- * Implement the document() XSLT function\r
- *   node-set document(object, node-set?)\r
- */\r
-void\r
-xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs)\r
-{\r
-    xmlXPathObjectPtr obj, obj2 = NULL;\r
-    xmlChar *base = NULL, *URI;\r
-\r
-\r
-    if ((nargs < 1) || (nargs > 2)) {\r
-        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-                         "document() : invalid number of args %d\n",\r
-                         nargs);\r
-        ctxt->error = XPATH_INVALID_ARITY;\r
-        return;\r
-    }\r
-    if (ctxt->value == NULL) {\r
-        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-                         "document() : invalid arg value\n");\r
-        ctxt->error = XPATH_INVALID_TYPE;\r
-        return;\r
-    }\r
-\r
-    if (nargs == 2) {\r
-        if (ctxt->value->type != XPATH_NODESET) {\r
-            xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-                             "document() : invalid arg expecting a nodeset\n");\r
-            ctxt->error = XPATH_INVALID_TYPE;\r
-            return;\r
-        }\r
-\r
-        obj2 = valuePop(ctxt);\r
-    }\r
-\r
-    if (ctxt->value->type == XPATH_NODESET) {\r
-        int i;\r
-        xmlXPathObjectPtr newobj, ret;\r
-\r
-        obj = valuePop(ctxt);\r
-        ret = xmlXPathNewNodeSet(NULL);\r
-\r
-        if (obj->nodesetval) {\r
-            for (i = 0; i < obj->nodesetval->nodeNr; i++) {\r
-                valuePush(ctxt,\r
-                          xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i]));\r
-                xmlXPathStringFunction(ctxt, 1);\r
-                if (nargs == 2) {\r
-                    valuePush(ctxt, xmlXPathObjectCopy(obj2));\r
-                } else {\r
-                    valuePush(ctxt,\r
-                              xmlXPathNewNodeSet(obj->nodesetval->\r
-                                                 nodeTab[i]));\r
-                }\r
-                xsltDocumentFunction(ctxt, 2);\r
-                newobj = valuePop(ctxt);\r
-                ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,\r
-                                                       newobj->nodesetval);\r
-                xmlXPathFreeObject(newobj);\r
-            }\r
-        }\r
-\r
-        xmlXPathFreeObject(obj);\r
-        if (obj2 != NULL)\r
-            xmlXPathFreeObject(obj2);\r
-        valuePush(ctxt, ret);\r
-        return;\r
-    }\r
-    /*\r
-     * Make sure it's converted to a string\r
-     */\r
-    xmlXPathStringFunction(ctxt, 1);\r
-    if (ctxt->value->type != XPATH_STRING) {\r
-        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-                         "document() : invalid arg expecting a string\n");\r
-        ctxt->error = XPATH_INVALID_TYPE;\r
-        if (obj2 != NULL)\r
-            xmlXPathFreeObject(obj2);\r
-        return;\r
-    }\r
-    obj = valuePop(ctxt);\r
-    if (obj->stringval == NULL) {\r
-        valuePush(ctxt, xmlXPathNewNodeSet(NULL));\r
-    } else {\r
-        if ((obj2 != NULL) && (obj2->nodesetval != NULL) &&\r
-            (obj2->nodesetval->nodeNr > 0) &&\r
-            IS_XSLT_REAL_NODE(obj2->nodesetval->nodeTab[0])) {\r
-            xmlNodePtr target;\r
-\r
-            target = obj2->nodesetval->nodeTab[0];\r
-            if ((target->type == XML_ATTRIBUTE_NODE) ||\r
-               (target->type == XML_PI_NODE)) {\r
-                target = ((xmlAttrPtr) target)->parent;\r
-            }\r
-            base = xmlNodeGetBase(target->doc, target);\r
-        } else {\r
-            xsltTransformContextPtr tctxt;\r
-\r
-            tctxt = xsltXPathGetTransformContext(ctxt);\r
-            if ((tctxt != NULL) && (tctxt->inst != NULL)) {\r
-                base = xmlNodeGetBase(tctxt->inst->doc, tctxt->inst);\r
-            } else if ((tctxt != NULL) && (tctxt->style != NULL) &&\r
-                       (tctxt->style->doc != NULL)) {\r
-                base = xmlNodeGetBase(tctxt->style->doc,\r
-                                      (xmlNodePtr) tctxt->style->doc);\r
-            }\r
-        }\r
-        URI = xmlBuildURI(obj->stringval, base);\r
-        if (base != NULL)\r
-            xmlFree(base);\r
-        if (URI == NULL) {\r
-            valuePush(ctxt, xmlXPathNewNodeSet(NULL));\r
-        } else {\r
-           xsltDocumentFunctionLoadDocument( ctxt, URI );\r
-           xmlFree(URI);\r
-       }\r
-    }\r
-    xmlXPathFreeObject(obj);\r
-    if (obj2 != NULL)\r
-        xmlXPathFreeObject(obj2);\r
-}\r
-\r
-/**\r
- * xsltKeyFunction:\r
- * @ctxt:  the XPath Parser context\r
- * @nargs:  the number of arguments\r
- *\r
- * Implement the key() XSLT function\r
- *   node-set key(string, object)\r
- */\r
-void\r
-xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){    \r
-    xmlXPathObjectPtr obj1, obj2;    \r
-    \r
-    if (nargs != 2) {\r
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-               "key() : expects two arguments\n");\r
-       ctxt->error = XPATH_INVALID_ARITY;\r
-       return;\r
-    }    \r
-\r
-    /*\r
-    * Get the key's value.\r
-    */\r
-    obj2 = valuePop(ctxt);\r
-    xmlXPathStringFunction(ctxt, 1);\r
-    if ((obj2 == NULL) ||\r
-       (ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {\r
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-           "key() : invalid arg expecting a string\n");\r
-       ctxt->error = XPATH_INVALID_TYPE;\r
-       xmlXPathFreeObject(obj2);\r
-\r
-       return;\r
-    }\r
-    /*\r
-    * Get the key's name.\r
-    */\r
-    obj1 = valuePop(ctxt);    \r
-\r
-    if ((obj2->type == XPATH_NODESET) || (obj2->type == XPATH_XSLT_TREE)) {\r
-       int i;\r
-       xmlXPathObjectPtr newobj, ret;\r
-\r
-       ret = xmlXPathNewNodeSet(NULL);\r
-\r
-       if (obj2->nodesetval != NULL) {\r
-           for (i = 0; i < obj2->nodesetval->nodeNr; i++) {\r
-               valuePush(ctxt, xmlXPathObjectCopy(obj1));\r
-               valuePush(ctxt,\r
-                         xmlXPathNewNodeSet(obj2->nodesetval->nodeTab[i]));\r
-               xmlXPathStringFunction(ctxt, 1);\r
-               xsltKeyFunction(ctxt, 2);\r
-               newobj = valuePop(ctxt);\r
-               ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,\r
-                                                      newobj->nodesetval);\r
-               xmlXPathFreeObject(newobj);\r
-           }\r
-       }\r
-       valuePush(ctxt, ret);\r
-    } else {\r
-       xmlNodeSetPtr nodelist = NULL;\r
-       xmlChar *key = NULL, *value;\r
-       const xmlChar *keyURI;\r
-       xsltTransformContextPtr tctxt;   \r
-       xmlChar *qname, *prefix;\r
-       xmlXPathContextPtr xpctxt = ctxt->context;\r
-       xmlNodePtr tmpNode = NULL;\r
-       xsltDocumentPtr oldDocInfo;\r
-\r
-       tctxt = xsltXPathGetTransformContext(ctxt);\r
-\r
-       oldDocInfo = tctxt->document;\r
-\r
-       if (xpctxt->node == NULL) {\r
-           xsltTransformError(tctxt, NULL, tctxt->inst,\r
-               "Internal error in xsltKeyFunction(): "\r
-               "The context node is not set on the XPath context.\n");\r
-           tctxt->state = XSLT_STATE_STOPPED;\r
-           goto error;\r
-       }       \r
-       /*\r
-        * Get the associated namespace URI if qualified name\r
-        */\r
-       qname = obj1->stringval;\r
-       key = xmlSplitQName2(qname, &prefix);\r
-       if (key == NULL) {\r
-           key = xmlStrdup(obj1->stringval);\r
-           keyURI = NULL;\r
-           if (prefix != NULL)\r
-               xmlFree(prefix);\r
-       } else {\r
-           if (prefix != NULL) {\r
-               keyURI = xmlXPathNsLookup(xpctxt, prefix);\r
-               if (keyURI == NULL) {\r
-                   xsltTransformError(tctxt, NULL, tctxt->inst,\r
-                       "key() : prefix %s is not bound\n", prefix);\r
-                   /*\r
-                   * TODO: Shouldn't we stop here?\r
-                   */\r
-               }\r
-               xmlFree(prefix);\r
-           } else {\r
-               keyURI = NULL;\r
-           }\r
-       }\r
-\r
-       /*\r
-        * Force conversion of first arg to string\r
-        */\r
-       valuePush(ctxt, obj2);\r
-       xmlXPathStringFunction(ctxt, 1);\r
-       if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {\r
-           xsltTransformError(tctxt, NULL, tctxt->inst,\r
-               "key() : invalid arg expecting a string\n");\r
-           ctxt->error = XPATH_INVALID_TYPE;\r
-           goto error;\r
-       }\r
-       obj2 = valuePop(ctxt);\r
-       value = obj2->stringval;\r
-       \r
-       /*\r
-       * We need to ensure that ctxt->document is available for\r
-       * xsltGetKey().\r
-       * First find the relevant doc, which is the context node's\r
-       * owner doc; using context->doc is not safe, since\r
-       * the doc could have been acquired via the document() function,\r
-       * or the doc might be a Result Tree Fragment.\r
-       * FUTURE INFO: In XSLT 2.0 the key() function takes an additional\r
-       * argument indicating the doc to use.\r
-       */      \r
-       if (xpctxt->node->type == XML_NAMESPACE_DECL) {\r
-           /*\r
-           * REVISIT: This is a libxml hack! Check xpath.c for details.\r
-           * The XPath module sets the owner element of a ns-node on\r
-           * the ns->next field.\r
-           */\r
-           if ((((xmlNsPtr) xpctxt->node)->next != NULL) &&\r
-               (((xmlNsPtr) xpctxt->node)->next->type == XML_ELEMENT_NODE))\r
-           {\r
-               tmpNode = (xmlNodePtr) ((xmlNsPtr) xpctxt->node)->next;\r
-           }\r
-       } else\r
-           tmpNode = xpctxt->node;\r
-\r
-       if ((tmpNode == NULL) || (tmpNode->doc == NULL)) {\r
-           xsltTransformError(tctxt, NULL, tctxt->inst,\r
-               "Internal error in xsltKeyFunction(): "\r
-               "Couldn't get the doc of the XPath context node.\n");\r
-           goto error;\r
-       }\r
-\r
-       if ((tctxt->document == NULL) ||\r
-           (tctxt->document->doc != tmpNode->doc))\r
-       {          \r
-           if (tmpNode->doc->name && (tmpNode->doc->name[0] == ' ')) {\r
-               /*\r
-               * This is a Result Tree Fragment.\r
-               */\r
-               if (tmpNode->doc->_private == NULL) {\r
-                   tmpNode->doc->_private = xsltNewDocument(tctxt, tmpNode->doc);\r
-                   if (tmpNode->doc->_private == NULL)\r
-                       goto error;\r
-               }\r
-               tctxt->document = (xsltDocumentPtr) tmpNode->doc->_private;             \r
-           } else {\r
-               /*\r
-               * May be the initial source doc or a doc acquired via the\r
-               * document() function.\r
-               */\r
-               tctxt->document = xsltFindDocument(tctxt, tmpNode->doc);\r
-           }\r
-           if (tctxt->document == NULL) {\r
-               xsltTransformError(tctxt, NULL, tctxt->inst,\r
-                   "Internal error in xsltKeyFunction(): "\r
-                   "Could not get the document info of a context doc.\n");\r
-               tctxt->state = XSLT_STATE_STOPPED;\r
-               goto error;\r
-           }\r
-       }\r
-       /*\r
-       * Get/compute the key value.\r
-       */\r
-       nodelist = xsltGetKey(tctxt, key, keyURI, value);\r
-\r
-error: \r
-       tctxt->document = oldDocInfo;\r
-       valuePush(ctxt, xmlXPathWrapNodeSet(\r
-           xmlXPathNodeSetMerge(NULL, nodelist)));\r
-       if (key != NULL)\r
-           xmlFree(key);\r
-    }    \r
-\r
-    if (obj1 != NULL)\r
-       xmlXPathFreeObject(obj1);\r
-    if (obj2 != NULL)\r
-       xmlXPathFreeObject(obj2);    \r
-}\r
-\r
-/**\r
- * xsltUnparsedEntityURIFunction:\r
- * @ctxt:  the XPath Parser context\r
- * @nargs:  the number of arguments\r
- *\r
- * Implement the unparsed-entity-uri() XSLT function\r
- *   string unparsed-entity-uri(string)\r
- */\r
-void\r
-xsltUnparsedEntityURIFunction(xmlXPathParserContextPtr ctxt, int nargs){\r
-    xmlXPathObjectPtr obj;\r
-    xmlChar *str;\r
-\r
-    if ((nargs != 1) || (ctxt->value == NULL)) {\r
-        xsltGenericError(xsltGenericErrorContext,\r
-               "unparsed-entity-uri() : expects one string arg\n");\r
-       ctxt->error = XPATH_INVALID_ARITY;\r
-       return;\r
-    }\r
-    obj = valuePop(ctxt);\r
-    if (obj->type != XPATH_STRING) {\r
-       obj = xmlXPathConvertString(obj);\r
-    }\r
-\r
-    str = obj->stringval;\r
-    if (str == NULL) {\r
-       valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));\r
-    } else {\r
-       xmlEntityPtr entity;\r
-\r
-       entity = xmlGetDocEntity(ctxt->context->doc, str);\r
-       if (entity == NULL) {\r
-           valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));\r
-       } else {\r
-           if (entity->URI != NULL)\r
-               valuePush(ctxt, xmlXPathNewString(entity->URI));\r
-           else\r
-               valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));\r
-       }\r
-    }\r
-    xmlXPathFreeObject(obj);\r
-}\r
-\r
-/**\r
- * xsltFormatNumberFunction:\r
- * @ctxt:  the XPath Parser context\r
- * @nargs:  the number of arguments\r
- *\r
- * Implement the format-number() XSLT function\r
- *   string format-number(number, string, string?)\r
- */\r
-void\r
-xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)\r
-{\r
-    xmlXPathObjectPtr numberObj = NULL;\r
-    xmlXPathObjectPtr formatObj = NULL;\r
-    xmlXPathObjectPtr decimalObj = NULL;\r
-    xsltStylesheetPtr sheet;\r
-    xsltDecimalFormatPtr formatValues;\r
-    xmlChar *result;\r
-    xsltTransformContextPtr tctxt;\r
-\r
-    tctxt = xsltXPathGetTransformContext(ctxt);\r
-    if (tctxt == NULL)\r
-       return;\r
-    sheet = tctxt->style;\r
-    if (sheet == NULL)\r
-       return;\r
-    formatValues = sheet->decimalFormat;\r
-    \r
-    switch (nargs) {\r
-    case 3:\r
-       CAST_TO_STRING;\r
-       decimalObj = valuePop(ctxt);\r
-       formatValues = xsltDecimalFormatGetByName(sheet, decimalObj->stringval);\r
-       if (formatValues == NULL) {\r
-           xsltTransformError(tctxt, NULL, NULL,\r
-                   "format-number() : undeclared decimal format '%s'\n", \r
-                   decimalObj->stringval);\r
-       }\r
-       /* Intentional fall-through */\r
-    case 2:\r
-       CAST_TO_STRING;\r
-       formatObj = valuePop(ctxt);\r
-       CAST_TO_NUMBER;\r
-       numberObj = valuePop(ctxt);\r
-       break;\r
-    default:\r
-       XP_ERROR(XPATH_INVALID_ARITY);\r
-    }\r
-\r
-    if (formatValues != NULL) {\r
-       if (xsltFormatNumberConversion(formatValues,\r
-                                      formatObj->stringval,\r
-                                      numberObj->floatval,\r
-                                      &result) == XPATH_EXPRESSION_OK) {\r
-           valuePush(ctxt, xmlXPathNewString(result));\r
-           xmlFree(result);\r
-       }\r
-    }\r
-\r
-    xmlXPathFreeObject(numberObj);\r
-    xmlXPathFreeObject(formatObj);\r
-    xmlXPathFreeObject(decimalObj);\r
-}\r
-\r
-/**\r
- * xsltGenerateIdFunction:\r
- * @ctxt:  the XPath Parser context\r
- * @nargs:  the number of arguments\r
- *\r
- * Implement the generate-id() XSLT function\r
- *   string generate-id(node-set?)\r
- */\r
-void\r
-xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){\r
-    xmlNodePtr cur = NULL;\r
-    unsigned long val;\r
-    xmlChar str[20];\r
-\r
-    if (nargs == 0) {\r
-       cur = ctxt->context->node;\r
-    } else if (nargs == 1) {\r
-       xmlXPathObjectPtr obj;\r
-       xmlNodeSetPtr nodelist;\r
-       int i, ret;\r
-\r
-       if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) {\r
-           ctxt->error = XPATH_INVALID_TYPE;\r
-           xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-               "generate-id() : invalid arg expecting a node-set\n");\r
-           return;\r
-       }\r
-       obj = valuePop(ctxt);\r
-       nodelist = obj->nodesetval;\r
-       if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) {\r
-           xmlXPathFreeObject(obj);\r
-           valuePush(ctxt, xmlXPathNewCString(""));\r
-           return;\r
-       }\r
-       cur = nodelist->nodeTab[0];\r
-       for (i = 1;i < nodelist->nodeNr;i++) {\r
-           ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]);\r
-           if (ret == -1)\r
-               cur = nodelist->nodeTab[i];\r
-       }\r
-       xmlXPathFreeObject(obj);\r
-    } else {\r
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-               "generate-id() : invalid number of args %d\n", nargs);\r
-       ctxt->error = XPATH_INVALID_ARITY;\r
-       return;\r
-    }\r
-    /*\r
-     * Okay this is ugly but should work, use the NodePtr address\r
-     * to forge the ID\r
-     */\r
-    val = (unsigned long)((char *)cur - (char *)0);\r
-    val /= sizeof(xmlNode);\r
-    sprintf((char *)str, "id%ld", val);\r
-    valuePush(ctxt, xmlXPathNewString(str));\r
-}\r
-\r
-/**\r
- * xsltSystemPropertyFunction:\r
- * @ctxt:  the XPath Parser context\r
- * @nargs:  the number of arguments\r
- *\r
- * Implement the system-property() XSLT function\r
- *   object system-property(string)\r
- */\r
-void\r
-xsltSystemPropertyFunction(xmlXPathParserContextPtr ctxt, int nargs){\r
-    xmlXPathObjectPtr obj;\r
-    xmlChar *prefix, *name;\r
-    const xmlChar *nsURI = NULL;\r
-\r
-    if (nargs != 1) {\r
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-               "system-property() : expects one string arg\n");\r
-       ctxt->error = XPATH_INVALID_ARITY;\r
-       return;\r
-    }\r
-    if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {\r
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-           "system-property() : invalid arg expecting a string\n");\r
-       ctxt->error = XPATH_INVALID_TYPE;\r
-       return;\r
-    }\r
-    obj = valuePop(ctxt);\r
-    if (obj->stringval == NULL) {\r
-       valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));\r
-    } else {\r
-       name = xmlSplitQName2(obj->stringval, &prefix);\r
-       if (name == NULL) {\r
-           name = xmlStrdup(obj->stringval);\r
-       } else {\r
-           nsURI = xmlXPathNsLookup(ctxt->context, prefix);\r
-           if (nsURI == NULL) {\r
-               xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-                   "system-property() : prefix %s is not bound\n", prefix);\r
-           }\r
-       }\r
-\r
-       if (xmlStrEqual(nsURI, XSLT_NAMESPACE)) {\r
-#ifdef DOCBOOK_XSL_HACK\r
-           if (xmlStrEqual(name, (const xmlChar *)"vendor")) {\r
-               xsltStylesheetPtr sheet;\r
-               xsltTransformContextPtr tctxt;\r
-\r
-               tctxt = xsltXPathGetTransformContext(ctxt);\r
-               if ((tctxt != NULL) && (tctxt->inst != NULL) &&\r
-                   (xmlStrEqual(tctxt->inst->name, BAD_CAST "variable")) &&\r
-                   (tctxt->inst->parent != NULL) &&\r
-                   (xmlStrEqual(tctxt->inst->parent->name,\r
-                                BAD_CAST "template")))\r
-                   sheet = tctxt->style;\r
-               else\r
-                   sheet = NULL;\r
-               if ((sheet != NULL) && (sheet->doc != NULL) &&\r
-                   (sheet->doc->URL != NULL) &&\r
-                   (xmlStrstr(sheet->doc->URL,\r
-                              (const xmlChar *)"chunk") != NULL)) {\r
-                   valuePush(ctxt, xmlXPathNewString(\r
-                       (const xmlChar *)"libxslt (SAXON 6.2 compatible)"));\r
-\r
-               } else {\r
-                   valuePush(ctxt, xmlXPathNewString(\r
-                       (const xmlChar *)XSLT_DEFAULT_VENDOR));\r
-               }\r
-           } else\r
-#else\r
-           if (xmlStrEqual(name, (const xmlChar *)"vendor")) {\r
-               valuePush(ctxt, xmlXPathNewString(\r
-                         (const xmlChar *)XSLT_DEFAULT_VENDOR));\r
-           } else\r
-#endif\r
-           if (xmlStrEqual(name, (const xmlChar *)"version")) {\r
-               valuePush(ctxt, xmlXPathNewString(\r
-                   (const xmlChar *)XSLT_DEFAULT_VERSION));\r
-           } else if (xmlStrEqual(name, (const xmlChar *)"vendor-url")) {\r
-               valuePush(ctxt, xmlXPathNewString(\r
-                   (const xmlChar *)XSLT_DEFAULT_URL));\r
-           } else {\r
-               valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));\r
-           }\r
-       }\r
-       if (name != NULL)\r
-           xmlFree(name);\r
-       if (prefix != NULL)\r
-           xmlFree(prefix);\r
-    }\r
-    xmlXPathFreeObject(obj);\r
-}\r
-\r
-/**\r
- * xsltElementAvailableFunction:\r
- * @ctxt:  the XPath Parser context\r
- * @nargs:  the number of arguments\r
- *\r
- * Implement the element-available() XSLT function\r
- *   boolean element-available(string)\r
- */\r
-void\r
-xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){\r
-    xmlXPathObjectPtr obj;\r
-    xmlChar *prefix, *name;\r
-    const xmlChar *nsURI = NULL;\r
-    xsltTransformContextPtr tctxt;\r
-\r
-    if (nargs != 1) {\r
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-               "element-available() : expects one string arg\n");\r
-       ctxt->error = XPATH_INVALID_ARITY;\r
-       return;\r
-    }\r
-    if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {\r
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-           "element-available() : invalid arg expecting a string\n");\r
-       ctxt->error = XPATH_INVALID_TYPE;\r
-       return;\r
-    }\r
-    obj = valuePop(ctxt);\r
-    tctxt = xsltXPathGetTransformContext(ctxt);\r
-    if (tctxt == NULL) {\r
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-               "element-available() : internal error tctxt == NULL\n");\r
-       xmlXPathFreeObject(obj);\r
-       valuePush(ctxt, xmlXPathNewBoolean(0));\r
-       return;\r
-    }\r
-\r
-\r
-    name = xmlSplitQName2(obj->stringval, &prefix);\r
-    if (name == NULL) {\r
-       xmlNsPtr ns;\r
-\r
-       name = xmlStrdup(obj->stringval);\r
-       ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL);\r
-       if (ns != NULL) nsURI = xmlStrdup(ns->href);\r
-    } else {\r
-       nsURI = xmlXPathNsLookup(ctxt->context, prefix);\r
-       if (nsURI == NULL) {\r
-           xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-               "element-available() : prefix %s is not bound\n", prefix);\r
-       }\r
-    }\r
-\r
-    if (xsltExtElementLookup(tctxt, name, nsURI) != NULL) {\r
-       valuePush(ctxt, xmlXPathNewBoolean(1));\r
-    } else {\r
-       valuePush(ctxt, xmlXPathNewBoolean(0));\r
-    }\r
-\r
-    xmlXPathFreeObject(obj);\r
-    if (name != NULL)\r
-       xmlFree(name);\r
-    if (prefix != NULL)\r
-       xmlFree(prefix);\r
-}\r
-\r
-/**\r
- * xsltFunctionAvailableFunction:\r
- * @ctxt:  the XPath Parser context\r
- * @nargs:  the number of arguments\r
- *\r
- * Implement the function-available() XSLT function\r
- *   boolean function-available(string)\r
- */\r
-void\r
-xsltFunctionAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){\r
-    xmlXPathObjectPtr obj;\r
-    xmlChar *prefix, *name;\r
-    const xmlChar *nsURI = NULL;\r
-\r
-    if (nargs != 1) {\r
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-               "function-available() : expects one string arg\n");\r
-       ctxt->error = XPATH_INVALID_ARITY;\r
-       return;\r
-    }\r
-    if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {\r
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-           "function-available() : invalid arg expecting a string\n");\r
-       ctxt->error = XPATH_INVALID_TYPE;\r
-       return;\r
-    }\r
-    obj = valuePop(ctxt);\r
-\r
-    name = xmlSplitQName2(obj->stringval, &prefix);\r
-    if (name == NULL) {\r
-       name = xmlStrdup(obj->stringval);\r
-    } else {\r
-       nsURI = xmlXPathNsLookup(ctxt->context, prefix);\r
-       if (nsURI == NULL) {\r
-           xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-               "function-available() : prefix %s is not bound\n", prefix);\r
-       }\r
-    }\r
-\r
-    if (xmlXPathFunctionLookupNS(ctxt->context, name, nsURI) != NULL) {\r
-       valuePush(ctxt, xmlXPathNewBoolean(1));\r
-    } else {\r
-       valuePush(ctxt, xmlXPathNewBoolean(0));\r
-    }\r
-\r
-    xmlXPathFreeObject(obj);\r
-    if (name != NULL)\r
-       xmlFree(name);\r
-    if (prefix != NULL)\r
-       xmlFree(prefix);\r
-}\r
-\r
-/**\r
- * xsltCurrentFunction:\r
- * @ctxt:  the XPath Parser context\r
- * @nargs:  the number of arguments\r
- *\r
- * Implement the current() XSLT function\r
- *   node-set current()\r
- */\r
-static void\r
-xsltCurrentFunction(xmlXPathParserContextPtr ctxt, int nargs){\r
-    xsltTransformContextPtr tctxt;\r
-\r
-    if (nargs != 0) {\r
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-               "current() : function uses no argument\n");\r
-       ctxt->error = XPATH_INVALID_ARITY;\r
-       return;\r
-    }\r
-    tctxt = xsltXPathGetTransformContext(ctxt);\r
-    if (tctxt == NULL) {\r
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,\r
-               "current() : internal error tctxt == NULL\n");\r
-       valuePush(ctxt, xmlXPathNewNodeSet(NULL));\r
-    } else {\r
-       valuePush(ctxt, xmlXPathNewNodeSet(tctxt->node)); /* current */\r
-    }\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Registration of XSLT and libxslt functions              *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltRegisterAllFunctions:\r
- * @ctxt:  the XPath context\r
- *\r
- * Registers all default XSLT functions in this context\r
- */\r
-void\r
-xsltRegisterAllFunctions(xmlXPathContextPtr ctxt)\r
-{\r
-    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "current",\r
-                         xsltCurrentFunction);\r
-    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "document",\r
-                         xsltDocumentFunction);\r
-    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "key", xsltKeyFunction);\r
-    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "unparsed-entity-uri",\r
-                         xsltUnparsedEntityURIFunction);\r
-    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "format-number",\r
-                         xsltFormatNumberFunction);\r
-    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "generate-id",\r
-                         xsltGenerateIdFunction);\r
-    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "system-property",\r
-                         xsltSystemPropertyFunction);\r
-    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "element-available",\r
-                         xsltElementAvailableFunction);\r
-    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "function-available",\r
-                         xsltFunctionAvailableFunction);\r
-}\r
+/*
+ * functions.c: Implementation of the XSLT extra functions
+ *
+ * Reference:
+ *   http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ * Bjorn Reese <breese@users.sourceforge.net> for number formatting
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/valid.h>
+#include <libxml/hash.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/parserInternals.h>
+#include <libxml/uri.h>
+#include <libxml/xpointer.h>
+#include "xslt.h"
+#include "xsltInternals.h"
+#include "xsltutils.h"
+#include "functions.h"
+#include "extensions.h"
+#include "numbersInternals.h"
+#include "keys.h"
+#include "documents.h"
+
+#ifdef WITH_XSLT_DEBUG
+#define WITH_XSLT_DEBUG_FUNCTION
+#endif
+
+/*
+ * Some versions of DocBook XSL use the vendor string to detect
+ * supporting chunking, this is a workaround to be considered
+ * in the list of decent XSLT processors <grin/>
+ */
+#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 (xmlXPathContextPtr ctxt,
+                        const xmlChar *name, const xmlChar *ns_uri) {
+    xmlXPathFunction ret;
+
+    if ((ctxt == NULL) || (name == NULL) || (ns_uri == NULL))
+       return (NULL);
+
+#ifdef WITH_XSLT_DEBUG_FUNCTION
+    xsltGenericDebug(xsltGenericDebugContext,
+            "Lookup function {%s}%s\n", ns_uri, name);
+#endif
+
+    /* give priority to context-level functions */
+    /*
+    ret = (xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri);
+    */
+    XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->funcHash, name, ns_uri);
+
+    if (ret == NULL)
+       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                               *
+ *                                                                     *
+ ************************************************************************/
+
+static void
+xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI)
+{
+    xsltTransformContextPtr tctxt;
+    xmlURIPtr uri;
+    xmlChar *fragment;
+    xsltDocumentPtr idoc; /* document info */
+    xmlDocPtr doc;
+    xmlXPathContextPtr xptrctxt = NULL;
+    xmlXPathObjectPtr resObj = NULL;
+
+    tctxt = xsltXPathGetTransformContext(ctxt);
+    if (tctxt == NULL) {
+       xsltTransformError(NULL, NULL, NULL,
+           "document() : internal error tctxt == NULL\n");
+       valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+       return;
+    } 
+       
+    uri = xmlParseURI((const char *) URI);
+    if (uri == NULL) {
+       xsltTransformError(tctxt, NULL, NULL,
+           "document() : failed to parse URI\n");
+       valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+       return;
+    } 
+    
+    /*
+     * check for and remove fragment identifier
+     */
+    fragment = (xmlChar *)uri->fragment;
+    if (fragment != NULL) {
+       uri->fragment = NULL;
+       URI = xmlSaveUri(uri);
+       idoc = xsltLoadDocument(tctxt, URI);
+       xmlFree(URI);
+    } else
+       idoc = xsltLoadDocument(tctxt, URI);
+    xmlFreeURI(uri);
+    
+    if (idoc == NULL) {
+       if ((URI == NULL) ||
+           (URI[0] == '#') ||
+           (xmlStrEqual(tctxt->style->doc->URL, URI))) 
+       {
+           /*
+           * This selects the stylesheet's doc itself.
+           */
+           doc = tctxt->style->doc;
+       } else {
+           valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+
+           if (fragment != NULL)
+               xmlFree(fragment);
+
+           return;
+       }
+    } else
+       doc = idoc->doc;
+
+    if (fragment == NULL) {
+       valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc));
+       return;
+    }
+       
+    /* use XPointer of HTML location for fragment ID */
+#ifdef LIBXML_XPTR_ENABLED
+    xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
+    if (xptrctxt == NULL) {
+       xsltTransformError(tctxt, NULL, NULL,
+           "document() : internal error xptrctxt == NULL\n");
+       goto out_fragment;
+    }
+
+    resObj = xmlXPtrEval(fragment, xptrctxt);
+    xmlXPathFreeContext(xptrctxt);
+#endif
+    xmlFree(fragment); 
+
+    if (resObj == NULL)
+       goto out_fragment;
+       
+    switch (resObj->type) {
+       case XPATH_NODESET:
+           break;
+       case XPATH_UNDEFINED:
+       case XPATH_BOOLEAN:
+       case XPATH_NUMBER:
+       case XPATH_STRING:
+       case XPATH_POINT:
+       case XPATH_USERS:
+       case XPATH_XSLT_TREE:
+       case XPATH_RANGE:
+       case XPATH_LOCATIONSET:
+           xsltTransformError(tctxt, NULL, NULL,
+               "document() : XPointer does not select a node set: #%s\n", 
+               fragment);
+       goto out_object;
+    }
+    
+    valuePush(ctxt, resObj);
+    return;
+
+out_object:
+    xmlXPathFreeObject(resObj);
+
+out_fragment:
+    valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+}
+
+/**
+ * xsltDocumentFunction:
+ * @ctxt:  the XPath Parser context
+ * @nargs:  the number of arguments
+ *
+ * Implement the document() XSLT function
+ *   node-set document(object, node-set?)
+ */
+void
+xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+    xmlXPathObjectPtr obj, obj2 = NULL;
+    xmlChar *base = NULL, *URI;
+
+
+    if ((nargs < 1) || (nargs > 2)) {
+        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+                         "document() : invalid number of args %d\n",
+                         nargs);
+        ctxt->error = XPATH_INVALID_ARITY;
+        return;
+    }
+    if (ctxt->value == NULL) {
+        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+                         "document() : invalid arg value\n");
+        ctxt->error = XPATH_INVALID_TYPE;
+        return;
+    }
+
+    if (nargs == 2) {
+        if (ctxt->value->type != XPATH_NODESET) {
+            xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+                             "document() : invalid arg expecting a nodeset\n");
+            ctxt->error = XPATH_INVALID_TYPE;
+            return;
+        }
+
+        obj2 = valuePop(ctxt);
+    }
+
+    if (ctxt->value->type == XPATH_NODESET) {
+        int i;
+        xmlXPathObjectPtr newobj, ret;
+
+        obj = valuePop(ctxt);
+        ret = xmlXPathNewNodeSet(NULL);
+
+        if (obj->nodesetval) {
+            for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+                valuePush(ctxt,
+                          xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i]));
+                xmlXPathStringFunction(ctxt, 1);
+                if (nargs == 2) {
+                    valuePush(ctxt, xmlXPathObjectCopy(obj2));
+                } else {
+                    valuePush(ctxt,
+                              xmlXPathNewNodeSet(obj->nodesetval->
+                                                 nodeTab[i]));
+                }
+                xsltDocumentFunction(ctxt, 2);
+                newobj = valuePop(ctxt);
+                ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
+                                                       newobj->nodesetval);
+                xmlXPathFreeObject(newobj);
+            }
+        }
+
+        xmlXPathFreeObject(obj);
+        if (obj2 != NULL)
+            xmlXPathFreeObject(obj2);
+        valuePush(ctxt, ret);
+        return;
+    }
+    /*
+     * Make sure it's converted to a string
+     */
+    xmlXPathStringFunction(ctxt, 1);
+    if (ctxt->value->type != XPATH_STRING) {
+        xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+                         "document() : invalid arg expecting a string\n");
+        ctxt->error = XPATH_INVALID_TYPE;
+        if (obj2 != NULL)
+            xmlXPathFreeObject(obj2);
+        return;
+    }
+    obj = valuePop(ctxt);
+    if (obj->stringval == NULL) {
+        valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+    } else {
+        if ((obj2 != NULL) && (obj2->nodesetval != NULL) &&
+            (obj2->nodesetval->nodeNr > 0) &&
+            IS_XSLT_REAL_NODE(obj2->nodesetval->nodeTab[0])) {
+            xmlNodePtr target;
+
+            target = obj2->nodesetval->nodeTab[0];
+            if ((target->type == XML_ATTRIBUTE_NODE) ||
+               (target->type == XML_PI_NODE)) {
+                target = ((xmlAttrPtr) target)->parent;
+            }
+            base = xmlNodeGetBase(target->doc, target);
+        } else {
+            xsltTransformContextPtr tctxt;
+
+            tctxt = xsltXPathGetTransformContext(ctxt);
+            if ((tctxt != NULL) && (tctxt->inst != NULL)) {
+                base = xmlNodeGetBase(tctxt->inst->doc, tctxt->inst);
+            } else if ((tctxt != NULL) && (tctxt->style != NULL) &&
+                       (tctxt->style->doc != NULL)) {
+                base = xmlNodeGetBase(tctxt->style->doc,
+                                      (xmlNodePtr) tctxt->style->doc);
+            }
+        }
+        URI = xmlBuildURI(obj->stringval, base);
+        if (base != NULL)
+            xmlFree(base);
+        if (URI == NULL) {
+            valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+        } else {
+           xsltDocumentFunctionLoadDocument( ctxt, URI );
+           xmlFree(URI);
+       }
+    }
+    xmlXPathFreeObject(obj);
+    if (obj2 != NULL)
+        xmlXPathFreeObject(obj2);
+}
+
+/**
+ * xsltKeyFunction:
+ * @ctxt:  the XPath Parser context
+ * @nargs:  the number of arguments
+ *
+ * Implement the key() XSLT function
+ *   node-set key(string, object)
+ */
+void
+xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){    
+    xmlXPathObjectPtr obj1, obj2;    
+    
+    if (nargs != 2) {
+       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+               "key() : expects two arguments\n");
+       ctxt->error = XPATH_INVALID_ARITY;
+       return;
+    }    
+
+    /*
+    * Get the key's value.
+    */
+    obj2 = valuePop(ctxt);
+    xmlXPathStringFunction(ctxt, 1);
+    if ((obj2 == NULL) ||
+       (ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
+       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+           "key() : invalid arg expecting a string\n");
+       ctxt->error = XPATH_INVALID_TYPE;
+       xmlXPathFreeObject(obj2);
+
+       return;
+    }
+    /*
+    * Get the key's name.
+    */
+    obj1 = valuePop(ctxt);    
+
+    if ((obj2->type == XPATH_NODESET) || (obj2->type == XPATH_XSLT_TREE)) {
+       int i;
+       xmlXPathObjectPtr newobj, ret;
+
+       ret = xmlXPathNewNodeSet(NULL);
+
+       if (obj2->nodesetval != NULL) {
+           for (i = 0; i < obj2->nodesetval->nodeNr; i++) {
+               valuePush(ctxt, xmlXPathObjectCopy(obj1));
+               valuePush(ctxt,
+                         xmlXPathNewNodeSet(obj2->nodesetval->nodeTab[i]));
+               xmlXPathStringFunction(ctxt, 1);
+               xsltKeyFunction(ctxt, 2);
+               newobj = valuePop(ctxt);
+               ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
+                                                      newobj->nodesetval);
+               xmlXPathFreeObject(newobj);
+           }
+       }
+       valuePush(ctxt, ret);
+    } else {
+       xmlNodeSetPtr nodelist = NULL;
+       xmlChar *key = NULL, *value;
+       const xmlChar *keyURI;
+       xsltTransformContextPtr tctxt;   
+       xmlChar *qname, *prefix;
+       xmlXPathContextPtr xpctxt = ctxt->context;
+       xmlNodePtr tmpNode = NULL;
+       xsltDocumentPtr oldDocInfo;
+
+       tctxt = xsltXPathGetTransformContext(ctxt);
+
+       oldDocInfo = tctxt->document;
+
+       if (xpctxt->node == NULL) {
+           xsltTransformError(tctxt, NULL, tctxt->inst,
+               "Internal error in xsltKeyFunction(): "
+               "The context node is not set on the XPath context.\n");
+           tctxt->state = XSLT_STATE_STOPPED;
+           goto error;
+       }       
+       /*
+        * Get the associated namespace URI if qualified name
+        */
+       qname = obj1->stringval;
+       key = xmlSplitQName2(qname, &prefix);
+       if (key == NULL) {
+           key = xmlStrdup(obj1->stringval);
+           keyURI = NULL;
+           if (prefix != NULL)
+               xmlFree(prefix);
+       } else {
+           if (prefix != NULL) {
+               keyURI = xmlXPathNsLookup(xpctxt, prefix);
+               if (keyURI == NULL) {
+                   xsltTransformError(tctxt, NULL, tctxt->inst,
+                       "key() : prefix %s is not bound\n", prefix);
+                   /*
+                   * TODO: Shouldn't we stop here?
+                   */
+               }
+               xmlFree(prefix);
+           } else {
+               keyURI = NULL;
+           }
+       }
+
+       /*
+        * Force conversion of first arg to string
+        */
+       valuePush(ctxt, obj2);
+       xmlXPathStringFunction(ctxt, 1);
+       if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
+           xsltTransformError(tctxt, NULL, tctxt->inst,
+               "key() : invalid arg expecting a string\n");
+           ctxt->error = XPATH_INVALID_TYPE;
+           goto error;
+       }
+       obj2 = valuePop(ctxt);
+       value = obj2->stringval;
+       
+       /*
+       * We need to ensure that ctxt->document is available for
+       * xsltGetKey().
+       * First find the relevant doc, which is the context node's
+       * owner doc; using context->doc is not safe, since
+       * the doc could have been acquired via the document() function,
+       * or the doc might be a Result Tree Fragment.
+       * FUTURE INFO: In XSLT 2.0 the key() function takes an additional
+       * argument indicating the doc to use.
+       */      
+       if (xpctxt->node->type == XML_NAMESPACE_DECL) {
+           /*
+           * REVISIT: This is a libxml hack! Check xpath.c for details.
+           * The XPath module sets the owner element of a ns-node on
+           * the ns->next field.
+           */
+           if ((((xmlNsPtr) xpctxt->node)->next != NULL) &&
+               (((xmlNsPtr) xpctxt->node)->next->type == XML_ELEMENT_NODE))
+           {
+               tmpNode = (xmlNodePtr) ((xmlNsPtr) xpctxt->node)->next;
+           }
+       } else
+           tmpNode = xpctxt->node;
+
+       if ((tmpNode == NULL) || (tmpNode->doc == NULL)) {
+           xsltTransformError(tctxt, NULL, tctxt->inst,
+               "Internal error in xsltKeyFunction(): "
+               "Couldn't get the doc of the XPath context node.\n");
+           goto error;
+       }
+
+       if ((tctxt->document == NULL) ||
+           (tctxt->document->doc != tmpNode->doc))
+       {          
+           if (tmpNode->doc->name && (tmpNode->doc->name[0] == ' ')) {
+               /*
+               * This is a Result Tree Fragment.
+               */
+               if (tmpNode->doc->_private == NULL) {
+                   tmpNode->doc->_private = xsltNewDocument(tctxt, tmpNode->doc);
+                   if (tmpNode->doc->_private == NULL)
+                       goto error;
+               }
+               tctxt->document = (xsltDocumentPtr) tmpNode->doc->_private;             
+           } else {
+               /*
+               * May be the initial source doc or a doc acquired via the
+               * document() function.
+               */
+               tctxt->document = xsltFindDocument(tctxt, tmpNode->doc);
+           }
+           if (tctxt->document == NULL) {
+               xsltTransformError(tctxt, NULL, tctxt->inst,
+                   "Internal error in xsltKeyFunction(): "
+                   "Could not get the document info of a context doc.\n");
+               tctxt->state = XSLT_STATE_STOPPED;
+               goto error;
+           }
+       }
+       /*
+       * Get/compute the key value.
+       */
+       nodelist = xsltGetKey(tctxt, key, keyURI, value);
+
+error: 
+       tctxt->document = oldDocInfo;
+       valuePush(ctxt, xmlXPathWrapNodeSet(
+           xmlXPathNodeSetMerge(NULL, nodelist)));
+       if (key != NULL)
+           xmlFree(key);
+    }    
+
+    if (obj1 != NULL)
+       xmlXPathFreeObject(obj1);
+    if (obj2 != NULL)
+       xmlXPathFreeObject(obj2);    
+}
+
+/**
+ * xsltUnparsedEntityURIFunction:
+ * @ctxt:  the XPath Parser context
+ * @nargs:  the number of arguments
+ *
+ * Implement the unparsed-entity-uri() XSLT function
+ *   string unparsed-entity-uri(string)
+ */
+void
+xsltUnparsedEntityURIFunction(xmlXPathParserContextPtr ctxt, int nargs){
+    xmlXPathObjectPtr obj;
+    xmlChar *str;
+
+    if ((nargs != 1) || (ctxt->value == NULL)) {
+        xsltGenericError(xsltGenericErrorContext,
+               "unparsed-entity-uri() : expects one string arg\n");
+       ctxt->error = XPATH_INVALID_ARITY;
+       return;
+    }
+    obj = valuePop(ctxt);
+    if (obj->type != XPATH_STRING) {
+       obj = xmlXPathConvertString(obj);
+    }
+
+    str = obj->stringval;
+    if (str == NULL) {
+       valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
+    } else {
+       xmlEntityPtr entity;
+
+       entity = xmlGetDocEntity(ctxt->context->doc, str);
+       if (entity == NULL) {
+           valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
+       } else {
+           if (entity->URI != NULL)
+               valuePush(ctxt, xmlXPathNewString(entity->URI));
+           else
+               valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
+       }
+    }
+    xmlXPathFreeObject(obj);
+}
+
+/**
+ * xsltFormatNumberFunction:
+ * @ctxt:  the XPath Parser context
+ * @nargs:  the number of arguments
+ *
+ * Implement the format-number() XSLT function
+ *   string format-number(number, string, string?)
+ */
+void
+xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+    xmlXPathObjectPtr numberObj = NULL;
+    xmlXPathObjectPtr formatObj = NULL;
+    xmlXPathObjectPtr decimalObj = NULL;
+    xsltStylesheetPtr sheet;
+    xsltDecimalFormatPtr formatValues;
+    xmlChar *result;
+    xsltTransformContextPtr tctxt;
+
+    tctxt = xsltXPathGetTransformContext(ctxt);
+    if (tctxt == NULL)
+       return;
+    sheet = tctxt->style;
+    if (sheet == NULL)
+       return;
+    formatValues = sheet->decimalFormat;
+    
+    switch (nargs) {
+    case 3:
+       CAST_TO_STRING;
+       decimalObj = valuePop(ctxt);
+       formatValues = xsltDecimalFormatGetByName(sheet, decimalObj->stringval);
+       if (formatValues == NULL) {
+           xsltTransformError(tctxt, NULL, NULL,
+                   "format-number() : undeclared decimal format '%s'\n", 
+                   decimalObj->stringval);
+       }
+       /* Intentional fall-through */
+    case 2:
+       CAST_TO_STRING;
+       formatObj = valuePop(ctxt);
+       CAST_TO_NUMBER;
+       numberObj = valuePop(ctxt);
+       break;
+    default:
+       XP_ERROR(XPATH_INVALID_ARITY);
+    }
+
+    if (formatValues != NULL) {
+       if (xsltFormatNumberConversion(formatValues,
+                                      formatObj->stringval,
+                                      numberObj->floatval,
+                                      &result) == XPATH_EXPRESSION_OK) {
+           valuePush(ctxt, xmlXPathNewString(result));
+           xmlFree(result);
+       }
+    }
+
+    xmlXPathFreeObject(numberObj);
+    xmlXPathFreeObject(formatObj);
+    xmlXPathFreeObject(decimalObj);
+}
+
+/**
+ * xsltGenerateIdFunction:
+ * @ctxt:  the XPath Parser context
+ * @nargs:  the number of arguments
+ *
+ * Implement the generate-id() XSLT function
+ *   string generate-id(node-set?)
+ */
+void
+xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){
+    xmlNodePtr cur = NULL;
+    unsigned long val;
+    xmlChar str[20];
+
+    if (nargs == 0) {
+       cur = ctxt->context->node;
+    } else if (nargs == 1) {
+       xmlXPathObjectPtr obj;
+       xmlNodeSetPtr nodelist;
+       int i, ret;
+
+       if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) {
+           ctxt->error = XPATH_INVALID_TYPE;
+           xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+               "generate-id() : invalid arg expecting a node-set\n");
+           return;
+       }
+       obj = valuePop(ctxt);
+       nodelist = obj->nodesetval;
+       if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) {
+           xmlXPathFreeObject(obj);
+           valuePush(ctxt, xmlXPathNewCString(""));
+           return;
+       }
+       cur = nodelist->nodeTab[0];
+       for (i = 1;i < nodelist->nodeNr;i++) {
+           ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]);
+           if (ret == -1)
+               cur = nodelist->nodeTab[i];
+       }
+       xmlXPathFreeObject(obj);
+    } else {
+       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+               "generate-id() : invalid number of args %d\n", nargs);
+       ctxt->error = XPATH_INVALID_ARITY;
+       return;
+    }
+    /*
+     * Okay this is ugly but should work, use the NodePtr address
+     * to forge the ID
+     */
+    val = (unsigned long)((char *)cur - (char *)0);
+    val /= sizeof(xmlNode);
+    sprintf((char *)str, "id%ld", val);
+    valuePush(ctxt, xmlXPathNewString(str));
+}
+
+/**
+ * xsltSystemPropertyFunction:
+ * @ctxt:  the XPath Parser context
+ * @nargs:  the number of arguments
+ *
+ * Implement the system-property() XSLT function
+ *   object system-property(string)
+ */
+void
+xsltSystemPropertyFunction(xmlXPathParserContextPtr ctxt, int nargs){
+    xmlXPathObjectPtr obj;
+    xmlChar *prefix, *name;
+    const xmlChar *nsURI = NULL;
+
+    if (nargs != 1) {
+       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+               "system-property() : expects one string arg\n");
+       ctxt->error = XPATH_INVALID_ARITY;
+       return;
+    }
+    if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
+       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+           "system-property() : invalid arg expecting a string\n");
+       ctxt->error = XPATH_INVALID_TYPE;
+       return;
+    }
+    obj = valuePop(ctxt);
+    if (obj->stringval == NULL) {
+       valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
+    } else {
+       name = xmlSplitQName2(obj->stringval, &prefix);
+       if (name == NULL) {
+           name = xmlStrdup(obj->stringval);
+       } else {
+           nsURI = xmlXPathNsLookup(ctxt->context, prefix);
+           if (nsURI == NULL) {
+               xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+                   "system-property() : prefix %s is not bound\n", prefix);
+           }
+       }
+
+       if (xmlStrEqual(nsURI, XSLT_NAMESPACE)) {
+#ifdef DOCBOOK_XSL_HACK
+           if (xmlStrEqual(name, (const xmlChar *)"vendor")) {
+               xsltStylesheetPtr sheet;
+               xsltTransformContextPtr tctxt;
+
+               tctxt = xsltXPathGetTransformContext(ctxt);
+               if ((tctxt != NULL) && (tctxt->inst != NULL) &&
+                   (xmlStrEqual(tctxt->inst->name, BAD_CAST "variable")) &&
+                   (tctxt->inst->parent != NULL) &&
+                   (xmlStrEqual(tctxt->inst->parent->name,
+                                BAD_CAST "template")))
+                   sheet = tctxt->style;
+               else
+                   sheet = NULL;
+               if ((sheet != NULL) && (sheet->doc != NULL) &&
+                   (sheet->doc->URL != NULL) &&
+                   (xmlStrstr(sheet->doc->URL,
+                              (const xmlChar *)"chunk") != NULL)) {
+                   valuePush(ctxt, xmlXPathNewString(
+                       (const xmlChar *)"libxslt (SAXON 6.2 compatible)"));
+
+               } else {
+                   valuePush(ctxt, xmlXPathNewString(
+                       (const xmlChar *)XSLT_DEFAULT_VENDOR));
+               }
+           } else
+#else
+           if (xmlStrEqual(name, (const xmlChar *)"vendor")) {
+               valuePush(ctxt, xmlXPathNewString(
+                         (const xmlChar *)XSLT_DEFAULT_VENDOR));
+           } else
+#endif
+           if (xmlStrEqual(name, (const xmlChar *)"version")) {
+               valuePush(ctxt, xmlXPathNewString(
+                   (const xmlChar *)XSLT_DEFAULT_VERSION));
+           } else if (xmlStrEqual(name, (const xmlChar *)"vendor-url")) {
+               valuePush(ctxt, xmlXPathNewString(
+                   (const xmlChar *)XSLT_DEFAULT_URL));
+           } else {
+               valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
+           }
+       }
+       if (name != NULL)
+           xmlFree(name);
+       if (prefix != NULL)
+           xmlFree(prefix);
+    }
+    xmlXPathFreeObject(obj);
+}
+
+/**
+ * xsltElementAvailableFunction:
+ * @ctxt:  the XPath Parser context
+ * @nargs:  the number of arguments
+ *
+ * Implement the element-available() XSLT function
+ *   boolean element-available(string)
+ */
+void
+xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
+    xmlXPathObjectPtr obj;
+    xmlChar *prefix, *name;
+    const xmlChar *nsURI = NULL;
+    xsltTransformContextPtr tctxt;
+
+    if (nargs != 1) {
+       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+               "element-available() : expects one string arg\n");
+       ctxt->error = XPATH_INVALID_ARITY;
+       return;
+    }
+    if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
+       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+           "element-available() : invalid arg expecting a string\n");
+       ctxt->error = XPATH_INVALID_TYPE;
+       return;
+    }
+    obj = valuePop(ctxt);
+    tctxt = xsltXPathGetTransformContext(ctxt);
+    if (tctxt == NULL) {
+       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+               "element-available() : internal error tctxt == NULL\n");
+       xmlXPathFreeObject(obj);
+       valuePush(ctxt, xmlXPathNewBoolean(0));
+       return;
+    }
+
+
+    name = xmlSplitQName2(obj->stringval, &prefix);
+    if (name == NULL) {
+       xmlNsPtr ns;
+
+       name = xmlStrdup(obj->stringval);
+       ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL);
+       if (ns != NULL) nsURI = xmlStrdup(ns->href);
+    } else {
+       nsURI = xmlXPathNsLookup(ctxt->context, prefix);
+       if (nsURI == NULL) {
+           xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+               "element-available() : prefix %s is not bound\n", prefix);
+       }
+    }
+
+    if (xsltExtElementLookup(tctxt, name, nsURI) != NULL) {
+       valuePush(ctxt, xmlXPathNewBoolean(1));
+    } else {
+       valuePush(ctxt, xmlXPathNewBoolean(0));
+    }
+
+    xmlXPathFreeObject(obj);
+    if (name != NULL)
+       xmlFree(name);
+    if (prefix != NULL)
+       xmlFree(prefix);
+}
+
+/**
+ * xsltFunctionAvailableFunction:
+ * @ctxt:  the XPath Parser context
+ * @nargs:  the number of arguments
+ *
+ * Implement the function-available() XSLT function
+ *   boolean function-available(string)
+ */
+void
+xsltFunctionAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
+    xmlXPathObjectPtr obj;
+    xmlChar *prefix, *name;
+    const xmlChar *nsURI = NULL;
+
+    if (nargs != 1) {
+       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+               "function-available() : expects one string arg\n");
+       ctxt->error = XPATH_INVALID_ARITY;
+       return;
+    }
+    if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
+       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+           "function-available() : invalid arg expecting a string\n");
+       ctxt->error = XPATH_INVALID_TYPE;
+       return;
+    }
+    obj = valuePop(ctxt);
+
+    name = xmlSplitQName2(obj->stringval, &prefix);
+    if (name == NULL) {
+       name = xmlStrdup(obj->stringval);
+    } else {
+       nsURI = xmlXPathNsLookup(ctxt->context, prefix);
+       if (nsURI == NULL) {
+           xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+               "function-available() : prefix %s is not bound\n", prefix);
+       }
+    }
+
+    if (xmlXPathFunctionLookupNS(ctxt->context, name, nsURI) != NULL) {
+       valuePush(ctxt, xmlXPathNewBoolean(1));
+    } else {
+       valuePush(ctxt, xmlXPathNewBoolean(0));
+    }
+
+    xmlXPathFreeObject(obj);
+    if (name != NULL)
+       xmlFree(name);
+    if (prefix != NULL)
+       xmlFree(prefix);
+}
+
+/**
+ * xsltCurrentFunction:
+ * @ctxt:  the XPath Parser context
+ * @nargs:  the number of arguments
+ *
+ * Implement the current() XSLT function
+ *   node-set current()
+ */
+static void
+xsltCurrentFunction(xmlXPathParserContextPtr ctxt, int nargs){
+    xsltTransformContextPtr tctxt;
+
+    if (nargs != 0) {
+       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+               "current() : function uses no argument\n");
+       ctxt->error = XPATH_INVALID_ARITY;
+       return;
+    }
+    tctxt = xsltXPathGetTransformContext(ctxt);
+    if (tctxt == NULL) {
+       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
+               "current() : internal error tctxt == NULL\n");
+       valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+    } else {
+       valuePush(ctxt, xmlXPathNewNodeSet(tctxt->node)); /* current */
+    }
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Registration of XSLT and libxslt functions              *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltRegisterAllFunctions:
+ * @ctxt:  the XPath context
+ *
+ * Registers all default XSLT functions in this context
+ */
+void
+xsltRegisterAllFunctions(xmlXPathContextPtr ctxt)
+{
+    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "current",
+                         xsltCurrentFunction);
+    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "document",
+                         xsltDocumentFunction);
+    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "key", xsltKeyFunction);
+    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "unparsed-entity-uri",
+                         xsltUnparsedEntityURIFunction);
+    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "format-number",
+                         xsltFormatNumberFunction);
+    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "generate-id",
+                         xsltGenerateIdFunction);
+    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "system-property",
+                         xsltSystemPropertyFunction);
+    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "element-available",
+                         xsltElementAvailableFunction);
+    xmlXPathRegisterFunc(ctxt, (const xmlChar *) "function-available",
+                         xsltFunctionAvailableFunction);
+}
index c054561..6b9623d 100644 (file)
-/*\r
- * keys.c: Implemetation of the keys support\r
- *\r
- * Reference:\r
- *   http://www.w3.org/TR/1999/REC-xslt-19991116\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * daniel@veillard.com\r
- */\r
-\r
-#define IN_LIBXSLT\r
-#include "libxslt.h"\r
-\r
-#include <string.h>\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/tree.h>\r
-#include <libxml/valid.h>\r
-#include <libxml/hash.h>\r
-#include <libxml/xmlerror.h>\r
-#include <libxml/parserInternals.h>\r
-#include <libxml/xpathInternals.h>\r
-#include "xslt.h"\r
-#include "xsltInternals.h"\r
-#include "xsltutils.h"\r
-#include "imports.h"\r
-#include "templates.h"\r
-#include "keys.h"\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
-#define WITH_XSLT_DEBUG_KEYS\r
-#endif\r
-\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Type functions                                  *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltNewKeyDef:\r
- * @name:  the key name or NULL\r
- * @nameURI:  the name URI or NULL\r
- *\r
- * Create a new XSLT KeyDef\r
- *\r
- * Returns the newly allocated xsltKeyDefPtr or NULL in case of error\r
- */\r
-static xsltKeyDefPtr\r
-xsltNewKeyDef(const xmlChar *name, const xmlChar *nameURI) {\r
-    xsltKeyDefPtr cur;\r
-\r
-    cur = (xsltKeyDefPtr) xmlMalloc(sizeof(xsltKeyDef));\r
-    if (cur == NULL) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-               "xsltNewKeyDef : malloc failed\n");\r
-       return(NULL);\r
-    }\r
-    memset(cur, 0, sizeof(xsltKeyDef));\r
-    if (name != NULL)\r
-       cur->name = xmlStrdup(name);\r
-    if (nameURI != NULL)\r
-       cur->nameURI = xmlStrdup(nameURI);\r
-    cur->nsList = NULL;\r
-    return(cur);\r
-}\r
-\r
-/**\r
- * xsltFreeKeyDef:\r
- * @keyd:  an XSLT key definition\r
- *\r
- * Free up the memory allocated by @keyd\r
- */\r
-static void\r
-xsltFreeKeyDef(xsltKeyDefPtr keyd) {\r
-    if (keyd == NULL)\r
-       return;\r
-    if (keyd->comp != NULL)\r
-       xmlXPathFreeCompExpr(keyd->comp);\r
-    if (keyd->usecomp != NULL)\r
-       xmlXPathFreeCompExpr(keyd->usecomp);\r
-    if (keyd->name != NULL)\r
-       xmlFree(keyd->name);\r
-    if (keyd->nameURI != NULL)\r
-       xmlFree(keyd->nameURI);\r
-    if (keyd->match != NULL)\r
-       xmlFree(keyd->match);\r
-    if (keyd->use != NULL)\r
-       xmlFree(keyd->use);\r
-    if (keyd->nsList != NULL)\r
-        xmlFree(keyd->nsList);\r
-    memset(keyd, -1, sizeof(xsltKeyDef));\r
-    xmlFree(keyd);\r
-}\r
-\r
-/**\r
- * xsltFreeKeyDefList:\r
- * @keyd:  an XSLT key definition list\r
- *\r
- * Free up the memory allocated by all the elements of @keyd\r
- */\r
-static void\r
-xsltFreeKeyDefList(xsltKeyDefPtr keyd) {\r
-    xsltKeyDefPtr cur;\r
-\r
-    while (keyd != NULL) {\r
-       cur = keyd;\r
-       keyd = keyd->next;\r
-       xsltFreeKeyDef(cur);\r
-    }\r
-}\r
-\r
-/**\r
- * xsltNewKeyTable:\r
- * @name:  the key name or NULL\r
- * @nameURI:  the name URI or NULL\r
- *\r
- * Create a new XSLT KeyTable\r
- *\r
- * Returns the newly allocated xsltKeyTablePtr or NULL in case of error\r
- */\r
-static xsltKeyTablePtr\r
-xsltNewKeyTable(const xmlChar *name, const xmlChar *nameURI) {\r
-    xsltKeyTablePtr cur;\r
-\r
-    cur = (xsltKeyTablePtr) xmlMalloc(sizeof(xsltKeyTable));\r
-    if (cur == NULL) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-               "xsltNewKeyTable : malloc failed\n");\r
-       return(NULL);\r
-    }\r
-    memset(cur, 0, sizeof(xsltKeyTable));\r
-    if (name != NULL)\r
-       cur->name = xmlStrdup(name);\r
-    if (nameURI != NULL)\r
-       cur->nameURI = xmlStrdup(nameURI);\r
-    cur->keys = xmlHashCreate(0);\r
-    return(cur);\r
-}\r
-\r
-/**\r
- * xsltFreeKeyTable:\r
- * @keyt:  an XSLT key table\r
- *\r
- * Free up the memory allocated by @keyt\r
- */\r
-static void\r
-xsltFreeKeyTable(xsltKeyTablePtr keyt) {\r
-    if (keyt == NULL)\r
-       return;\r
-    if (keyt->name != NULL)\r
-       xmlFree(keyt->name);\r
-    if (keyt->nameURI != NULL)\r
-       xmlFree(keyt->nameURI);\r
-    if (keyt->keys != NULL)\r
-       xmlHashFree(keyt->keys, \r
-                   (xmlHashDeallocator) xmlXPathFreeNodeSet);\r
-    memset(keyt, -1, sizeof(xsltKeyTable));\r
-    xmlFree(keyt);\r
-}\r
-\r
-/**\r
- * xsltFreeKeyTableList:\r
- * @keyt:  an XSLT key table list\r
- *\r
- * Free up the memory allocated by all the elements of @keyt\r
- */\r
-static void\r
-xsltFreeKeyTableList(xsltKeyTablePtr keyt) {\r
-    xsltKeyTablePtr cur;\r
-\r
-    while (keyt != NULL) {\r
-       cur = keyt;\r
-       keyt = keyt->next;\r
-       xsltFreeKeyTable(cur);\r
-    }\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             The interpreter for the precompiled patterns            *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-\r
-/**\r
- * xsltFreeKeys:\r
- * @style: an XSLT stylesheet\r
- *\r
- * Free up the memory used by XSLT keys in a stylesheet\r
- */\r
-void\r
-xsltFreeKeys(xsltStylesheetPtr style) {\r
-    if (style->keys)\r
-       xsltFreeKeyDefList((xsltKeyDefPtr) style->keys);\r
-}\r
-\r
-/**\r
- * skipString:\r
- * @cur: the current pointer\r
- * @end: the current offset\r
- *\r
- * skip a string delimited by " or '\r
- *\r
- * Returns the byte after the string or -1 in case of error\r
- */\r
-static int\r
-skipString(const xmlChar *cur, int end) {\r
-    xmlChar limit;\r
-\r
-    if ((cur == NULL) || (end < 0)) return(-1);\r
-    if ((cur[end] == '\'') || (cur[end] == '"')) limit = cur[end];\r
-    else return(end);\r
-    end++;\r
-    while (cur[end] != 0) {\r
-        if (cur[end] == limit)\r
-           return(end + 1);\r
-       end++;\r
-    }\r
-    return(-1);\r
-}\r
-\r
-/**\r
- * skipPredicate:\r
- * @cur: the current pointer\r
- * @end: the current offset\r
- *\r
- * skip a predicate\r
- *\r
- * Returns the byte after the predicate or -1 in case of error\r
- */\r
-static int\r
-skipPredicate(const xmlChar *cur, int end) {\r
-    if ((cur == NULL) || (end < 0)) return(-1);\r
-    if (cur[end] != '[') return(end);\r
-    end++;\r
-    while (cur[end] != 0) {\r
-        if ((cur[end] == '\'') || (cur[end] == '"')) {\r
-           end = skipString(cur, end);\r
-           if (end <= 0)\r
-               return(-1);\r
-           continue;\r
-       } else if (cur[end] == '[') {\r
-           end = skipPredicate(cur, end);\r
-           if (end <= 0)\r
-               return(-1);\r
-           continue;\r
-       } else if (cur[end] == ']')\r
-           return(end + 1);\r
-       end++;\r
-    }\r
-    return(-1);\r
-}\r
-\r
-/**\r
- * xsltAddKey:\r
- * @style: an XSLT stylesheet\r
- * @name:  the key name or NULL\r
- * @nameURI:  the name URI or NULL\r
- * @match:  the match value\r
- * @use:  the use value\r
- * @inst: the key instruction\r
- *\r
- * add a key definition to a stylesheet\r
- *\r
- * Returns 0 in case of success, and -1 in case of failure.\r
- */\r
-int    \r
-xsltAddKey(xsltStylesheetPtr style, const xmlChar *name,\r
-          const xmlChar *nameURI, const xmlChar *match,\r
-          const xmlChar *use, xmlNodePtr inst) {\r
-    xsltKeyDefPtr key;\r
-    xmlChar *pattern = NULL;\r
-    int current, end, start, i = 0;\r
-\r
-    if ((style == NULL) || (name == NULL) || (match == NULL) || (use == NULL))\r
-       return(-1);\r
-\r
-#ifdef WITH_XSLT_DEBUG_KEYS\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "Add key %s, match %s, use %s\n", name, match, use);\r
-#endif\r
-\r
-    key = xsltNewKeyDef(name, nameURI);\r
-    key->match = xmlStrdup(match);\r
-    key->use = xmlStrdup(use);\r
-    key->inst = inst;\r
-    key->nsList = xmlGetNsList(inst->doc, inst);\r
-    if (key->nsList != NULL) {\r
-        while (key->nsList[i] != NULL)\r
-           i++;\r
-    }\r
-    key->nsNr = i;\r
-\r
-    /*\r
-     * Split the | and register it as as many keys\r
-     */\r
-    current = end = 0;\r
-    while (match[current] != 0) {\r
-       start = current;\r
-       while (IS_BLANK_CH(match[current]))\r
-           current++;\r
-       end = current;\r
-       while ((match[end] != 0) && (match[end] != '|')) {\r
-           if (match[end] == '[') {\r
-               end = skipPredicate(match, end);\r
-               if (end <= 0) {\r
-                   xsltTransformError(NULL, style, inst,\r
-                                      "key pattern is malformed: %s",\r
-                                      key->match);\r
-                   if (style != NULL) style->errors++;\r
-                   goto error;\r
-               }\r
-           } else\r
-               end++;\r
-       }\r
-       if (current == end) {\r
-           xsltTransformError(NULL, style, inst,\r
-                              "key pattern is empty\n");\r
-           if (style != NULL) style->errors++;\r
-           goto error;\r
-       }\r
-       if (match[start] != '/') {\r
-           pattern = xmlStrcat(pattern, (xmlChar *)"//");\r
-           if (pattern == NULL) {\r
-               if (style != NULL) style->errors++;\r
-               goto error;\r
-           }\r
-       }\r
-       pattern = xmlStrncat(pattern, &match[start], end - start);\r
-       if (pattern == NULL) {\r
-           if (style != NULL) style->errors++;\r
-           goto error;\r
-       }\r
-\r
-       if (match[end] == '|') {\r
-           pattern = xmlStrcat(pattern, (xmlChar *)"|");\r
-           end++;\r
-       }\r
-       current = end;\r
-    }\r
-#ifdef WITH_XSLT_DEBUG_KEYS\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "   resulting pattern %s\n", pattern);\r
-#endif\r
-    /*    \r
-    * XSLT-1: "It is an error for the value of either the use\r
-    *  attribute or the match attribute to contain a\r
-    *  VariableReference."\r
-    * TODO: We should report a variable-reference at compile-time.\r
-    *   Maybe a search for "$", if it occurs outside of quotation\r
-    *   marks, could be sufficient.\r
-    */\r
-    key->comp = xsltXPathCompile(style, pattern);\r
-    if (key->comp == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-               "xsl:key : XPath pattern compilation failed '%s'\n",\r
-                        pattern);\r
-       if (style != NULL) style->errors++;\r
-    }\r
-    key->usecomp = xsltXPathCompile(style, use);\r
-    if (key->usecomp == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-               "xsl:key : XPath pattern compilation failed '%s'\n",\r
-                        use);\r
-       if (style != NULL) style->errors++;\r
-    }\r
-    key->next = style->keys;\r
-    style->keys = key;\r
-error:\r
-    if (pattern != NULL)\r
-       xmlFree(pattern);\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltGetKey:\r
- * @ctxt: an XSLT transformation context\r
- * @name:  the key name or NULL\r
- * @nameURI:  the name URI or NULL\r
- * @value:  the key value to look for\r
- *\r
- * Looks up a key of the in current source doc (the document info\r
- * on @ctxt->document). Computes the key if not already done\r
- * for the current source doc.\r
- *\r
- * Returns the nodeset resulting from the query or NULL\r
- */\r
-xmlNodeSetPtr\r
-xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name,\r
-          const xmlChar *nameURI, const xmlChar *value) {\r
-    xmlNodeSetPtr ret;\r
-    xsltKeyTablePtr table;\r
-#ifdef XSLT_REFACTORED_KEYCOMP\r
-    int found = 0;\r
-#endif\r
-\r
-    if ((ctxt == NULL) || (name == NULL) || (value == NULL) ||\r
-       (ctxt->document == NULL))\r
-       return(NULL);\r
-\r
-#ifdef WITH_XSLT_DEBUG_KEYS\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "Get key %s, value %s\n", name, value);\r
-#endif\r
-\r
-    table = (xsltKeyTablePtr) ctxt->document->keys;\r
-    while (table != NULL) {\r
-       if (((nameURI != NULL) == (table->nameURI != NULL)) &&\r
-           xmlStrEqual(table->name, name) &&\r
-           xmlStrEqual(table->nameURI, nameURI))\r
-       {\r
-#ifdef XSLT_REFACTORED_KEYCOMP\r
-           found = 1;\r
-#endif\r
-           ret = (xmlNodeSetPtr)xmlHashLookup(table->keys, value);\r
-           return(ret);\r
-       }\r
-       table = table->next;\r
-    }\r
-#ifdef XSLT_REFACTORED_KEYCOMP\r
-    if (! found) {\r
-       xsltStylesheetPtr style = ctxt->style;  \r
-       xsltKeyDefPtr keyd;\r
-       /*\r
-       * This might be the first call to the key with the specified\r
-       * name and the specified document.\r
-       * Find all keys with a matching name and compute them for the\r
-       * current tree.\r
-       */\r
-       found = 0;\r
-       while (style != NULL) {\r
-           keyd = (xsltKeyDefPtr) style->keys;\r
-           while (keyd != NULL) {\r
-               if (((nameURI != NULL) == (keyd->nameURI != NULL)) &&\r
-                   xmlStrEqual(keyd->name, name) &&\r
-                   xmlStrEqual(keyd->nameURI, nameURI))\r
-               {\r
-                   found = 1;\r
-                   xsltInitCtxtKey(ctxt, ctxt->document, keyd);\r
-               }\r
-               keyd = keyd->next;              \r
-           }       \r
-           style = xsltNextImport(style);\r
-       }\r
-       if (found) {\r
-           /*\r
-           * The key was computed, so look it up.\r
-           */\r
-           table = (xsltKeyTablePtr) ctxt->document->keys;\r
-           while (table != NULL) {\r
-               if (((nameURI != NULL) == (table->nameURI != NULL)) &&\r
-                   xmlStrEqual(table->name, name) &&\r
-                   xmlStrEqual(table->nameURI, nameURI))\r
-               {\r
-                   ret = (xmlNodeSetPtr)xmlHashLookup(table->keys, value);\r
-                   return(ret);\r
-               }\r
-               table = table->next;\r
-           }\r
-\r
-       }\r
-    }\r
-#endif\r
-    return(NULL);\r
-}\r
-\r
-#if 0 /* Merged with xsltInitCtxtKey() */\r
-/**\r
- * xsltEvalXPathKeys:\r
- * @ctxt:  the XSLT transformation context\r
- * @comp:  the compiled XPath expression\r
- *\r
- * Process the expression using XPath to get the list of keys\r
- *\r
- * Returns the array of computed string value or NULL, must be deallocated\r
- *         by the caller.\r
- */\r
-static xmlChar **\r
-xsltEvalXPathKeys(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,\r
-                  xsltKeyDefPtr keyd) {\r
-    xmlChar **ret = NULL;\r
-    xmlXPathObjectPtr res;\r
-    xmlNodePtr oldInst;\r
-    xmlNodePtr oldNode;\r
-    int        oldPos, oldSize;\r
-    int oldNsNr;\r
-    xmlNsPtr *oldNamespaces;\r
-\r
-    oldInst = ctxt->inst;\r
-    oldNode = ctxt->node;\r
-    oldPos = ctxt->xpathCtxt->proximityPosition;\r
-    oldSize = ctxt->xpathCtxt->contextSize;\r
-    oldNsNr = ctxt->xpathCtxt->nsNr;\r
-    oldNamespaces = ctxt->xpathCtxt->namespaces;\r
-\r
-    ctxt->xpathCtxt->node = ctxt->node;\r
-    ctxt->xpathCtxt->namespaces = keyd->nsList;\r
-    ctxt->xpathCtxt->nsNr = keyd->nsNr;\r
-    res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);\r
-    if (res != NULL) {\r
-       if (res->type == XPATH_NODESET) {\r
-           int len, i, j;\r
-\r
-           if (res->nodesetval != NULL)\r
-               len = res->nodesetval->nodeNr;\r
-           else\r
-               len = 0;\r
-           if (len != 0) {\r
-               ret = (xmlChar **) xmlMalloc((len + 1) * sizeof(xmlChar *));\r
-               if (ret != NULL) {\r
-                   for (i = 0,j = 0;i < len;i++) {\r
-                       ret[j] = xmlXPathCastNodeToString(\r
-                               res->nodesetval->nodeTab[i]);\r
-                       if (ret[j] != NULL)\r
-                           j++;\r
-                   }\r
-                   ret[j] = NULL;\r
-               }\r
-           }\r
-       } else {\r
-           if (res->type != XPATH_STRING)\r
-               res = xmlXPathConvertString(res);\r
-           if (res->type == XPATH_STRING) {\r
-               ret = (xmlChar **) xmlMalloc(2 * sizeof(xmlChar *));\r
-               if (ret != NULL) {\r
-                   ret[0] = res->stringval;\r
-                   ret[1] = NULL;\r
-                   res->stringval = NULL;\r
-               }\r
-           } else {\r
-               xsltTransformError(ctxt, NULL, NULL,\r
-                    "xpath : string() function didn't return a String\n");\r
-           }\r
-       }\r
-       xmlXPathFreeObject(res);\r
-    } else {\r
-       ctxt->state = XSLT_STATE_STOPPED;\r
-    }\r
-#ifdef WITH_XSLT_DEBUG_TEMPLATES\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-        "xsltEvalXPathString: returns %s\n", ret);\r
-#endif\r
-    ctxt->inst = oldInst;\r
-    ctxt->node = oldNode;\r
-    ctxt->xpathCtxt->contextSize = oldSize;\r
-    ctxt->xpathCtxt->proximityPosition = oldPos;\r
-    ctxt->xpathCtxt->nsNr = oldNsNr;\r
-    ctxt->xpathCtxt->namespaces = oldNamespaces;\r
-    return(ret);\r
-}\r
-#endif\r
-\r
-/**\r
- * xsltInitCtxtKey:\r
- * @ctxt: an XSLT transformation context\r
- * @idoc:  the document information (holds key values)\r
- * @keyDef: the key definition\r
- *\r
- * Computes the key tables this key and for the current input document.\r
- */\r
-int\r
-xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc,\r
-               xsltKeyDefPtr keyDef)\r
-{\r
-    int i, len, k;    \r
-    xmlNodeSetPtr matchList = NULL, keylist;\r
-    xmlXPathObjectPtr matchRes = NULL, useRes = NULL;\r
-    xmlChar *str = NULL;\r
-    xsltKeyTablePtr table;\r
-    xmlNodePtr oldInst, cur;\r
-    xmlNodePtr oldContextNode;\r
-    xsltDocumentPtr oldDocInfo;\r
-    int        oldXPPos, oldXPSize;\r
-    xmlDocPtr oldXPDoc;\r
-    int oldXPNsNr;\r
-    xmlNsPtr *oldXPNamespaces;    \r
-    xmlXPathContextPtr xpctxt;\r
-\r
-    if ((keyDef->comp == NULL) || (keyDef->usecomp == NULL))\r
-       return(-1);\r
-\r
-    xpctxt = ctxt->xpathCtxt;\r
-    idoc->nbKeysComputed++;\r
-    /*\r
-    * Save context state.\r
-    */\r
-    oldInst = ctxt->inst;\r
-    oldDocInfo = ctxt->document;\r
-    oldContextNode = ctxt->node;\r
-\r
-    oldXPDoc = xpctxt->doc;\r
-    oldXPPos = xpctxt->proximityPosition;\r
-    oldXPSize = xpctxt->contextSize;\r
-    oldXPNsNr = xpctxt->nsNr;\r
-    oldXPNamespaces = xpctxt->namespaces;\r
-\r
-    /*\r
-    * Set up contexts.\r
-    */\r
-    ctxt->document = idoc;\r
-    ctxt->node = (xmlNodePtr) idoc->doc;\r
-    ctxt->inst = keyDef->inst;      \r
-\r
-    xpctxt->doc = idoc->doc;\r
-    xpctxt->node = (xmlNodePtr) idoc->doc;    \r
-    /* TODO : clarify the use of namespaces in keys evaluation */\r
-    xpctxt->namespaces = keyDef->nsList;\r
-    xpctxt->nsNr = keyDef->nsNr;\r
-\r
-    /*\r
-    * Evaluate the 'match' expression of the xsl:key.\r
-    * TODO: The 'match' is a *pattern*.\r
-    */\r
-    matchRes = xmlXPathCompiledEval(keyDef->comp, xpctxt);\r
-    if (matchRes == NULL) {\r
-\r
-#ifdef WITH_XSLT_DEBUG_KEYS\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltInitCtxtKey: %s evaluation failed\n", keyDef->match));\r
-#endif\r
-       xsltTransformError(ctxt, NULL, keyDef->inst,\r
-           "Failed to evaluate the 'match' expression.\n");\r
-       ctxt->state = XSLT_STATE_STOPPED;\r
-       goto error;\r
-    } else {\r
-       if (matchRes->type == XPATH_NODESET) {\r
-           matchList = matchRes->nodesetval;\r
-\r
-#ifdef WITH_XSLT_DEBUG_KEYS\r
-           if (matchList != NULL)\r
-               XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "xsltInitCtxtKey: %s evaluates to %d nodes\n",\r
-                                keyDef->match, matchList->nodeNr));\r
-#endif\r
-       } else {\r
-           /*\r
-           * Is not a node set, but must be.\r
-           */\r
-#ifdef WITH_XSLT_DEBUG_KEYS\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,\r
-                "xsltInitCtxtKey: %s is not a node set\n", keyDef->match));\r
-#endif\r
-           xsltTransformError(ctxt, NULL, keyDef->inst,\r
-               "The 'match' expression did not evaluate to a node set.\n");\r
-           ctxt->state = XSLT_STATE_STOPPED;\r
-           goto error;\r
-       }\r
-    }\r
-    if ((matchList == NULL) || (matchList->nodeNr <= 0))\r
-       goto exit;\r
-\r
-    /**\r
-     * Multiple key definitions for the same name are allowed, so\r
-     * we must check if the key is already present for this doc\r
-     */\r
-    table = (xsltKeyTablePtr) idoc->keys;\r
-    while (table != NULL) {\r
-        if (xmlStrEqual(table->name, keyDef->name) &&\r
-           (((keyDef->nameURI == NULL) && (table->nameURI == NULL)) ||\r
-            ((keyDef->nameURI != NULL) && (table->nameURI != NULL) &&\r
-             (xmlStrEqual(table->nameURI, keyDef->nameURI)))))\r
-           break;\r
-       table = table->next;\r
-    }\r
-    /**\r
-     * If the key was not previously defined, create it now and\r
-     * chain it to the list of keys for the doc\r
-     */\r
-    if (table == NULL) {\r
-        table = xsltNewKeyTable(keyDef->name, keyDef->nameURI);\r
-        if (table == NULL)\r
-           goto error;\r
-        table->next = idoc->keys;\r
-        idoc->keys = table;\r
-    }\r
-\r
-    /*\r
-    * SPEC XSLT 1.0 (XSLT 2.0 does not clarify the context size!)\r
-    * "...the use attribute of the xsl:key element is evaluated with x as\r
-    "  the current node and with a node list containing just x as the\r
-    *  current node list"\r
-    */\r
-    xpctxt->contextSize = 1;\r
-    xpctxt->proximityPosition = 1;\r
-    \r
-    for (i = 0; i < matchList->nodeNr; i++) {\r
-       cur = matchList->nodeTab[i];\r
-       if (! IS_XSLT_REAL_NODE(cur))\r
-           continue;\r
-       xpctxt->node = cur;\r
-       /*\r
-       * Process the 'use' of the xsl:key.\r
-       * SPEC XSLT 1.0:\r
-       * "The use attribute is an expression specifying the values of\r
-       *  the key; the expression is evaluated once for each node that\r
-       *  matches the pattern."\r
-       */\r
-       if (useRes != NULL)\r
-           xmlXPathFreeObject(useRes);\r
-       useRes = xmlXPathCompiledEval(keyDef->usecomp, xpctxt);\r
-       if (useRes == NULL) {\r
-           xsltTransformError(ctxt, NULL, keyDef->inst,\r
-               "Failed to evaluate the 'use' expression.\n");\r
-           ctxt->state = XSLT_STATE_STOPPED;\r
-           break;\r
-       }\r
-       if (useRes->type == XPATH_NODESET) {\r
-           if ((useRes->nodesetval != NULL) &&\r
-               (useRes->nodesetval->nodeNr != 0))\r
-           {\r
-               len = useRes->nodesetval->nodeNr;\r
-               str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[0]);\r
-           } else {\r
-               continue;\r
-           }\r
-       } else {\r
-           len = 1;\r
-           if (useRes->type == XPATH_STRING) {\r
-               /*\r
-               * Consume the string value.\r
-               */\r
-               str = useRes->stringval;\r
-               useRes->stringval = NULL;\r
-           } else {\r
-               str = xmlXPathCastToString(useRes);\r
-           }\r
-       }       \r
-       /*\r
-       * Process all strings.\r
-       */\r
-       k = 0;\r
-       while (1) {\r
-           if (str == NULL)\r
-               goto next_string;\r
-\r
-#ifdef WITH_XSLT_DEBUG_KEYS\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsl:key : node associated to ('%s', '%s')\n", keyDef->name, str));\r
-#endif\r
-           \r
-           keylist = xmlHashLookup(table->keys, str);\r
-           if (keylist == NULL) {\r
-               keylist = xmlXPathNodeSetCreate(cur);\r
-               if (keylist == NULL)\r
-                   goto error;\r
-               xmlHashAddEntry(table->keys, str, keylist);\r
-           } else {\r
-               /*\r
-               * TODO: How do we know if this function failed?\r
-               */\r
-               xmlXPathNodeSetAdd(keylist, cur);               \r
-           }\r
-           switch (cur->type) {\r
-               case XML_ELEMENT_NODE:\r
-               case XML_TEXT_NODE:\r
-               case XML_CDATA_SECTION_NODE:\r
-               case XML_PI_NODE:\r
-               case XML_COMMENT_NODE:\r
-                   cur->psvi = keyDef;\r
-                   break;\r
-               case XML_ATTRIBUTE_NODE:\r
-                   ((xmlAttrPtr) cur)->psvi = keyDef;\r
-                   break;\r
-               case XML_DOCUMENT_NODE:\r
-               case XML_HTML_DOCUMENT_NODE:\r
-                   ((xmlDocPtr) cur)->psvi = keyDef;\r
-                   break;\r
-               default:\r
-                   break;\r
-           }\r
-           xmlFree(str);\r
-           str = NULL;\r
-\r
-next_string:\r
-           k++;\r
-           if (k >= len)\r
-               break;\r
-           str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[k]);         \r
-       }\r
-    }\r
-\r
-exit:\r
-error:\r
-    /*\r
-    * Restore context state.\r
-    */\r
-    xpctxt->doc = oldXPDoc;\r
-    xpctxt->nsNr = oldXPNsNr;\r
-    xpctxt->namespaces = oldXPNamespaces;\r
-    xpctxt->proximityPosition = oldXPPos;\r
-    xpctxt->contextSize = oldXPSize;\r
-\r
-    ctxt->node = oldContextNode;\r
-    ctxt->document = oldDocInfo;\r
-    ctxt->inst = oldInst;\r
-\r
-    if (str)\r
-       xmlFree(str);\r
-    if (useRes != NULL)\r
-       xmlXPathFreeObject(useRes);\r
-    if (matchRes != NULL)\r
-       xmlXPathFreeObject(matchRes);\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltInitCtxtKeys:\r
- * @ctxt:  an XSLT transformation context\r
- * @idoc:  a document info\r
- *\r
- * Computes all the keys tables for the current input document.\r
- * Should be done before global varibales are initialized.\r
- * NOTE: Not used anymore in the refactored code.\r
- */\r
-void\r
-xsltInitCtxtKeys(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc) {\r
-    xsltStylesheetPtr style;\r
-    xsltKeyDefPtr keyDef;\r
-\r
-    if ((ctxt == NULL) || (idoc == NULL))\r
-       return;\r
-#ifdef WITH_XSLT_DEBUG_KEYS\r
-    if ((idoc->doc != NULL) && (idoc->doc->URL != NULL))\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext, "Initializing keys on %s\n",\r
-                    idoc->doc->URL));\r
-#endif\r
-    style = ctxt->style;\r
-    while (style != NULL) {\r
-       keyDef = (xsltKeyDefPtr) style->keys;\r
-       while (keyDef != NULL) {\r
-           xsltInitCtxtKey(ctxt, idoc, keyDef);\r
-\r
-           keyDef = keyDef->next;\r
-       }\r
-\r
-       style = xsltNextImport(style);\r
-    }\r
-}\r
-\r
-/**\r
- * xsltFreeDocumentKeys:\r
- * @doc: a XSLT document\r
- *\r
- * Free the keys associated to a document\r
- */\r
-void   \r
-xsltFreeDocumentKeys(xsltDocumentPtr idoc) {\r
-    if (idoc != NULL)\r
-        xsltFreeKeyTableList(idoc->keys);\r
-}\r
-\r
+/*
+ * keys.c: Implemetation of the keys support
+ *
+ * Reference:
+ *   http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/valid.h>
+#include <libxml/hash.h>
+#include <libxml/xmlerror.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xpathInternals.h>
+#include "xslt.h"
+#include "xsltInternals.h"
+#include "xsltutils.h"
+#include "imports.h"
+#include "templates.h"
+#include "keys.h"
+
+#ifdef WITH_XSLT_DEBUG
+#define WITH_XSLT_DEBUG_KEYS
+#endif
+
+
+/************************************************************************
+ *                                                                     *
+ *                     Type functions                                  *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltNewKeyDef:
+ * @name:  the key name or NULL
+ * @nameURI:  the name URI or NULL
+ *
+ * Create a new XSLT KeyDef
+ *
+ * Returns the newly allocated xsltKeyDefPtr or NULL in case of error
+ */
+static xsltKeyDefPtr
+xsltNewKeyDef(const xmlChar *name, const xmlChar *nameURI) {
+    xsltKeyDefPtr cur;
+
+    cur = (xsltKeyDefPtr) xmlMalloc(sizeof(xsltKeyDef));
+    if (cur == NULL) {
+       xsltTransformError(NULL, NULL, NULL,
+               "xsltNewKeyDef : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltKeyDef));
+    if (name != NULL)
+       cur->name = xmlStrdup(name);
+    if (nameURI != NULL)
+       cur->nameURI = xmlStrdup(nameURI);
+    cur->nsList = NULL;
+    return(cur);
+}
+
+/**
+ * xsltFreeKeyDef:
+ * @keyd:  an XSLT key definition
+ *
+ * Free up the memory allocated by @keyd
+ */
+static void
+xsltFreeKeyDef(xsltKeyDefPtr keyd) {
+    if (keyd == NULL)
+       return;
+    if (keyd->comp != NULL)
+       xmlXPathFreeCompExpr(keyd->comp);
+    if (keyd->usecomp != NULL)
+       xmlXPathFreeCompExpr(keyd->usecomp);
+    if (keyd->name != NULL)
+       xmlFree(keyd->name);
+    if (keyd->nameURI != NULL)
+       xmlFree(keyd->nameURI);
+    if (keyd->match != NULL)
+       xmlFree(keyd->match);
+    if (keyd->use != NULL)
+       xmlFree(keyd->use);
+    if (keyd->nsList != NULL)
+        xmlFree(keyd->nsList);
+    memset(keyd, -1, sizeof(xsltKeyDef));
+    xmlFree(keyd);
+}
+
+/**
+ * xsltFreeKeyDefList:
+ * @keyd:  an XSLT key definition list
+ *
+ * Free up the memory allocated by all the elements of @keyd
+ */
+static void
+xsltFreeKeyDefList(xsltKeyDefPtr keyd) {
+    xsltKeyDefPtr cur;
+
+    while (keyd != NULL) {
+       cur = keyd;
+       keyd = keyd->next;
+       xsltFreeKeyDef(cur);
+    }
+}
+
+/**
+ * xsltNewKeyTable:
+ * @name:  the key name or NULL
+ * @nameURI:  the name URI or NULL
+ *
+ * Create a new XSLT KeyTable
+ *
+ * Returns the newly allocated xsltKeyTablePtr or NULL in case of error
+ */
+static xsltKeyTablePtr
+xsltNewKeyTable(const xmlChar *name, const xmlChar *nameURI) {
+    xsltKeyTablePtr cur;
+
+    cur = (xsltKeyTablePtr) xmlMalloc(sizeof(xsltKeyTable));
+    if (cur == NULL) {
+       xsltTransformError(NULL, NULL, NULL,
+               "xsltNewKeyTable : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltKeyTable));
+    if (name != NULL)
+       cur->name = xmlStrdup(name);
+    if (nameURI != NULL)
+       cur->nameURI = xmlStrdup(nameURI);
+    cur->keys = xmlHashCreate(0);
+    return(cur);
+}
+
+/**
+ * xsltFreeKeyTable:
+ * @keyt:  an XSLT key table
+ *
+ * Free up the memory allocated by @keyt
+ */
+static void
+xsltFreeKeyTable(xsltKeyTablePtr keyt) {
+    if (keyt == NULL)
+       return;
+    if (keyt->name != NULL)
+       xmlFree(keyt->name);
+    if (keyt->nameURI != NULL)
+       xmlFree(keyt->nameURI);
+    if (keyt->keys != NULL)
+       xmlHashFree(keyt->keys, 
+                   (xmlHashDeallocator) xmlXPathFreeNodeSet);
+    memset(keyt, -1, sizeof(xsltKeyTable));
+    xmlFree(keyt);
+}
+
+/**
+ * xsltFreeKeyTableList:
+ * @keyt:  an XSLT key table list
+ *
+ * Free up the memory allocated by all the elements of @keyt
+ */
+static void
+xsltFreeKeyTableList(xsltKeyTablePtr keyt) {
+    xsltKeyTablePtr cur;
+
+    while (keyt != NULL) {
+       cur = keyt;
+       keyt = keyt->next;
+       xsltFreeKeyTable(cur);
+    }
+}
+
+/************************************************************************
+ *                                                                     *
+ *             The interpreter for the precompiled patterns            *
+ *                                                                     *
+ ************************************************************************/
+
+
+/**
+ * xsltFreeKeys:
+ * @style: an XSLT stylesheet
+ *
+ * Free up the memory used by XSLT keys in a stylesheet
+ */
+void
+xsltFreeKeys(xsltStylesheetPtr style) {
+    if (style->keys)
+       xsltFreeKeyDefList((xsltKeyDefPtr) style->keys);
+}
+
+/**
+ * skipString:
+ * @cur: the current pointer
+ * @end: the current offset
+ *
+ * skip a string delimited by " or '
+ *
+ * Returns the byte after the string or -1 in case of error
+ */
+static int
+skipString(const xmlChar *cur, int end) {
+    xmlChar limit;
+
+    if ((cur == NULL) || (end < 0)) return(-1);
+    if ((cur[end] == '\'') || (cur[end] == '"')) limit = cur[end];
+    else return(end);
+    end++;
+    while (cur[end] != 0) {
+        if (cur[end] == limit)
+           return(end + 1);
+       end++;
+    }
+    return(-1);
+}
+
+/**
+ * skipPredicate:
+ * @cur: the current pointer
+ * @end: the current offset
+ *
+ * skip a predicate
+ *
+ * Returns the byte after the predicate or -1 in case of error
+ */
+static int
+skipPredicate(const xmlChar *cur, int end) {
+    if ((cur == NULL) || (end < 0)) return(-1);
+    if (cur[end] != '[') return(end);
+    end++;
+    while (cur[end] != 0) {
+        if ((cur[end] == '\'') || (cur[end] == '"')) {
+           end = skipString(cur, end);
+           if (end <= 0)
+               return(-1);
+           continue;
+       } else if (cur[end] == '[') {
+           end = skipPredicate(cur, end);
+           if (end <= 0)
+               return(-1);
+           continue;
+       } else if (cur[end] == ']')
+           return(end + 1);
+       end++;
+    }
+    return(-1);
+}
+
+/**
+ * xsltAddKey:
+ * @style: an XSLT stylesheet
+ * @name:  the key name or NULL
+ * @nameURI:  the name URI or NULL
+ * @match:  the match value
+ * @use:  the use value
+ * @inst: the key instruction
+ *
+ * add a key definition to a stylesheet
+ *
+ * Returns 0 in case of success, and -1 in case of failure.
+ */
+int    
+xsltAddKey(xsltStylesheetPtr style, const xmlChar *name,
+          const xmlChar *nameURI, const xmlChar *match,
+          const xmlChar *use, xmlNodePtr inst) {
+    xsltKeyDefPtr key;
+    xmlChar *pattern = NULL;
+    int current, end, start, i = 0;
+
+    if ((style == NULL) || (name == NULL) || (match == NULL) || (use == NULL))
+       return(-1);
+
+#ifdef WITH_XSLT_DEBUG_KEYS
+    xsltGenericDebug(xsltGenericDebugContext,
+       "Add key %s, match %s, use %s\n", name, match, use);
+#endif
+
+    key = xsltNewKeyDef(name, nameURI);
+    key->match = xmlStrdup(match);
+    key->use = xmlStrdup(use);
+    key->inst = inst;
+    key->nsList = xmlGetNsList(inst->doc, inst);
+    if (key->nsList != NULL) {
+        while (key->nsList[i] != NULL)
+           i++;
+    }
+    key->nsNr = i;
+
+    /*
+     * Split the | and register it as as many keys
+     */
+    current = end = 0;
+    while (match[current] != 0) {
+       start = current;
+       while (IS_BLANK_CH(match[current]))
+           current++;
+       end = current;
+       while ((match[end] != 0) && (match[end] != '|')) {
+           if (match[end] == '[') {
+               end = skipPredicate(match, end);
+               if (end <= 0) {
+                   xsltTransformError(NULL, style, inst,
+                                      "key pattern is malformed: %s",
+                                      key->match);
+                   if (style != NULL) style->errors++;
+                   goto error;
+               }
+           } else
+               end++;
+       }
+       if (current == end) {
+           xsltTransformError(NULL, style, inst,
+                              "key pattern is empty\n");
+           if (style != NULL) style->errors++;
+           goto error;
+       }
+       if (match[start] != '/') {
+           pattern = xmlStrcat(pattern, (xmlChar *)"//");
+           if (pattern == NULL) {
+               if (style != NULL) style->errors++;
+               goto error;
+           }
+       }
+       pattern = xmlStrncat(pattern, &match[start], end - start);
+       if (pattern == NULL) {
+           if (style != NULL) style->errors++;
+           goto error;
+       }
+
+       if (match[end] == '|') {
+           pattern = xmlStrcat(pattern, (xmlChar *)"|");
+           end++;
+       }
+       current = end;
+    }
+#ifdef WITH_XSLT_DEBUG_KEYS
+    xsltGenericDebug(xsltGenericDebugContext,
+       "   resulting pattern %s\n", pattern);
+#endif
+    /*    
+    * XSLT-1: "It is an error for the value of either the use
+    *  attribute or the match attribute to contain a
+    *  VariableReference."
+    * TODO: We should report a variable-reference at compile-time.
+    *   Maybe a search for "$", if it occurs outside of quotation
+    *   marks, could be sufficient.
+    */
+    key->comp = xsltXPathCompile(style, pattern);
+    if (key->comp == NULL) {
+       xsltTransformError(NULL, style, inst,
+               "xsl:key : XPath pattern compilation failed '%s'\n",
+                        pattern);
+       if (style != NULL) style->errors++;
+    }
+    key->usecomp = xsltXPathCompile(style, use);
+    if (key->usecomp == NULL) {
+       xsltTransformError(NULL, style, inst,
+               "xsl:key : XPath pattern compilation failed '%s'\n",
+                        use);
+       if (style != NULL) style->errors++;
+    }
+    key->next = style->keys;
+    style->keys = key;
+error:
+    if (pattern != NULL)
+       xmlFree(pattern);
+    return(0);
+}
+
+/**
+ * xsltGetKey:
+ * @ctxt: an XSLT transformation context
+ * @name:  the key name or NULL
+ * @nameURI:  the name URI or NULL
+ * @value:  the key value to look for
+ *
+ * Looks up a key of the in current source doc (the document info
+ * on @ctxt->document). Computes the key if not already done
+ * for the current source doc.
+ *
+ * Returns the nodeset resulting from the query or NULL
+ */
+xmlNodeSetPtr
+xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name,
+          const xmlChar *nameURI, const xmlChar *value) {
+    xmlNodeSetPtr ret;
+    xsltKeyTablePtr table;
+#ifdef XSLT_REFACTORED_KEYCOMP
+    int found = 0;
+#endif
+
+    if ((ctxt == NULL) || (name == NULL) || (value == NULL) ||
+       (ctxt->document == NULL))
+       return(NULL);
+
+#ifdef WITH_XSLT_DEBUG_KEYS
+    xsltGenericDebug(xsltGenericDebugContext,
+       "Get key %s, value %s\n", name, value);
+#endif
+
+    table = (xsltKeyTablePtr) ctxt->document->keys;
+    while (table != NULL) {
+       if (((nameURI != NULL) == (table->nameURI != NULL)) &&
+           xmlStrEqual(table->name, name) &&
+           xmlStrEqual(table->nameURI, nameURI))
+       {
+#ifdef XSLT_REFACTORED_KEYCOMP
+           found = 1;
+#endif
+           ret = (xmlNodeSetPtr)xmlHashLookup(table->keys, value);
+           return(ret);
+       }
+       table = table->next;
+    }
+#ifdef XSLT_REFACTORED_KEYCOMP
+    if (! found) {
+       xsltStylesheetPtr style = ctxt->style;  
+       xsltKeyDefPtr keyd;
+       /*
+       * This might be the first call to the key with the specified
+       * name and the specified document.
+       * Find all keys with a matching name and compute them for the
+       * current tree.
+       */
+       found = 0;
+       while (style != NULL) {
+           keyd = (xsltKeyDefPtr) style->keys;
+           while (keyd != NULL) {
+               if (((nameURI != NULL) == (keyd->nameURI != NULL)) &&
+                   xmlStrEqual(keyd->name, name) &&
+                   xmlStrEqual(keyd->nameURI, nameURI))
+               {
+                   found = 1;
+                   xsltInitCtxtKey(ctxt, ctxt->document, keyd);
+               }
+               keyd = keyd->next;              
+           }       
+           style = xsltNextImport(style);
+       }
+       if (found) {
+           /*
+           * The key was computed, so look it up.
+           */
+           table = (xsltKeyTablePtr) ctxt->document->keys;
+           while (table != NULL) {
+               if (((nameURI != NULL) == (table->nameURI != NULL)) &&
+                   xmlStrEqual(table->name, name) &&
+                   xmlStrEqual(table->nameURI, nameURI))
+               {
+                   ret = (xmlNodeSetPtr)xmlHashLookup(table->keys, value);
+                   return(ret);
+               }
+               table = table->next;
+           }
+
+       }
+    }
+#endif
+    return(NULL);
+}
+
+#if 0 /* Merged with xsltInitCtxtKey() */
+/**
+ * xsltEvalXPathKeys:
+ * @ctxt:  the XSLT transformation context
+ * @comp:  the compiled XPath expression
+ *
+ * Process the expression using XPath to get the list of keys
+ *
+ * Returns the array of computed string value or NULL, must be deallocated
+ *         by the caller.
+ */
+static xmlChar **
+xsltEvalXPathKeys(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
+                  xsltKeyDefPtr keyd) {
+    xmlChar **ret = NULL;
+    xmlXPathObjectPtr res;
+    xmlNodePtr oldInst;
+    xmlNodePtr oldNode;
+    int        oldPos, oldSize;
+    int oldNsNr;
+    xmlNsPtr *oldNamespaces;
+
+    oldInst = ctxt->inst;
+    oldNode = ctxt->node;
+    oldPos = ctxt->xpathCtxt->proximityPosition;
+    oldSize = ctxt->xpathCtxt->contextSize;
+    oldNsNr = ctxt->xpathCtxt->nsNr;
+    oldNamespaces = ctxt->xpathCtxt->namespaces;
+
+    ctxt->xpathCtxt->node = ctxt->node;
+    ctxt->xpathCtxt->namespaces = keyd->nsList;
+    ctxt->xpathCtxt->nsNr = keyd->nsNr;
+    res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
+    if (res != NULL) {
+       if (res->type == XPATH_NODESET) {
+           int len, i, j;
+
+           if (res->nodesetval != NULL)
+               len = res->nodesetval->nodeNr;
+           else
+               len = 0;
+           if (len != 0) {
+               ret = (xmlChar **) xmlMalloc((len + 1) * sizeof(xmlChar *));
+               if (ret != NULL) {
+                   for (i = 0,j = 0;i < len;i++) {
+                       ret[j] = xmlXPathCastNodeToString(
+                               res->nodesetval->nodeTab[i]);
+                       if (ret[j] != NULL)
+                           j++;
+                   }
+                   ret[j] = NULL;
+               }
+           }
+       } else {
+           if (res->type != XPATH_STRING)
+               res = xmlXPathConvertString(res);
+           if (res->type == XPATH_STRING) {
+               ret = (xmlChar **) xmlMalloc(2 * sizeof(xmlChar *));
+               if (ret != NULL) {
+                   ret[0] = res->stringval;
+                   ret[1] = NULL;
+                   res->stringval = NULL;
+               }
+           } else {
+               xsltTransformError(ctxt, NULL, NULL,
+                    "xpath : string() function didn't return a String\n");
+           }
+       }
+       xmlXPathFreeObject(res);
+    } else {
+       ctxt->state = XSLT_STATE_STOPPED;
+    }
+#ifdef WITH_XSLT_DEBUG_TEMPLATES
+    xsltGenericDebug(xsltGenericDebugContext,
+        "xsltEvalXPathString: returns %s\n", ret);
+#endif
+    ctxt->inst = oldInst;
+    ctxt->node = oldNode;
+    ctxt->xpathCtxt->contextSize = oldSize;
+    ctxt->xpathCtxt->proximityPosition = oldPos;
+    ctxt->xpathCtxt->nsNr = oldNsNr;
+    ctxt->xpathCtxt->namespaces = oldNamespaces;
+    return(ret);
+}
+#endif
+
+/**
+ * xsltInitCtxtKey:
+ * @ctxt: an XSLT transformation context
+ * @idoc:  the document information (holds key values)
+ * @keyDef: the key definition
+ *
+ * Computes the key tables this key and for the current input document.
+ */
+int
+xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc,
+               xsltKeyDefPtr keyDef)
+{
+    int i, len, k;    
+    xmlNodeSetPtr matchList = NULL, keylist;
+    xmlXPathObjectPtr matchRes = NULL, useRes = NULL;
+    xmlChar *str = NULL;
+    xsltKeyTablePtr table;
+    xmlNodePtr oldInst, cur;
+    xmlNodePtr oldContextNode;
+    xsltDocumentPtr oldDocInfo;
+    int        oldXPPos, oldXPSize;
+    xmlDocPtr oldXPDoc;
+    int oldXPNsNr;
+    xmlNsPtr *oldXPNamespaces;    
+    xmlXPathContextPtr xpctxt;
+
+    if ((keyDef->comp == NULL) || (keyDef->usecomp == NULL))
+       return(-1);
+
+    xpctxt = ctxt->xpathCtxt;
+    idoc->nbKeysComputed++;
+    /*
+    * Save context state.
+    */
+    oldInst = ctxt->inst;
+    oldDocInfo = ctxt->document;
+    oldContextNode = ctxt->node;
+
+    oldXPDoc = xpctxt->doc;
+    oldXPPos = xpctxt->proximityPosition;
+    oldXPSize = xpctxt->contextSize;
+    oldXPNsNr = xpctxt->nsNr;
+    oldXPNamespaces = xpctxt->namespaces;
+
+    /*
+    * Set up contexts.
+    */
+    ctxt->document = idoc;
+    ctxt->node = (xmlNodePtr) idoc->doc;
+    ctxt->inst = keyDef->inst;      
+
+    xpctxt->doc = idoc->doc;
+    xpctxt->node = (xmlNodePtr) idoc->doc;    
+    /* TODO : clarify the use of namespaces in keys evaluation */
+    xpctxt->namespaces = keyDef->nsList;
+    xpctxt->nsNr = keyDef->nsNr;
+
+    /*
+    * Evaluate the 'match' expression of the xsl:key.
+    * TODO: The 'match' is a *pattern*.
+    */
+    matchRes = xmlXPathCompiledEval(keyDef->comp, xpctxt);
+    if (matchRes == NULL) {
+
+#ifdef WITH_XSLT_DEBUG_KEYS
+       XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltInitCtxtKey: %s evaluation failed\n", keyDef->match));
+#endif
+       xsltTransformError(ctxt, NULL, keyDef->inst,
+           "Failed to evaluate the 'match' expression.\n");
+       ctxt->state = XSLT_STATE_STOPPED;
+       goto error;
+    } else {
+       if (matchRes->type == XPATH_NODESET) {
+           matchList = matchRes->nodesetval;
+
+#ifdef WITH_XSLT_DEBUG_KEYS
+           if (matchList != NULL)
+               XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
+                    "xsltInitCtxtKey: %s evaluates to %d nodes\n",
+                                keyDef->match, matchList->nodeNr));
+#endif
+       } else {
+           /*
+           * Is not a node set, but must be.
+           */
+#ifdef WITH_XSLT_DEBUG_KEYS
+           XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
+                "xsltInitCtxtKey: %s is not a node set\n", keyDef->match));
+#endif
+           xsltTransformError(ctxt, NULL, keyDef->inst,
+               "The 'match' expression did not evaluate to a node set.\n");
+           ctxt->state = XSLT_STATE_STOPPED;
+           goto error;
+       }
+    }
+    if ((matchList == NULL) || (matchList->nodeNr <= 0))
+       goto exit;
+
+    /**
+     * Multiple key definitions for the same name are allowed, so
+     * we must check if the key is already present for this doc
+     */
+    table = (xsltKeyTablePtr) idoc->keys;
+    while (table != NULL) {
+        if (xmlStrEqual(table->name, keyDef->name) &&
+           (((keyDef->nameURI == NULL) && (table->nameURI == NULL)) ||
+            ((keyDef->nameURI != NULL) && (table->nameURI != NULL) &&
+             (xmlStrEqual(table->nameURI, keyDef->nameURI)))))
+           break;
+       table = table->next;
+    }
+    /**
+     * If the key was not previously defined, create it now and
+     * chain it to the list of keys for the doc
+     */
+    if (table == NULL) {
+        table = xsltNewKeyTable(keyDef->name, keyDef->nameURI);
+        if (table == NULL)
+           goto error;
+        table->next = idoc->keys;
+        idoc->keys = table;
+    }
+
+    /*
+    * SPEC XSLT 1.0 (XSLT 2.0 does not clarify the context size!)
+    * "...the use attribute of the xsl:key element is evaluated with x as
+    "  the current node and with a node list containing just x as the
+    *  current node list"
+    */
+    xpctxt->contextSize = 1;
+    xpctxt->proximityPosition = 1;
+    
+    for (i = 0; i < matchList->nodeNr; i++) {
+       cur = matchList->nodeTab[i];
+       if (! IS_XSLT_REAL_NODE(cur))
+           continue;
+       xpctxt->node = cur;
+       /*
+       * Process the 'use' of the xsl:key.
+       * SPEC XSLT 1.0:
+       * "The use attribute is an expression specifying the values of
+       *  the key; the expression is evaluated once for each node that
+       *  matches the pattern."
+       */
+       if (useRes != NULL)
+           xmlXPathFreeObject(useRes);
+       useRes = xmlXPathCompiledEval(keyDef->usecomp, xpctxt);
+       if (useRes == NULL) {
+           xsltTransformError(ctxt, NULL, keyDef->inst,
+               "Failed to evaluate the 'use' expression.\n");
+           ctxt->state = XSLT_STATE_STOPPED;
+           break;
+       }
+       if (useRes->type == XPATH_NODESET) {
+           if ((useRes->nodesetval != NULL) &&
+               (useRes->nodesetval->nodeNr != 0))
+           {
+               len = useRes->nodesetval->nodeNr;
+               str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[0]);
+           } else {
+               continue;
+           }
+       } else {
+           len = 1;
+           if (useRes->type == XPATH_STRING) {
+               /*
+               * Consume the string value.
+               */
+               str = useRes->stringval;
+               useRes->stringval = NULL;
+           } else {
+               str = xmlXPathCastToString(useRes);
+           }
+       }       
+       /*
+       * Process all strings.
+       */
+       k = 0;
+       while (1) {
+           if (str == NULL)
+               goto next_string;
+
+#ifdef WITH_XSLT_DEBUG_KEYS
+           XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
+               "xsl:key : node associated to ('%s', '%s')\n", keyDef->name, str));
+#endif
+           
+           keylist = xmlHashLookup(table->keys, str);
+           if (keylist == NULL) {
+               keylist = xmlXPathNodeSetCreate(cur);
+               if (keylist == NULL)
+                   goto error;
+               xmlHashAddEntry(table->keys, str, keylist);
+           } else {
+               /*
+               * TODO: How do we know if this function failed?
+               */
+               xmlXPathNodeSetAdd(keylist, cur);               
+           }
+           switch (cur->type) {
+               case XML_ELEMENT_NODE:
+               case XML_TEXT_NODE:
+               case XML_CDATA_SECTION_NODE:
+               case XML_PI_NODE:
+               case XML_COMMENT_NODE:
+                   cur->psvi = keyDef;
+                   break;
+               case XML_ATTRIBUTE_NODE:
+                   ((xmlAttrPtr) cur)->psvi = keyDef;
+                   break;
+               case XML_DOCUMENT_NODE:
+               case XML_HTML_DOCUMENT_NODE:
+                   ((xmlDocPtr) cur)->psvi = keyDef;
+                   break;
+               default:
+                   break;
+           }
+           xmlFree(str);
+           str = NULL;
+
+next_string:
+           k++;
+           if (k >= len)
+               break;
+           str = xmlXPathCastNodeToString(useRes->nodesetval->nodeTab[k]);         
+       }
+    }
+
+exit:
+error:
+    /*
+    * Restore context state.
+    */
+    xpctxt->doc = oldXPDoc;
+    xpctxt->nsNr = oldXPNsNr;
+    xpctxt->namespaces = oldXPNamespaces;
+    xpctxt->proximityPosition = oldXPPos;
+    xpctxt->contextSize = oldXPSize;
+
+    ctxt->node = oldContextNode;
+    ctxt->document = oldDocInfo;
+    ctxt->inst = oldInst;
+
+    if (str)
+       xmlFree(str);
+    if (useRes != NULL)
+       xmlXPathFreeObject(useRes);
+    if (matchRes != NULL)
+       xmlXPathFreeObject(matchRes);
+    return(0);
+}
+
+/**
+ * xsltInitCtxtKeys:
+ * @ctxt:  an XSLT transformation context
+ * @idoc:  a document info
+ *
+ * Computes all the keys tables for the current input document.
+ * Should be done before global varibales are initialized.
+ * NOTE: Not used anymore in the refactored code.
+ */
+void
+xsltInitCtxtKeys(xsltTransformContextPtr ctxt, xsltDocumentPtr idoc) {
+    xsltStylesheetPtr style;
+    xsltKeyDefPtr keyDef;
+
+    if ((ctxt == NULL) || (idoc == NULL))
+       return;
+#ifdef WITH_XSLT_DEBUG_KEYS
+    if ((idoc->doc != NULL) && (idoc->doc->URL != NULL))
+       XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext, "Initializing keys on %s\n",
+                    idoc->doc->URL));
+#endif
+    style = ctxt->style;
+    while (style != NULL) {
+       keyDef = (xsltKeyDefPtr) style->keys;
+       while (keyDef != NULL) {
+           xsltInitCtxtKey(ctxt, idoc, keyDef);
+
+           keyDef = keyDef->next;
+       }
+
+       style = xsltNextImport(style);
+    }
+}
+
+/**
+ * xsltFreeDocumentKeys:
+ * @doc: a XSLT document
+ *
+ * Free the keys associated to a document
+ */
+void   
+xsltFreeDocumentKeys(xsltDocumentPtr idoc) {
+    if (idoc != NULL)
+        xsltFreeKeyTableList(idoc->keys);
+}
+
index 5202630..e27e0e5 100644 (file)
-/*\r
- * namespaces.c: Implementation of the XSLT namespaces handling\r
- *\r
- * Reference:\r
- *   http://www.w3.org/TR/1999/REC-xslt-19991116\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * daniel@veillard.com\r
- */\r
-\r
-#define IN_LIBXSLT\r
-#include "libxslt.h"\r
-\r
-#include <string.h>\r
-\r
-#ifdef HAVE_SYS_TYPES_H\r
-#include <sys/types.h>\r
-#endif\r
-#ifdef HAVE_MATH_H\r
-#include <math.h>\r
-#endif\r
-#ifdef HAVE_FLOAT_H\r
-#include <float.h>\r
-#endif\r
-#ifdef HAVE_IEEEFP_H\r
-#include <ieeefp.h>\r
-#endif\r
-#ifdef HAVE_NAN_H\r
-#include <nan.h>\r
-#endif\r
-#ifdef HAVE_CTYPE_H\r
-#include <ctype.h>\r
-#endif\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/tree.h>\r
-#include <libxml/hash.h>\r
-#include <libxml/xmlerror.h>\r
-#include <libxml/uri.h>\r
-#include "xslt.h"\r
-#include "xsltInternals.h"\r
-#include "xsltutils.h"\r
-#include "namespaces.h"\r
-#include "imports.h"\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Module interfaces                               *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-#ifdef XSLT_REFACTORED  \r
-static xsltNsAliasPtr\r
-xsltNewNsAlias(xsltCompilerCtxtPtr cctxt)\r
-{\r
-    xsltNsAliasPtr ret;\r
-\r
-    if (cctxt == NULL)\r
-       return(NULL);\r
-\r
-    ret = (xsltNsAliasPtr) xmlMalloc(sizeof(xsltNsAlias));\r
-    if (ret == NULL) {\r
-       xsltTransformError(NULL, cctxt->style, NULL,\r
-           "Internal error in xsltNewNsAlias(): Memory allocation failed.\n");\r
-       cctxt->style->errors++;\r
-       return(NULL);\r
-    }\r
-    memset(ret, 0, sizeof(xsltNsAlias));    \r
-    /*\r
-    * TODO: Store the item at current stylesheet-level.\r
-    */\r
-    ret->next = cctxt->nsAliases;\r
-    cctxt->nsAliases = ret;       \r
-\r
-    return(ret);\r
-}\r
-#endif /* XSLT_REFACTORED */\r
-/**\r
- * xsltNamespaceAlias:\r
- * @style:  the XSLT stylesheet\r
- * @node:  the xsl:namespace-alias node\r
- *\r
- * Read the stylesheet-prefix and result-prefix attributes, register\r
- * them as well as the corresponding namespace.\r
- */\r
-void\r
-xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node)\r
-{\r
-    xmlChar *resultPrefix = NULL;\r
-    xmlChar *stylePrefix = NULL;\r
-    xmlNsPtr literalNs = NULL;\r
-    xmlNsPtr targetNs = NULL;\r
\r
-#ifdef XSLT_REFACTORED \r
-    xsltNsAliasPtr alias;\r
-\r
-    if ((style == NULL) || (node == NULL))\r
-       return;\r
-\r
-    /*\r
-    * SPEC XSLT 1.0:\r
-    *  "If a namespace URI is declared to be an alias for multiple\r
-    *  different namespace URIs, then the declaration with the highest\r
-    *  import precedence is used. It is an error if there is more than\r
-    *  one such declaration. An XSLT processor may signal the error;\r
-    *  if it does not signal the error, it must recover by choosing,\r
-    *  from amongst the declarations with the highest import precedence,\r
-    *  the one that occurs last in the stylesheet."\r
-    *\r
-    * SPEC TODO: Check for the errors mentioned above.\r
-    */\r
-    /*\r
-    * NOTE that the XSLT 2.0 also *does* use the NULL namespace if\r
-    *  "#default" is used and there's no default namespace is scope.\r
-    *  I.e., this is *not* an error. \r
-    *  Most XSLT 1.0 implementations work this way.\r
-    *  The XSLT 1.0 spec has nothing to say on the subject. \r
-    */\r
-    /*\r
-    * Attribute "stylesheet-prefix".\r
-    */\r
-    stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL);\r
-    if (stylePrefix == NULL) {\r
-       xsltTransformError(NULL, style, node,\r
-           "The attribute 'stylesheet-prefix' is missing.\n");\r
-       return;\r
-    }\r
-    if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default"))\r
-       literalNs = xmlSearchNs(node->doc, node, NULL); \r
-    else {\r
-       literalNs = xmlSearchNs(node->doc, node, stylePrefix);\r
-       if (literalNs == NULL) {\r
-           xsltTransformError(NULL, style, node,\r
-               "Attribute 'stylesheet-prefix': There's no namespace "\r
-               "declaration in scope for the prefix '%s'.\n",\r
-                   stylePrefix);\r
-           goto error;\r
-       }\r
-    }\r
-    /*\r
-    * Attribute "result-prefix".\r
-    */\r
-    resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL);\r
-    if (resultPrefix == NULL) {\r
-       xsltTransformError(NULL, style, node,\r
-           "The attribute 'result-prefix' is missing.\n");\r
-       goto error;\r
-    }        \r
-    if (xmlStrEqual(resultPrefix, (const xmlChar *)"#default"))\r
-       targetNs = xmlSearchNs(node->doc, node, NULL);\r
-    else {\r
-       targetNs = xmlSearchNs(node->doc, node, resultPrefix);\r
-\r
-        if (targetNs == NULL) {\r
-          xsltTransformError(NULL, style, node,\r
-               "Attribute 'result-prefix': There's no namespace "\r
-               "declaration in scope for the prefix '%s'.\n",\r
-                   stylePrefix);\r
-           goto error;\r
-       }\r
-    }\r
-    /*\r
-     *\r
-     * Same alias for multiple different target namespace URIs:\r
-     *  TODO: The one with the highest import precedence is used.\r
-     *  Example:\r
-     *  <xsl:namespace-alias stylesheet-prefix="foo"\r
-     *                       result-prefix="bar"/>\r
-     *\r
-     *  <xsl:namespace-alias stylesheet-prefix="foo"\r
-     *                       result-prefix="zar"/>\r
-     *\r
-     * Same target namespace URI for multiple different aliases:\r
-     *  All alias-definitions will be used.\r
-     *  Example:\r
-     *  <xsl:namespace-alias stylesheet-prefix="bar"\r
-     *                       result-prefix="foo"/>\r
-     *\r
-     *  <xsl:namespace-alias stylesheet-prefix="zar"\r
-     *                       result-prefix="foo"/>\r
-     * Cases using #default:\r
-     *  <xsl:namespace-alias stylesheet-prefix="#default"\r
-     *                       result-prefix="#default"/>\r
-     *  TODO: Has this an effect at all?\r
-     *\r
-     *  <xsl:namespace-alias stylesheet-prefix="foo"\r
-     *                       result-prefix="#default"/>\r
-     *  From namespace to no namespace.\r
-     *\r
-     *  <xsl:namespace-alias stylesheet-prefix="#default"\r
-     *                       result-prefix="foo"/>\r
-     *  From no namespace to namespace.\r
-     */\r
-    \r
-       \r
-     /*\r
-     * Store the ns-node in the alias-object.\r
-    */\r
-    alias = xsltNewNsAlias(XSLT_CCTXT(style));\r
-    if (alias == NULL)\r
-       return;\r
-    alias->literalNs = literalNs;\r
-    alias->targetNs = targetNs;\r
-    XSLT_CCTXT(style)->hasNsAliases = 1;\r
-\r
-\r
-#else /* XSLT_REFACTORED */\r
-    const xmlChar *literalNsName;\r
-    const xmlChar *targetNsName;\r
-    \r
-\r
-    if ((style == NULL) || (node == NULL))\r
-       return;\r
-\r
-    stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL);\r
-    if (stylePrefix == NULL) {\r
-       xsltTransformError(NULL, style, node,\r
-           "namespace-alias: stylesheet-prefix attribute missing\n");\r
-       return;\r
-    }\r
-    resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL);\r
-    if (resultPrefix == NULL) {\r
-       xsltTransformError(NULL, style, node,\r
-           "namespace-alias: result-prefix attribute missing\n");\r
-       goto error;\r
-    }\r
-    \r
-    if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default")) {\r
-       literalNs = xmlSearchNs(node->doc, node, NULL);\r
-       if (literalNs == NULL) {\r
-           literalNsName = NULL;\r
-       } else\r
-           literalNsName = literalNs->href; /* Yes - set for nsAlias table */\r
-    } else {\r
-       literalNs = xmlSearchNs(node->doc, node, stylePrefix);\r
\r
-       if ((literalNs == NULL) || (literalNs->href == NULL)) {\r
-           xsltTransformError(NULL, style, node,\r
-               "namespace-alias: prefix %s not bound to any namespace\n",\r
-                                       stylePrefix);\r
-           goto error;\r
-       } else\r
-           literalNsName = literalNs->href;\r
-    }\r
-\r
-    /*\r
-     * When "#default" is used for result, if a default namespace has not\r
-     * been explicitly declared the special value UNDEFINED_DEFAULT_NS is\r
-     * put into the nsAliases table\r
-     */\r
-    if (xmlStrEqual(resultPrefix, (const xmlChar *)"#default")) {\r
-       targetNs = xmlSearchNs(node->doc, node, NULL);\r
-       if (targetNs == NULL) {\r
-           targetNsName = UNDEFINED_DEFAULT_NS;\r
-       } else\r
-           targetNsName = targetNs->href;\r
-    } else {\r
-       targetNs = xmlSearchNs(node->doc, node, resultPrefix);\r
-\r
-        if ((targetNs == NULL) || (targetNs->href == NULL)) {\r
-           xsltTransformError(NULL, style, node,\r
-               "namespace-alias: prefix %s not bound to any namespace\n",\r
-                                       resultPrefix);\r
-           goto error;\r
-       } else\r
-           targetNsName = targetNs->href;\r
-    }\r
-    /*\r
-     * Special case: if #default is used for\r
-     *  the stylesheet-prefix (literal namespace) and there's no default\r
-     *  namespace in scope, we'll use style->defaultAlias for this.\r
-     */   \r
-    if (literalNsName == NULL) {\r
-        if (targetNs != NULL) {\r
-           /*\r
-           * BUG TODO: Is it not sufficient to have only 1 field for\r
-           *  this, since subsequently alias declarations will\r
-           *  overwrite this.      \r
-           *  Example:\r
-           *   <xsl:namespace-alias result-prefix="foo"\r
-           *                        stylesheet-prefix="#default"/>\r
-           *   <xsl:namespace-alias result-prefix="bar"\r
-           *                        stylesheet-prefix="#default"/>\r
-           *  The mapping for "foo" won't be visible anymore.\r
-           */\r
-            style->defaultAlias = targetNs->href;\r
-       }\r
-    } else {\r
-        if (style->nsAliases == NULL)\r
-           style->nsAliases = xmlHashCreate(10);\r
-        if (style->nsAliases == NULL) {\r
-           xsltTransformError(NULL, style, node,\r
-               "namespace-alias: cannot create hash table\n");\r
-           goto error;\r
-        }\r
-       xmlHashAddEntry((xmlHashTablePtr) style->nsAliases,\r
-           literalNsName, (void *) targetNsName);\r
-    }\r
-#endif /* else of XSLT_REFACTORED */\r
-\r
-error:\r
-    if (stylePrefix != NULL)\r
-       xmlFree(stylePrefix);\r
-    if (resultPrefix != NULL)\r
-       xmlFree(resultPrefix);\r
-}\r
-\r
-/**\r
- * xsltGetSpecialNamespace:\r
- * @ctxt:  the transformation context\r
- * @invocNode: the invoking node; e.g. a literal result element/attr;\r
- *             only used for error reports\r
- * @nsName:  the namespace name (or NULL)\r
- * @nsPrefix:  the suggested namespace prefix (or NULL)\r
- * @target:  the result element on which to anchor a namespace\r
- *\r
- * Find a matching (prefix and ns-name) ns-declaration\r
- * for the requested @nsName and @nsPrefix in the result tree.\r
- * If none is found then a new ns-declaration will be\r
- * added to @resultElem. If, in this case, the given prefix is\r
- * already in use, then a ns-declaration with a modified ns-prefix\r
- * be we created. Note that this function's priority is to\r
- * preserve ns-prefixes; it will only change a prefix if there's\r
- * a namespace clash.\r
- * If both @nsName and @nsPrefix are NULL, then this will try to\r
- * "undeclare" a default namespace by declaring an xmlns="".\r
- *\r
- * Returns a namespace declaration or NULL.\r
- */\r
-xmlNsPtr\r
-xsltGetSpecialNamespace(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,\r
-               const xmlChar *nsName, const xmlChar *nsPrefix,\r
-               xmlNodePtr target)\r
-{\r
-    xmlNsPtr ns;\r
-    int prefixOccupied = 0;\r
-\r
-    if ((ctxt == NULL) || (target == NULL) ||\r
-       (target->type != XML_ELEMENT_NODE))\r
-       return(NULL);\r
-\r
-    /*\r
-    * NOTE: Namespace exclusion and ns-aliasing is performed at\r
-    *  compilation-time in the refactored code; so this need not be done\r
-    *  here (it was in the old code).\r
-    * NOTE: @invocNode was named @cur in the old code and was documented to\r
-    *  be an input node; since it was only used to anchor an error report\r
-    *  somewhere, we can safely change this to @invocNode, which now\r
-    *  will be the XSLT instruction (also a literal result element/attribute),\r
-    *  which was responsible for this call.\r
-    */\r
-    /*\r
-    * OPTIMIZE TODO: This all could be optimized by keeping track of\r
-    *  the ns-decls currently in-scope via a specialized context.\r
-    */    \r
-    if ((nsPrefix == NULL) && ((nsName == NULL) || (nsName[0] == 0))) {\r
-       /*\r
-       * NOTE: the "undeclaration" of the default namespace was\r
-       * part of the logic of the old xsltGetSpecialNamespace() code,\r
-       * so we'll keep that mechanism.\r
-       * Related to the old code: bug #302020:\r
-       */\r
-       /*\r
-       * OPTIMIZE TODO: This all could be optimized by keeping track of\r
-       *  the ns-decls currently in-scope via a specialized context.\r
-       */\r
-       /*\r
-       * Search on the result element itself.\r
-       */\r
-       if (target->nsDef != NULL) {\r
-           ns = target->nsDef;\r
-           do {\r
-               if (ns->prefix == NULL) {\r
-                   if ((ns->href != NULL) && (ns->href[0] != 0)) {\r
-                       /*\r
-                       * Raise a namespace normalization error.\r
-                       */\r
-                       xsltTransformError(ctxt, NULL, invocNode,\r
-                           "Namespace normalization error: Cannot undeclare "\r
-                           "the default namespace, since the default namespace "\r
-                           "'%s' is already declared on the result element "\r
-                           "'%s'.\n", ns->href, target->name);\r
-                       return(NULL);\r
-                   } else {\r
-                       /*\r
-                       * The default namespace was undeclared on the\r
-                       * result element.\r
-                       */\r
-                       return(NULL);\r
-                   }\r
-                   break;\r
-               }\r
-               ns = ns->next;\r
-           } while (ns != NULL);\r
-       }       \r
-       if ((target->parent != NULL) &&\r
-           (target->parent->type == XML_ELEMENT_NODE))\r
-       {\r
-           /*\r
-           * The parent element is in no namespace, so assume\r
-           * that there is no default namespace in scope.\r
-           */\r
-           if (target->parent->ns == NULL)\r
-               return(NULL);\r
-           \r
-           ns = xmlSearchNs(target->doc, target->parent,\r
-               NULL);\r
-           /*\r
-           * Fine if there's no default ns is scope, or if the\r
-           * default ns was undeclared.\r
-           */\r
-           if ((ns == NULL) || (ns->href == NULL) || (ns->href[0] == 0))\r
-               return(NULL);\r
-           \r
-           /*\r
-           * Undeclare the default namespace.\r
-           */\r
-           xmlNewNs(target, BAD_CAST "", NULL);\r
-           /* TODO: Check result */    \r
-           return(NULL);\r
-       }\r
-       return(NULL);\r
-    }\r
-    /*\r
-    * Handle the XML namespace.\r
-    * QUESTION: Is this faster than using xmlStrEqual() anyway?\r
-    */\r
-    if ((nsPrefix != NULL) &&\r
-       (nsPrefix[0] == 'x') && (nsPrefix[1] == 'm') &&\r
-       (nsPrefix[2] == 'l') && (nsPrefix[3] == 0))\r
-    {\r
-       return(xmlSearchNs(target->doc, target, nsPrefix));\r
-    }\r
-    /*\r
-    * First: search on the result element itself.\r
-    */\r
-    if (target->nsDef != NULL) {\r
-       ns = target->nsDef;\r
-       do {\r
-           if ((ns->prefix == NULL) == (nsPrefix == NULL)) {\r
-               if (ns->prefix == nsPrefix) {\r
-                   if (xmlStrEqual(ns->href, nsName))\r
-                       return(ns);\r
-                   prefixOccupied = 1;\r
-                   break;\r
-               } else if (xmlStrEqual(ns->prefix, nsPrefix)) {\r
-                   if (xmlStrEqual(ns->href, nsName))\r
-                       return(ns);\r
-                   prefixOccupied = 1;\r
-                   break;\r
-               }\r
-           }\r
-           ns = ns->next;\r
-       } while (ns != NULL);\r
-    }\r
-    if (prefixOccupied) {\r
-       /*\r
-       * If the ns-prefix is occupied by an other ns-decl on the\r
-       * result element, then this means:\r
-       * 1) The desired prefix is shadowed\r
-       * 2) There's no way around changing the prefix  \r
-       *\r
-       * Try a desperate search for an in-scope ns-decl\r
-       * with a matching ns-name before we use the last option,\r
-       * which is to recreate the ns-decl with a modified prefix.\r
-       */\r
-       ns = xmlSearchNsByHref(target->doc, target, nsName);\r
-       if (ns != NULL)\r
-           return(ns);\r
-\r
-       /*\r
-       * Fallback to changing the prefix.\r
-       */    \r
-    } else if ((target->parent != NULL) &&\r
-       (target->parent->type == XML_ELEMENT_NODE))\r
-    {\r
-       /*\r
-       * Try to find a matching ns-decl in the ancestor-axis.\r
-       *\r
-       * Check the common case: The parent element of the current\r
-       * result element is in the same namespace (with an equal ns-prefix).\r
-       */     \r
-       if ((target->parent->ns != NULL) &&\r
-           ((target->parent->ns->prefix != NULL) == (nsPrefix != NULL)))\r
-       {\r
-           ns = target->parent->ns;\r
-           \r
-           if (nsPrefix == NULL) {\r
-               if (xmlStrEqual(ns->href, nsName))\r
-                   return(ns);\r
-           } else if (xmlStrEqual(ns->prefix, nsPrefix) &&\r
-               xmlStrEqual(ns->href, nsName))\r
-           {\r
-               return(ns);\r
-           }\r
-       }\r
-       /*\r
-       * Lookup the remaining in-scope namespaces.\r
-       */    \r
-       ns = xmlSearchNs(target->doc, target->parent, nsPrefix);\r
-       if (ns != NULL) {\r
-           if (xmlStrEqual(ns->href, nsName))\r
-               return(ns);         \r
-           /*\r
-           * Now check for a nasty case: We need to ensure that the new\r
-           * ns-decl won't shadow a prefix in-use by an existing attribute.\r
-           * <foo xmlns:a="urn:test:a">\r
-           *   <bar a:a="val-a">\r
-           *     <xsl:attribute xmlns:a="urn:test:b" name="a:b">\r
-           *        val-b</xsl:attribute>\r
-           *   </bar>\r
-           * </foo>\r
-           */\r
-           if (target->properties) {\r
-               xmlAttrPtr attr = target->properties;\r
-               do {\r
-                   if ((attr->ns) &&\r
-                       xmlStrEqual(attr->ns->prefix, nsPrefix))\r
-                   {\r
-                       /*\r
-                       * Bad, this prefix is already in use.\r
-                       * Since we'll change the prefix anyway, try\r
-                       * a search for a matching ns-decl based on the\r
-                       * namespace name.\r
-                       */\r
-                       ns = xmlSearchNsByHref(target->doc, target, nsName);\r
-                       if (ns != NULL)\r
-                           return(ns);\r
-                       goto declare_new_prefix;\r
-                   }\r
-                   attr = attr->next;\r
-               } while (attr != NULL);\r
-           }\r
-       } else {\r
-           /*\r
-           * Either no matching ns-prefix was found or the namespace is\r
-           * shadowed.\r
-           * Create a new ns-decl on the current result element.\r
-           *\r
-           * Hmm, we could also try to reuse an in-scope\r
-           * namespace with a matching ns-name but a different\r
-           * ns-prefix.\r
-           * What has higher priority? \r
-           *  1) If keeping the prefix: create a new ns-decl.\r
-           *  2) If reusal: first lookup ns-names; then fallback\r
-           *     to creation of a new ns-decl.\r
-           * REVISIT: this currently uses case 1) although\r
-           *  the old way was use xmlSearchNsByHref() and to let change\r
-           *  the prefix.\r
-           */\r
-#if 0\r
-           ns = xmlSearchNsByHref(target->doc, target, nsName);\r
-           if (ns != NULL)\r
-               return(ns);\r
-#endif\r
-       }\r
-       /*\r
-       * Create the ns-decl on the current result element.\r
-       */\r
-       ns = xmlNewNs(target, nsName, nsPrefix);\r
-       /* TODO: check errors */\r
-       return(ns);\r
-    } else {\r
-       /*\r
-       * This is either the root of the tree or something weird is going on.\r
-       */\r
-       ns = xmlNewNs(target, nsName, nsPrefix);\r
-       /* TODO: Check result */\r
-       return(ns);\r
-    }\r
-\r
-declare_new_prefix:\r
-    /*\r
-    * Fallback: we need to generate a new prefix and declare the namespace\r
-    * on the result element.\r
-    */\r
-    {\r
-       xmlChar pref[30];\r
-       int counter = 1;\r
-               \r
-       do {\r
-           snprintf((char *) pref, 30, "%s_%d", nsPrefix, counter++);\r
-           ns = xmlSearchNs(target->doc, target, BAD_CAST pref);\r
-           if (counter > 1000) {\r
-               xsltTransformError(ctxt, NULL, invocNode,\r
-                   "Internal error in xsltAcquireResultInScopeNs(): "              \r
-                   "Failed to compute a unique ns-prefix for the "\r
-                   "generated element");\r
-               return(NULL);\r
-           }\r
-       } while (ns != NULL);\r
-       ns = xmlNewNs(target, nsName, BAD_CAST pref);\r
-       /* TODO: Check result */\r
-       return(ns);\r
-    }\r
-    return(NULL);   \r
-}\r
-\r
-/**\r
- * xsltGetNamespace:\r
- * @ctxt:  a transformation context\r
- * @cur:  the input node\r
- * @ns:  the namespace\r
- * @out:  the output node (or its parent)\r
- *\r
- * Find a matching (prefix and ns-name) ns-declaration\r
- * for the requested @ns->prefix and @ns->href in the result tree.\r
- * If none is found then a new ns-declaration will be\r
- * added to @resultElem. If, in this case, the given prefix is\r
- * already in use, then a ns-declaration with a modified ns-prefix\r
- * be we created.\r
- *\r
- * Called by:\r
- *  - xsltCopyPropList() (*not*  anymore)\r
- *  - xsltShallowCopyElement()\r
- *  - xsltCopyTreeInternal() (*not*  anymore)\r
- *  - xsltApplySequenceConstructor() (*not* in the refactored code),\r
- *  - xsltElement() (*not* anymore)\r
- *\r
- * Returns a namespace declaration or NULL in case of\r
- *         namespace fixup failures or API or internal errors.\r
- */\r
-xmlNsPtr\r
-xsltGetNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns,\r
-                xmlNodePtr out)\r
-{    \r
-    \r
-    if (ns == NULL)\r
-       return(NULL);\r
-\r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * Namespace exclusion and ns-aliasing is performed at\r
-    * compilation-time in the refactored code.\r
-    * Additionally, aliasing is not intended for non Literal\r
-    * Result Elements.\r
-    */\r
-    return(xsltGetSpecialNamespace(ctxt, cur, ns->href, ns->prefix, out));\r
-#else\r
-    {\r
-       xsltStylesheetPtr style;\r
-       const xmlChar *URI = NULL; /* the replacement URI */\r
-\r
-       if ((ctxt == NULL) || (cur == NULL) || (out == NULL))\r
-           return(NULL);\r
-\r
-       style = ctxt->style;\r
-       while (style != NULL) {\r
-           if (style->nsAliases != NULL)\r
-               URI = (const xmlChar *) \r
-               xmlHashLookup(style->nsAliases, ns->href);\r
-           if (URI != NULL)\r
-               break;\r
-           \r
-           style = xsltNextImport(style);\r
-       }\r
-       \r
-       \r
-       if (URI == UNDEFINED_DEFAULT_NS) {\r
-           return(xsltGetSpecialNamespace(ctxt, cur, NULL, NULL, out));\r
-#if 0\r
-           /*\r
-           * TODO: Removed, since wrong. If there was no default\r
-           * namespace in the stylesheet then this must resolve to\r
-           * the NULL namespace.\r
-           */\r
-           xmlNsPtr dflt;          \r
-           dflt = xmlSearchNs(cur->doc, cur, NULL);\r
-           if (dflt != NULL)\r
-               URI = dflt->href;\r
-           else\r
-               return NULL;\r
-#endif\r
-       } else if (URI == NULL)\r
-           URI = ns->href;\r
-\r
-       return(xsltGetSpecialNamespace(ctxt, cur, URI, ns->prefix, out));\r
-    }\r
-#endif\r
-}\r
-\r
-/**\r
- * xsltGetPlainNamespace:\r
- * @ctxt:  a transformation context\r
- * @cur:  the input node\r
- * @ns:  the namespace\r
- * @out:  the result element\r
- *\r
- * Obsolete. \r
- * *Not* called by any Libxslt/Libexslt function.\r
- * Exaclty the same as xsltGetNamespace(). \r
- *\r
- * Returns a namespace declaration or NULL in case of\r
- *         namespace fixup failures or API or internal errors.\r
- */\r
-xmlNsPtr\r
-xsltGetPlainNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur,\r
-                      xmlNsPtr ns, xmlNodePtr out)\r
-{    \r
-    return(xsltGetNamespace(ctxt, cur, ns, out));\r
-}\r
-\r
-/**\r
- * xsltCopyNamespaceList:\r
- * @ctxt:  a transformation context\r
- * @node:  the target node\r
- * @cur:  the first namespace\r
- *\r
- * Do a copy of an namespace list. If @node is non-NULL the\r
- * new namespaces are added automatically. This handles namespaces\r
- * aliases.\r
- * This function is intended only for *internal* use at\r
- * transformation-time for copying ns-declarations of Literal\r
- * Result Elements.\r
- * \r
- * Called by:\r
- *   xsltCopyTreeInternal() (transform.c)\r
- *   xsltShallowCopyElem() (transform.c)\r
- *\r
- * REVISIT: This function won't be used in the refactored code.\r
- *\r
- * Returns: a new xmlNsPtr, or NULL in case of error.\r
- */\r
-xmlNsPtr\r
-xsltCopyNamespaceList(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                     xmlNsPtr cur) {\r
-    xmlNsPtr ret = NULL, tmp;\r
-    xmlNsPtr p = NULL,q;    \r
-\r
-    if (cur == NULL)\r
-       return(NULL);\r
-    if (cur->type != XML_NAMESPACE_DECL)\r
-       return(NULL);\r
-\r
-    /*\r
-     * One can add namespaces only on element nodes\r
-     */\r
-    if ((node != NULL) && (node->type != XML_ELEMENT_NODE))\r
-       node = NULL;\r
-\r
-    while (cur != NULL) {\r
-       if (cur->type != XML_NAMESPACE_DECL)\r
-           break;\r
-\r
-       /*\r
-        * Avoid duplicating namespace declarations in the tree if\r
-        * a matching declaration is in scope.\r
-        */\r
-       if (node != NULL) {\r
-           if ((node->ns != NULL) &&\r
-               (xmlStrEqual(node->ns->prefix, cur->prefix)) &&\r
-               (xmlStrEqual(node->ns->href, cur->href))) {\r
-               cur = cur->next;\r
-               continue;\r
-           }\r
-           tmp = xmlSearchNs(node->doc, node, cur->prefix);\r
-           if ((tmp != NULL) && (xmlStrEqual(tmp->href, cur->href))) {\r
-               cur = cur->next;\r
-               continue;\r
-           }\r
-       }\r
-#ifdef XSLT_REFACTORED\r
-       /*\r
-       * Namespace exclusion and ns-aliasing is performed at\r
-       * compilation-time in the refactored code.\r
-       */\r
-       q = xmlNewNs(node, cur->href, cur->prefix);\r
-       if (p == NULL) {\r
-           ret = p = q;\r
-       } else {\r
-           p->next = q;\r
-           p = q;\r
-       }\r
-#else\r
-       /*\r
-       * TODO: Remove this if the refactored code gets enabled.\r
-       */\r
-       if (!xmlStrEqual(cur->href, XSLT_NAMESPACE)) {\r
-           const xmlChar *URI;\r
-           /* TODO apply cascading */\r
-           URI = (const xmlChar *) xmlHashLookup(ctxt->style->nsAliases,\r
-                                                 cur->href);\r
-           if (URI == UNDEFINED_DEFAULT_NS)\r
-               continue;\r
-           if (URI != NULL) {\r
-               q = xmlNewNs(node, URI, cur->prefix);\r
-           } else {\r
-               q = xmlNewNs(node, cur->href, cur->prefix);\r
-           }\r
-           if (p == NULL) {\r
-               ret = p = q;\r
-           } else {\r
-               p->next = q;\r
-               p = q;\r
-           }\r
-       }\r
-#endif\r
-       cur = cur->next;\r
-    }\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltCopyNamespace:\r
- * @ctxt:  a transformation context\r
- * @elem:  the target element node\r
- * @ns:  the namespace node\r
- *\r
- * Copies a namespace node (declaration). If @elem is not NULL,\r
- * then the new namespace will be declared on @elem.\r
- *\r
- * Returns: a new xmlNsPtr, or NULL in case of an error.\r
- */\r
-xmlNsPtr\r
-xsltCopyNamespace(xsltTransformContextPtr ctxt, xmlNodePtr elem,\r
-                 xmlNsPtr ns)\r
-{    \r
-    if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))\r
-       return(NULL);\r
-    /*\r
-     * One can add namespaces only on element nodes\r
-     */\r
-    if ((elem != NULL) && (elem->type != XML_ELEMENT_NODE))\r
-       return(xmlNewNs(NULL, ns->href, ns->prefix));\r
-    else\r
-       return(xmlNewNs(elem, ns->href, ns->prefix));\r
-}\r
-\r
-\r
-/**\r
- * xsltFreeNamespaceAliasHashes:\r
- * @style: an XSLT stylesheet\r
- *\r
- * Free up the memory used by namespaces aliases\r
- */\r
-void\r
-xsltFreeNamespaceAliasHashes(xsltStylesheetPtr style) {\r
-    if (style->nsAliases != NULL)\r
-       xmlHashFree((xmlHashTablePtr) style->nsAliases, NULL);\r
-    style->nsAliases = NULL;\r
-}\r
+/*
+ * namespaces.c: Implementation of the XSLT namespaces handling
+ *
+ * Reference:
+ *   http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <string.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#endif
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
+#ifdef HAVE_NAN_H
+#include <nan.h>
+#endif
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/hash.h>
+#include <libxml/xmlerror.h>
+#include <libxml/uri.h>
+#include "xslt.h"
+#include "xsltInternals.h"
+#include "xsltutils.h"
+#include "namespaces.h"
+#include "imports.h"
+
+/************************************************************************
+ *                                                                     *
+ *                     Module interfaces                               *
+ *                                                                     *
+ ************************************************************************/
+
+#ifdef XSLT_REFACTORED  
+static xsltNsAliasPtr
+xsltNewNsAlias(xsltCompilerCtxtPtr cctxt)
+{
+    xsltNsAliasPtr ret;
+
+    if (cctxt == NULL)
+       return(NULL);
+
+    ret = (xsltNsAliasPtr) xmlMalloc(sizeof(xsltNsAlias));
+    if (ret == NULL) {
+       xsltTransformError(NULL, cctxt->style, NULL,
+           "Internal error in xsltNewNsAlias(): Memory allocation failed.\n");
+       cctxt->style->errors++;
+       return(NULL);
+    }
+    memset(ret, 0, sizeof(xsltNsAlias));    
+    /*
+    * TODO: Store the item at current stylesheet-level.
+    */
+    ret->next = cctxt->nsAliases;
+    cctxt->nsAliases = ret;       
+
+    return(ret);
+}
+#endif /* XSLT_REFACTORED */
+/**
+ * xsltNamespaceAlias:
+ * @style:  the XSLT stylesheet
+ * @node:  the xsl:namespace-alias node
+ *
+ * Read the stylesheet-prefix and result-prefix attributes, register
+ * them as well as the corresponding namespace.
+ */
+void
+xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node)
+{
+    xmlChar *resultPrefix = NULL;
+    xmlChar *stylePrefix = NULL;
+    xmlNsPtr literalNs = NULL;
+    xmlNsPtr targetNs = NULL;
+#ifdef XSLT_REFACTORED 
+    xsltNsAliasPtr alias;
+
+    if ((style == NULL) || (node == NULL))
+       return;
+
+    /*
+    * SPEC XSLT 1.0:
+    *  "If a namespace URI is declared to be an alias for multiple
+    *  different namespace URIs, then the declaration with the highest
+    *  import precedence is used. It is an error if there is more than
+    *  one such declaration. An XSLT processor may signal the error;
+    *  if it does not signal the error, it must recover by choosing,
+    *  from amongst the declarations with the highest import precedence,
+    *  the one that occurs last in the stylesheet."
+    *
+    * SPEC TODO: Check for the errors mentioned above.
+    */
+    /*
+    * NOTE that the XSLT 2.0 also *does* use the NULL namespace if
+    *  "#default" is used and there's no default namespace is scope.
+    *  I.e., this is *not* an error. 
+    *  Most XSLT 1.0 implementations work this way.
+    *  The XSLT 1.0 spec has nothing to say on the subject. 
+    */
+    /*
+    * Attribute "stylesheet-prefix".
+    */
+    stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL);
+    if (stylePrefix == NULL) {
+       xsltTransformError(NULL, style, node,
+           "The attribute 'stylesheet-prefix' is missing.\n");
+       return;
+    }
+    if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default"))
+       literalNs = xmlSearchNs(node->doc, node, NULL); 
+    else {
+       literalNs = xmlSearchNs(node->doc, node, stylePrefix);
+       if (literalNs == NULL) {
+           xsltTransformError(NULL, style, node,
+               "Attribute 'stylesheet-prefix': There's no namespace "
+               "declaration in scope for the prefix '%s'.\n",
+                   stylePrefix);
+           goto error;
+       }
+    }
+    /*
+    * Attribute "result-prefix".
+    */
+    resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL);
+    if (resultPrefix == NULL) {
+       xsltTransformError(NULL, style, node,
+           "The attribute 'result-prefix' is missing.\n");
+       goto error;
+    }        
+    if (xmlStrEqual(resultPrefix, (const xmlChar *)"#default"))
+       targetNs = xmlSearchNs(node->doc, node, NULL);
+    else {
+       targetNs = xmlSearchNs(node->doc, node, resultPrefix);
+
+        if (targetNs == NULL) {
+          xsltTransformError(NULL, style, node,
+               "Attribute 'result-prefix': There's no namespace "
+               "declaration in scope for the prefix '%s'.\n",
+                   stylePrefix);
+           goto error;
+       }
+    }
+    /*
+     *
+     * Same alias for multiple different target namespace URIs:
+     *  TODO: The one with the highest import precedence is used.
+     *  Example:
+     *  <xsl:namespace-alias stylesheet-prefix="foo"
+     *                       result-prefix="bar"/>
+     *
+     *  <xsl:namespace-alias stylesheet-prefix="foo"
+     *                       result-prefix="zar"/>
+     *
+     * Same target namespace URI for multiple different aliases:
+     *  All alias-definitions will be used.
+     *  Example:
+     *  <xsl:namespace-alias stylesheet-prefix="bar"
+     *                       result-prefix="foo"/>
+     *
+     *  <xsl:namespace-alias stylesheet-prefix="zar"
+     *                       result-prefix="foo"/>
+     * Cases using #default:
+     *  <xsl:namespace-alias stylesheet-prefix="#default"
+     *                       result-prefix="#default"/>
+     *  TODO: Has this an effect at all?
+     *
+     *  <xsl:namespace-alias stylesheet-prefix="foo"
+     *                       result-prefix="#default"/>
+     *  From namespace to no namespace.
+     *
+     *  <xsl:namespace-alias stylesheet-prefix="#default"
+     *                       result-prefix="foo"/>
+     *  From no namespace to namespace.
+     */
+    
+       
+     /*
+     * Store the ns-node in the alias-object.
+    */
+    alias = xsltNewNsAlias(XSLT_CCTXT(style));
+    if (alias == NULL)
+       return;
+    alias->literalNs = literalNs;
+    alias->targetNs = targetNs;
+    XSLT_CCTXT(style)->hasNsAliases = 1;
+
+
+#else /* XSLT_REFACTORED */
+    const xmlChar *literalNsName;
+    const xmlChar *targetNsName;
+    
+
+    if ((style == NULL) || (node == NULL))
+       return;
+
+    stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL);
+    if (stylePrefix == NULL) {
+       xsltTransformError(NULL, style, node,
+           "namespace-alias: stylesheet-prefix attribute missing\n");
+       return;
+    }
+    resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL);
+    if (resultPrefix == NULL) {
+       xsltTransformError(NULL, style, node,
+           "namespace-alias: result-prefix attribute missing\n");
+       goto error;
+    }
+    
+    if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default")) {
+       literalNs = xmlSearchNs(node->doc, node, NULL);
+       if (literalNs == NULL) {
+           literalNsName = NULL;
+       } else
+           literalNsName = literalNs->href; /* Yes - set for nsAlias table */
+    } else {
+       literalNs = xmlSearchNs(node->doc, node, stylePrefix);
+       if ((literalNs == NULL) || (literalNs->href == NULL)) {
+           xsltTransformError(NULL, style, node,
+               "namespace-alias: prefix %s not bound to any namespace\n",
+                                       stylePrefix);
+           goto error;
+       } else
+           literalNsName = literalNs->href;
+    }
+
+    /*
+     * When "#default" is used for result, if a default namespace has not
+     * been explicitly declared the special value UNDEFINED_DEFAULT_NS is
+     * put into the nsAliases table
+     */
+    if (xmlStrEqual(resultPrefix, (const xmlChar *)"#default")) {
+       targetNs = xmlSearchNs(node->doc, node, NULL);
+       if (targetNs == NULL) {
+           targetNsName = UNDEFINED_DEFAULT_NS;
+       } else
+           targetNsName = targetNs->href;
+    } else {
+       targetNs = xmlSearchNs(node->doc, node, resultPrefix);
+
+        if ((targetNs == NULL) || (targetNs->href == NULL)) {
+           xsltTransformError(NULL, style, node,
+               "namespace-alias: prefix %s not bound to any namespace\n",
+                                       resultPrefix);
+           goto error;
+       } else
+           targetNsName = targetNs->href;
+    }
+    /*
+     * Special case: if #default is used for
+     *  the stylesheet-prefix (literal namespace) and there's no default
+     *  namespace in scope, we'll use style->defaultAlias for this.
+     */   
+    if (literalNsName == NULL) {
+        if (targetNs != NULL) {
+           /*
+           * BUG TODO: Is it not sufficient to have only 1 field for
+           *  this, since subsequently alias declarations will
+           *  overwrite this.      
+           *  Example:
+           *   <xsl:namespace-alias result-prefix="foo"
+           *                        stylesheet-prefix="#default"/>
+           *   <xsl:namespace-alias result-prefix="bar"
+           *                        stylesheet-prefix="#default"/>
+           *  The mapping for "foo" won't be visible anymore.
+           */
+            style->defaultAlias = targetNs->href;
+       }
+    } else {
+        if (style->nsAliases == NULL)
+           style->nsAliases = xmlHashCreate(10);
+        if (style->nsAliases == NULL) {
+           xsltTransformError(NULL, style, node,
+               "namespace-alias: cannot create hash table\n");
+           goto error;
+        }
+       xmlHashAddEntry((xmlHashTablePtr) style->nsAliases,
+           literalNsName, (void *) targetNsName);
+    }
+#endif /* else of XSLT_REFACTORED */
+
+error:
+    if (stylePrefix != NULL)
+       xmlFree(stylePrefix);
+    if (resultPrefix != NULL)
+       xmlFree(resultPrefix);
+}
+
+/**
+ * xsltGetSpecialNamespace:
+ * @ctxt:  the transformation context
+ * @invocNode: the invoking node; e.g. a literal result element/attr;
+ *             only used for error reports
+ * @nsName:  the namespace name (or NULL)
+ * @nsPrefix:  the suggested namespace prefix (or NULL)
+ * @target:  the result element on which to anchor a namespace
+ *
+ * Find a matching (prefix and ns-name) ns-declaration
+ * for the requested @nsName and @nsPrefix in the result tree.
+ * If none is found then a new ns-declaration will be
+ * added to @resultElem. If, in this case, the given prefix is
+ * already in use, then a ns-declaration with a modified ns-prefix
+ * be we created. Note that this function's priority is to
+ * preserve ns-prefixes; it will only change a prefix if there's
+ * a namespace clash.
+ * If both @nsName and @nsPrefix are NULL, then this will try to
+ * "undeclare" a default namespace by declaring an xmlns="".
+ *
+ * Returns a namespace declaration or NULL.
+ */
+xmlNsPtr
+xsltGetSpecialNamespace(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
+               const xmlChar *nsName, const xmlChar *nsPrefix,
+               xmlNodePtr target)
+{
+    xmlNsPtr ns;
+    int prefixOccupied = 0;
+
+    if ((ctxt == NULL) || (target == NULL) ||
+       (target->type != XML_ELEMENT_NODE))
+       return(NULL);
+
+    /*
+    * NOTE: Namespace exclusion and ns-aliasing is performed at
+    *  compilation-time in the refactored code; so this need not be done
+    *  here (it was in the old code).
+    * NOTE: @invocNode was named @cur in the old code and was documented to
+    *  be an input node; since it was only used to anchor an error report
+    *  somewhere, we can safely change this to @invocNode, which now
+    *  will be the XSLT instruction (also a literal result element/attribute),
+    *  which was responsible for this call.
+    */
+    /*
+    * OPTIMIZE TODO: This all could be optimized by keeping track of
+    *  the ns-decls currently in-scope via a specialized context.
+    */    
+    if ((nsPrefix == NULL) && ((nsName == NULL) || (nsName[0] == 0))) {
+       /*
+       * NOTE: the "undeclaration" of the default namespace was
+       * part of the logic of the old xsltGetSpecialNamespace() code,
+       * so we'll keep that mechanism.
+       * Related to the old code: bug #302020:
+       */
+       /*
+       * OPTIMIZE TODO: This all could be optimized by keeping track of
+       *  the ns-decls currently in-scope via a specialized context.
+       */
+       /*
+       * Search on the result element itself.
+       */
+       if (target->nsDef != NULL) {
+           ns = target->nsDef;
+           do {
+               if (ns->prefix == NULL) {
+                   if ((ns->href != NULL) && (ns->href[0] != 0)) {
+                       /*
+                       * Raise a namespace normalization error.
+                       */
+                       xsltTransformError(ctxt, NULL, invocNode,
+                           "Namespace normalization error: Cannot undeclare "
+                           "the default namespace, since the default namespace "
+                           "'%s' is already declared on the result element "
+                           "'%s'.\n", ns->href, target->name);
+                       return(NULL);
+                   } else {
+                       /*
+                       * The default namespace was undeclared on the
+                       * result element.
+                       */
+                       return(NULL);
+                   }
+                   break;
+               }
+               ns = ns->next;
+           } while (ns != NULL);
+       }       
+       if ((target->parent != NULL) &&
+           (target->parent->type == XML_ELEMENT_NODE))
+       {
+           /*
+           * The parent element is in no namespace, so assume
+           * that there is no default namespace in scope.
+           */
+           if (target->parent->ns == NULL)
+               return(NULL);
+           
+           ns = xmlSearchNs(target->doc, target->parent,
+               NULL);
+           /*
+           * Fine if there's no default ns is scope, or if the
+           * default ns was undeclared.
+           */
+           if ((ns == NULL) || (ns->href == NULL) || (ns->href[0] == 0))
+               return(NULL);
+           
+           /*
+           * Undeclare the default namespace.
+           */
+           xmlNewNs(target, BAD_CAST "", NULL);
+           /* TODO: Check result */    
+           return(NULL);
+       }
+       return(NULL);
+    }
+    /*
+    * Handle the XML namespace.
+    * QUESTION: Is this faster than using xmlStrEqual() anyway?
+    */
+    if ((nsPrefix != NULL) &&
+       (nsPrefix[0] == 'x') && (nsPrefix[1] == 'm') &&
+       (nsPrefix[2] == 'l') && (nsPrefix[3] == 0))
+    {
+       return(xmlSearchNs(target->doc, target, nsPrefix));
+    }
+    /*
+    * First: search on the result element itself.
+    */
+    if (target->nsDef != NULL) {
+       ns = target->nsDef;
+       do {
+           if ((ns->prefix == NULL) == (nsPrefix == NULL)) {
+               if (ns->prefix == nsPrefix) {
+                   if (xmlStrEqual(ns->href, nsName))
+                       return(ns);
+                   prefixOccupied = 1;
+                   break;
+               } else if (xmlStrEqual(ns->prefix, nsPrefix)) {
+                   if (xmlStrEqual(ns->href, nsName))
+                       return(ns);
+                   prefixOccupied = 1;
+                   break;
+               }
+           }
+           ns = ns->next;
+       } while (ns != NULL);
+    }
+    if (prefixOccupied) {
+       /*
+       * If the ns-prefix is occupied by an other ns-decl on the
+       * result element, then this means:
+       * 1) The desired prefix is shadowed
+       * 2) There's no way around changing the prefix  
+       *
+       * Try a desperate search for an in-scope ns-decl
+       * with a matching ns-name before we use the last option,
+       * which is to recreate the ns-decl with a modified prefix.
+       */
+       ns = xmlSearchNsByHref(target->doc, target, nsName);
+       if (ns != NULL)
+           return(ns);
+
+       /*
+       * Fallback to changing the prefix.
+       */    
+    } else if ((target->parent != NULL) &&
+       (target->parent->type == XML_ELEMENT_NODE))
+    {
+       /*
+       * Try to find a matching ns-decl in the ancestor-axis.
+       *
+       * Check the common case: The parent element of the current
+       * result element is in the same namespace (with an equal ns-prefix).
+       */     
+       if ((target->parent->ns != NULL) &&
+           ((target->parent->ns->prefix != NULL) == (nsPrefix != NULL)))
+       {
+           ns = target->parent->ns;
+           
+           if (nsPrefix == NULL) {
+               if (xmlStrEqual(ns->href, nsName))
+                   return(ns);
+           } else if (xmlStrEqual(ns->prefix, nsPrefix) &&
+               xmlStrEqual(ns->href, nsName))
+           {
+               return(ns);
+           }
+       }
+       /*
+       * Lookup the remaining in-scope namespaces.
+       */    
+       ns = xmlSearchNs(target->doc, target->parent, nsPrefix);
+       if (ns != NULL) {
+           if (xmlStrEqual(ns->href, nsName))
+               return(ns);         
+           /*
+           * Now check for a nasty case: We need to ensure that the new
+           * ns-decl won't shadow a prefix in-use by an existing attribute.
+           * <foo xmlns:a="urn:test:a">
+           *   <bar a:a="val-a">
+           *     <xsl:attribute xmlns:a="urn:test:b" name="a:b">
+           *        val-b</xsl:attribute>
+           *   </bar>
+           * </foo>
+           */
+           if (target->properties) {
+               xmlAttrPtr attr = target->properties;
+               do {
+                   if ((attr->ns) &&
+                       xmlStrEqual(attr->ns->prefix, nsPrefix))
+                   {
+                       /*
+                       * Bad, this prefix is already in use.
+                       * Since we'll change the prefix anyway, try
+                       * a search for a matching ns-decl based on the
+                       * namespace name.
+                       */
+                       ns = xmlSearchNsByHref(target->doc, target, nsName);
+                       if (ns != NULL)
+                           return(ns);
+                       goto declare_new_prefix;
+                   }
+                   attr = attr->next;
+               } while (attr != NULL);
+           }
+       } else {
+           /*
+           * Either no matching ns-prefix was found or the namespace is
+           * shadowed.
+           * Create a new ns-decl on the current result element.
+           *
+           * Hmm, we could also try to reuse an in-scope
+           * namespace with a matching ns-name but a different
+           * ns-prefix.
+           * What has higher priority? 
+           *  1) If keeping the prefix: create a new ns-decl.
+           *  2) If reusal: first lookup ns-names; then fallback
+           *     to creation of a new ns-decl.
+           * REVISIT: this currently uses case 1) although
+           *  the old way was use xmlSearchNsByHref() and to let change
+           *  the prefix.
+           */
+#if 0
+           ns = xmlSearchNsByHref(target->doc, target, nsName);
+           if (ns != NULL)
+               return(ns);
+#endif
+       }
+       /*
+       * Create the ns-decl on the current result element.
+       */
+       ns = xmlNewNs(target, nsName, nsPrefix);
+       /* TODO: check errors */
+       return(ns);
+    } else {
+       /*
+       * This is either the root of the tree or something weird is going on.
+       */
+       ns = xmlNewNs(target, nsName, nsPrefix);
+       /* TODO: Check result */
+       return(ns);
+    }
+
+declare_new_prefix:
+    /*
+    * Fallback: we need to generate a new prefix and declare the namespace
+    * on the result element.
+    */
+    {
+       xmlChar pref[30];
+       int counter = 1;
+               
+       do {
+           snprintf((char *) pref, 30, "%s_%d", nsPrefix, counter++);
+           ns = xmlSearchNs(target->doc, target, BAD_CAST pref);
+           if (counter > 1000) {
+               xsltTransformError(ctxt, NULL, invocNode,
+                   "Internal error in xsltAcquireResultInScopeNs(): "              
+                   "Failed to compute a unique ns-prefix for the "
+                   "generated element");
+               return(NULL);
+           }
+       } while (ns != NULL);
+       ns = xmlNewNs(target, nsName, BAD_CAST pref);
+       /* TODO: Check result */
+       return(ns);
+    }
+    return(NULL);   
+}
+
+/**
+ * xsltGetNamespace:
+ * @ctxt:  a transformation context
+ * @cur:  the input node
+ * @ns:  the namespace
+ * @out:  the output node (or its parent)
+ *
+ * Find a matching (prefix and ns-name) ns-declaration
+ * for the requested @ns->prefix and @ns->href in the result tree.
+ * If none is found then a new ns-declaration will be
+ * added to @resultElem. If, in this case, the given prefix is
+ * already in use, then a ns-declaration with a modified ns-prefix
+ * be we created.
+ *
+ * Called by:
+ *  - xsltCopyPropList() (*not*  anymore)
+ *  - xsltShallowCopyElement()
+ *  - xsltCopyTreeInternal() (*not*  anymore)
+ *  - xsltApplySequenceConstructor() (*not* in the refactored code),
+ *  - xsltElement() (*not* anymore)
+ *
+ * Returns a namespace declaration or NULL in case of
+ *         namespace fixup failures or API or internal errors.
+ */
+xmlNsPtr
+xsltGetNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns,
+                xmlNodePtr out)
+{    
+    
+    if (ns == NULL)
+       return(NULL);
+
+#ifdef XSLT_REFACTORED
+    /*
+    * Namespace exclusion and ns-aliasing is performed at
+    * compilation-time in the refactored code.
+    * Additionally, aliasing is not intended for non Literal
+    * Result Elements.
+    */
+    return(xsltGetSpecialNamespace(ctxt, cur, ns->href, ns->prefix, out));
+#else
+    {
+       xsltStylesheetPtr style;
+       const xmlChar *URI = NULL; /* the replacement URI */
+
+       if ((ctxt == NULL) || (cur == NULL) || (out == NULL))
+           return(NULL);
+
+       style = ctxt->style;
+       while (style != NULL) {
+           if (style->nsAliases != NULL)
+               URI = (const xmlChar *) 
+               xmlHashLookup(style->nsAliases, ns->href);
+           if (URI != NULL)
+               break;
+           
+           style = xsltNextImport(style);
+       }
+       
+       
+       if (URI == UNDEFINED_DEFAULT_NS) {
+           return(xsltGetSpecialNamespace(ctxt, cur, NULL, NULL, out));
+#if 0
+           /*
+           * TODO: Removed, since wrong. If there was no default
+           * namespace in the stylesheet then this must resolve to
+           * the NULL namespace.
+           */
+           xmlNsPtr dflt;          
+           dflt = xmlSearchNs(cur->doc, cur, NULL);
+           if (dflt != NULL)
+               URI = dflt->href;
+           else
+               return NULL;
+#endif
+       } else if (URI == NULL)
+           URI = ns->href;
+
+       return(xsltGetSpecialNamespace(ctxt, cur, URI, ns->prefix, out));
+    }
+#endif
+}
+
+/**
+ * xsltGetPlainNamespace:
+ * @ctxt:  a transformation context
+ * @cur:  the input node
+ * @ns:  the namespace
+ * @out:  the result element
+ *
+ * Obsolete. 
+ * *Not* called by any Libxslt/Libexslt function.
+ * Exaclty the same as xsltGetNamespace(). 
+ *
+ * Returns a namespace declaration or NULL in case of
+ *         namespace fixup failures or API or internal errors.
+ */
+xmlNsPtr
+xsltGetPlainNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur,
+                      xmlNsPtr ns, xmlNodePtr out)
+{    
+    return(xsltGetNamespace(ctxt, cur, ns, out));
+}
+
+/**
+ * xsltCopyNamespaceList:
+ * @ctxt:  a transformation context
+ * @node:  the target node
+ * @cur:  the first namespace
+ *
+ * Do a copy of an namespace list. If @node is non-NULL the
+ * new namespaces are added automatically. This handles namespaces
+ * aliases.
+ * This function is intended only for *internal* use at
+ * transformation-time for copying ns-declarations of Literal
+ * Result Elements.
+ * 
+ * Called by:
+ *   xsltCopyTreeInternal() (transform.c)
+ *   xsltShallowCopyElem() (transform.c)
+ *
+ * REVISIT: This function won't be used in the refactored code.
+ *
+ * Returns: a new xmlNsPtr, or NULL in case of error.
+ */
+xmlNsPtr
+xsltCopyNamespaceList(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                     xmlNsPtr cur) {
+    xmlNsPtr ret = NULL, tmp;
+    xmlNsPtr p = NULL,q;    
+
+    if (cur == NULL)
+       return(NULL);
+    if (cur->type != XML_NAMESPACE_DECL)
+       return(NULL);
+
+    /*
+     * One can add namespaces only on element nodes
+     */
+    if ((node != NULL) && (node->type != XML_ELEMENT_NODE))
+       node = NULL;
+
+    while (cur != NULL) {
+       if (cur->type != XML_NAMESPACE_DECL)
+           break;
+
+       /*
+        * Avoid duplicating namespace declarations in the tree if
+        * a matching declaration is in scope.
+        */
+       if (node != NULL) {
+           if ((node->ns != NULL) &&
+               (xmlStrEqual(node->ns->prefix, cur->prefix)) &&
+               (xmlStrEqual(node->ns->href, cur->href))) {
+               cur = cur->next;
+               continue;
+           }
+           tmp = xmlSearchNs(node->doc, node, cur->prefix);
+           if ((tmp != NULL) && (xmlStrEqual(tmp->href, cur->href))) {
+               cur = cur->next;
+               continue;
+           }
+       }
+#ifdef XSLT_REFACTORED
+       /*
+       * Namespace exclusion and ns-aliasing is performed at
+       * compilation-time in the refactored code.
+       */
+       q = xmlNewNs(node, cur->href, cur->prefix);
+       if (p == NULL) {
+           ret = p = q;
+       } else {
+           p->next = q;
+           p = q;
+       }
+#else
+       /*
+       * TODO: Remove this if the refactored code gets enabled.
+       */
+       if (!xmlStrEqual(cur->href, XSLT_NAMESPACE)) {
+           const xmlChar *URI;
+           /* TODO apply cascading */
+           URI = (const xmlChar *) xmlHashLookup(ctxt->style->nsAliases,
+                                                 cur->href);
+           if (URI == UNDEFINED_DEFAULT_NS)
+               continue;
+           if (URI != NULL) {
+               q = xmlNewNs(node, URI, cur->prefix);
+           } else {
+               q = xmlNewNs(node, cur->href, cur->prefix);
+           }
+           if (p == NULL) {
+               ret = p = q;
+           } else {
+               p->next = q;
+               p = q;
+           }
+       }
+#endif
+       cur = cur->next;
+    }
+    return(ret);
+}
+
+/**
+ * xsltCopyNamespace:
+ * @ctxt:  a transformation context
+ * @elem:  the target element node
+ * @ns:  the namespace node
+ *
+ * Copies a namespace node (declaration). If @elem is not NULL,
+ * then the new namespace will be declared on @elem.
+ *
+ * Returns: a new xmlNsPtr, or NULL in case of an error.
+ */
+xmlNsPtr
+xsltCopyNamespace(xsltTransformContextPtr ctxt, xmlNodePtr elem,
+                 xmlNsPtr ns)
+{    
+    if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
+       return(NULL);
+    /*
+     * One can add namespaces only on element nodes
+     */
+    if ((elem != NULL) && (elem->type != XML_ELEMENT_NODE))
+       return(xmlNewNs(NULL, ns->href, ns->prefix));
+    else
+       return(xmlNewNs(elem, ns->href, ns->prefix));
+}
+
+
+/**
+ * xsltFreeNamespaceAliasHashes:
+ * @style: an XSLT stylesheet
+ *
+ * Free up the memory used by namespaces aliases
+ */
+void
+xsltFreeNamespaceAliasHashes(xsltStylesheetPtr style) {
+    if (style->nsAliases != NULL)
+       xmlHashFree((xmlHashTablePtr) style->nsAliases, NULL);
+    style->nsAliases = NULL;
+}
index 7df37a2..c3433c9 100644 (file)
-/*\r
- * pattern.c: Implemetation of the template match compilation and lookup\r
- *\r
- * Reference:\r
- *   http://www.w3.org/TR/1999/REC-xslt-19991116\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * daniel@veillard.com\r
- */\r
-\r
-/*\r
- * TODO: handle pathological cases like *[*[@a="b"]]\r
- * TODO: detect [number] at compilation, optimize accordingly\r
- */\r
-\r
-#define IN_LIBXSLT\r
-#include "libxslt.h"\r
-\r
-#include <string.h>\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/tree.h>\r
-#include <libxml/valid.h>\r
-#include <libxml/hash.h>\r
-#include <libxml/xmlerror.h>\r
-#include <libxml/parserInternals.h>\r
-#include "xslt.h"\r
-#include "xsltInternals.h"\r
-#include "xsltutils.h"\r
-#include "imports.h"\r
-#include "templates.h"\r
-#include "keys.h"\r
-#include "pattern.h"\r
-#include "documents.h"\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
-#define WITH_XSLT_DEBUG_PATTERN\r
-#endif\r
-\r
-/*\r
- * Types are private:\r
- */\r
-\r
-typedef enum {\r
-    XSLT_OP_END=0,\r
-    XSLT_OP_ROOT,\r
-    XSLT_OP_ELEM,\r
-    XSLT_OP_CHILD,\r
-    XSLT_OP_ATTR,\r
-    XSLT_OP_PARENT,\r
-    XSLT_OP_ANCESTOR,\r
-    XSLT_OP_ID,\r
-    XSLT_OP_KEY,\r
-    XSLT_OP_NS,\r
-    XSLT_OP_ALL,\r
-    XSLT_OP_PI,\r
-    XSLT_OP_COMMENT,\r
-    XSLT_OP_TEXT,\r
-    XSLT_OP_NODE,\r
-    XSLT_OP_PREDICATE\r
-} xsltOp;\r
-\r
-typedef struct _xsltStepState xsltStepState;\r
-typedef xsltStepState *xsltStepStatePtr;\r
-struct _xsltStepState {\r
-    int step;\r
-    xmlNodePtr node;\r
-};\r
-\r
-typedef struct _xsltStepStates xsltStepStates;\r
-typedef xsltStepStates *xsltStepStatesPtr;\r
-struct _xsltStepStates {\r
-    int nbstates;\r
-    int maxstates;\r
-    xsltStepStatePtr states;\r
-};\r
-\r
-typedef struct _xsltStepOp xsltStepOp;\r
-typedef xsltStepOp *xsltStepOpPtr;\r
-struct _xsltStepOp {\r
-    xsltOp op;\r
-    xmlChar *value;\r
-    xmlChar *value2;\r
-    xmlChar *value3;\r
-    xmlXPathCompExprPtr comp;\r
-    /*\r
-     * Optimisations for count\r
-     */\r
-    int        previousExtra;\r
-    int        indexExtra;\r
-    int        lenExtra;\r
-};\r
-\r
-struct _xsltCompMatch {\r
-    struct _xsltCompMatch *next; /* siblings in the name hash */\r
-    float priority;              /* the priority */\r
-    const xmlChar *pattern;       /* the pattern */\r
-    const xmlChar *mode;         /* the mode */\r
-    const xmlChar *modeURI;      /* the mode URI */\r
-    xsltTemplatePtr template;    /* the associated template */\r
-\r
-    int direct;\r
-    /* TODO fix the statically allocated size steps[] */\r
-    int nbStep;\r
-    int maxStep;\r
-    xmlNsPtr *nsList;          /* the namespaces in scope */\r
-    int nsNr;                  /* the number of namespaces in scope */\r
-    xsltStepOp steps[40];        /* ops for computation */\r
-};\r
-\r
-typedef struct _xsltParserContext xsltParserContext;\r
-typedef xsltParserContext *xsltParserContextPtr;\r
-struct _xsltParserContext {\r
-    xsltStylesheetPtr style;           /* the stylesheet */\r
-    xsltTransformContextPtr ctxt;      /* the transformation or NULL */\r
-    const xmlChar *cur;                        /* the current char being parsed */\r
-    const xmlChar *base;               /* the full expression */\r
-    xmlDocPtr      doc;                        /* the source document */\r
-    xmlNodePtr    elem;                        /* the source element */\r
-    int error;                         /* error code */\r
-    xsltCompMatchPtr comp;             /* the result */\r
-};\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Type functions                                  *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltNewCompMatch:\r
- *\r
- * Create a new XSLT CompMatch\r
- *\r
- * Returns the newly allocated xsltCompMatchPtr or NULL in case of error\r
- */\r
-static xsltCompMatchPtr\r
-xsltNewCompMatch(void) {\r
-    xsltCompMatchPtr cur;\r
-\r
-    cur = (xsltCompMatchPtr) xmlMalloc(sizeof(xsltCompMatch));\r
-    if (cur == NULL) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-               "xsltNewCompMatch : malloc failed\n");\r
-       return(NULL);\r
-    }\r
-    memset(cur, 0, sizeof(xsltCompMatch));\r
-    cur->maxStep = 40;\r
-    cur->nsNr = 0;\r
-    cur->nsList = NULL;\r
-    cur->direct = 0;\r
-    return(cur);\r
-}\r
-\r
-/**\r
- * xsltFreeCompMatch:\r
- * @comp:  an XSLT comp\r
- *\r
- * Free up the memory allocated by @comp\r
- */\r
-static void\r
-xsltFreeCompMatch(xsltCompMatchPtr comp) {\r
-    xsltStepOpPtr op;\r
-    int i;\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    if (comp->pattern != NULL)\r
-       xmlFree((xmlChar *)comp->pattern);\r
-    if (comp->nsList != NULL)\r
-       xmlFree(comp->nsList);\r
-    for (i = 0;i < comp->nbStep;i++) {\r
-       op = &comp->steps[i];\r
-       if (op->value != NULL)\r
-           xmlFree(op->value);\r
-       if (op->value2 != NULL)\r
-           xmlFree(op->value2);\r
-       if (op->value3 != NULL)\r
-           xmlFree(op->value3);\r
-       if (op->comp != NULL)\r
-           xmlXPathFreeCompExpr(op->comp);\r
-    }\r
-    memset(comp, -1, sizeof(xsltCompMatch));\r
-    xmlFree(comp);\r
-}\r
-\r
-/**\r
- * xsltFreeCompMatchList:\r
- * @comp:  an XSLT comp list\r
- *\r
- * Free up the memory allocated by all the elements of @comp\r
- */\r
-void\r
-xsltFreeCompMatchList(xsltCompMatchPtr comp) {\r
-    xsltCompMatchPtr cur;\r
-\r
-    while (comp != NULL) {\r
-       cur = comp;\r
-       comp = comp->next;\r
-       xsltFreeCompMatch(cur);\r
-    }\r
-}\r
-\r
-/**\r
- * xsltNormalizeCompSteps:\r
- * @payload: pointer to template hash table entry\r
- * @data: pointer to the stylesheet\r
- * @name: template match name\r
- *\r
- * This is a hashtable scanner function to normalize the compiled\r
- * steps of an imported stylesheet.\r
- */\r
-void xsltNormalizeCompSteps(void *payload,\r
-        void *data, const xmlChar *name ATTRIBUTE_UNUSED) {\r
-    xsltCompMatchPtr comp = payload;\r
-    xsltStylesheetPtr style = data;\r
-    int ix;\r
-\r
-    for (ix = 0; ix < comp->nbStep; ix++) {\r
-        comp->steps[ix].previousExtra += style->extrasNr;\r
-        comp->steps[ix].indexExtra += style->extrasNr;\r
-        comp->steps[ix].lenExtra += style->extrasNr;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltNewParserContext:\r
- * @style:  the stylesheet\r
- * @ctxt:  the transformation context, if done at run-time\r
- *\r
- * Create a new XSLT ParserContext\r
- *\r
- * Returns the newly allocated xsltParserContextPtr or NULL in case of error\r
- */\r
-static xsltParserContextPtr\r
-xsltNewParserContext(xsltStylesheetPtr style, xsltTransformContextPtr ctxt) {\r
-    xsltParserContextPtr cur;\r
-\r
-    cur = (xsltParserContextPtr) xmlMalloc(sizeof(xsltParserContext));\r
-    if (cur == NULL) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-               "xsltNewParserContext : malloc failed\n");\r
-       return(NULL);\r
-    }\r
-    memset(cur, 0, sizeof(xsltParserContext));\r
-    cur->style = style;\r
-    cur->ctxt = ctxt;\r
-    return(cur);\r
-}\r
-\r
-/**\r
- * xsltFreeParserContext:\r
- * @ctxt:  an XSLT parser context\r
- *\r
- * Free up the memory allocated by @ctxt\r
- */\r
-static void\r
-xsltFreeParserContext(xsltParserContextPtr ctxt) {\r
-    if (ctxt == NULL)\r
-       return;\r
-    memset(ctxt, -1, sizeof(xsltParserContext));\r
-    xmlFree(ctxt);\r
-}\r
-\r
-/**\r
- * xsltCompMatchAdd:\r
- * @comp:  the compiled match expression\r
- * @op:  an op\r
- * @value:  the first value\r
- * @value2:  the second value\r
- * @novar:  flag to set XML_XPATH_NOVAR\r
- *\r
- * Add an step to an XSLT Compiled Match\r
- *\r
- * Returns -1 in case of failure, 0 otherwise.\r
- */\r
-static int\r
-xsltCompMatchAdd(xsltParserContextPtr ctxt, xsltCompMatchPtr comp,\r
-                 xsltOp op, xmlChar * value, xmlChar * value2, int novar)\r
-{\r
-    if (comp->nbStep >= 40) {\r
-        xsltTransformError(NULL, NULL, NULL,\r
-                         "xsltCompMatchAdd: overflow\n");\r
-        return (-1);\r
-    }\r
-    comp->steps[comp->nbStep].op = op;\r
-    comp->steps[comp->nbStep].value = value;\r
-    comp->steps[comp->nbStep].value2 = value2;\r
-    if (ctxt->ctxt != NULL) {\r
-       comp->steps[comp->nbStep].previousExtra =\r
-           xsltAllocateExtraCtxt(ctxt->ctxt);\r
-       comp->steps[comp->nbStep].indexExtra =\r
-           xsltAllocateExtraCtxt(ctxt->ctxt);\r
-       comp->steps[comp->nbStep].lenExtra =\r
-           xsltAllocateExtraCtxt(ctxt->ctxt);\r
-    } else {\r
-       comp->steps[comp->nbStep].previousExtra =\r
-           xsltAllocateExtra(ctxt->style);\r
-       comp->steps[comp->nbStep].indexExtra =\r
-           xsltAllocateExtra(ctxt->style);\r
-       comp->steps[comp->nbStep].lenExtra =\r
-           xsltAllocateExtra(ctxt->style);\r
-    }\r
-    if (op == XSLT_OP_PREDICATE) {\r
-       xmlXPathContextPtr xctxt;\r
-\r
-       if (ctxt->style != NULL)\r
-           xctxt = xmlXPathNewContext(ctxt->style->doc);\r
-       else\r
-           xctxt = xmlXPathNewContext(NULL);\r
-#ifdef XML_XPATH_NOVAR\r
-       if (novar != 0)\r
-           xctxt->flags = XML_XPATH_NOVAR;\r
-#endif\r
-       if (ctxt->style != NULL)\r
-           xctxt->dict = ctxt->style->dict;\r
-       comp->steps[comp->nbStep].comp = xmlXPathCtxtCompile(xctxt, value);\r
-       xmlXPathFreeContext(xctxt);\r
-       if (comp->steps[comp->nbStep].comp == NULL) {\r
-           xsltTransformError(NULL, ctxt->style, ctxt->elem,\r
-                   "Failed to compile predicate\n");\r
-           if (ctxt->style != NULL)\r
-               ctxt->style->errors++;\r
-       }\r
-    }\r
-    comp->nbStep++;\r
-    return (0);\r
-}\r
-\r
-/**\r
- * xsltSwapTopCompMatch:\r
- * @comp:  the compiled match expression\r
- *\r
- * reverse the two top steps.\r
- */\r
-static void\r
-xsltSwapTopCompMatch(xsltCompMatchPtr comp) {\r
-    int i;\r
-    int j = comp->nbStep - 1;\r
-\r
-    if (j > 0) {\r
-       register xmlChar *tmp;\r
-       register xsltOp op;\r
-       register xmlXPathCompExprPtr expr; \r
-       i = j - 1;\r
-       tmp = comp->steps[i].value;\r
-       comp->steps[i].value = comp->steps[j].value;\r
-       comp->steps[j].value = tmp;\r
-       tmp = comp->steps[i].value2;\r
-       comp->steps[i].value2 = comp->steps[j].value2;\r
-       comp->steps[j].value2 = tmp;\r
-       op = comp->steps[i].op;\r
-       comp->steps[i].op = comp->steps[j].op;\r
-       comp->steps[j].op = op;\r
-       expr = comp->steps[i].comp;\r
-       comp->steps[i].comp = comp->steps[j].comp;\r
-       comp->steps[j].comp = expr;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltReverseCompMatch:\r
- * @comp:  the compiled match expression\r
- *\r
- * reverse all the stack of expressions\r
- */\r
-static void\r
-xsltReverseCompMatch(xsltCompMatchPtr comp) {\r
-    int i = 0;\r
-    int j = comp->nbStep - 1;\r
-\r
-    while (j > i) {\r
-       register xmlChar *tmp;\r
-       register xsltOp op;\r
-       register xmlXPathCompExprPtr expr; \r
-       tmp = comp->steps[i].value;\r
-       comp->steps[i].value = comp->steps[j].value;\r
-       comp->steps[j].value = tmp;\r
-       tmp = comp->steps[i].value2;\r
-       comp->steps[i].value2 = comp->steps[j].value2;\r
-       comp->steps[j].value2 = tmp;\r
-       op = comp->steps[i].op;\r
-       comp->steps[i].op = comp->steps[j].op;\r
-       comp->steps[j].op = op;\r
-       expr = comp->steps[i].comp;\r
-       comp->steps[i].comp = comp->steps[j].comp;\r
-       comp->steps[j].comp = expr;\r
-       j--;\r
-       i++;\r
-    }\r
-    comp->steps[comp->nbStep++].op = XSLT_OP_END;\r
-    /*\r
-     * detect consecutive XSLT_OP_PREDICATE indicating a direct\r
-     * matching should be done.\r
-     */\r
-    for (i = 0;i < comp->nbStep - 1;i++) {\r
-        if ((comp->steps[i].op == XSLT_OP_PREDICATE) &&\r
-           (comp->steps[i + 1].op == XSLT_OP_PREDICATE)) {\r
-\r
-           comp->direct = 1;\r
-           if (comp->pattern[0] != '/') {\r
-               xmlChar *query;\r
-\r
-               query = xmlStrdup((const xmlChar *)"//");\r
-               query = xmlStrcat(query, comp->pattern);\r
-\r
-               xmlFree((xmlChar *) comp->pattern);\r
-               comp->pattern = query;\r
-           }\r
-           break;\r
-       }\r
-    }\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             The interpreter for the precompiled patterns            *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-static int\r
-xsltPatPushState(xsltStepStates *states, int step, xmlNodePtr node) {\r
-    if ((states->states == NULL) || (states->maxstates <= 0)) {\r
-        states->maxstates = 4;\r
-       states->nbstates = 0;\r
-       states->states = xmlMalloc(4 * sizeof(xsltStepState));\r
-    }\r
-    else if (states->maxstates <= states->nbstates) {\r
-        xsltStepState *tmp;\r
-\r
-       tmp = (xsltStepStatePtr) xmlRealloc(states->states,\r
-                              2 * states->maxstates * sizeof(xsltStepState));\r
-       if (tmp == NULL)\r
-           return(-1);\r
-       states->states = tmp;\r
-       states->maxstates *= 2;\r
-    }\r
-    states->states[states->nbstates].step = step;\r
-    states->states[states->nbstates++].node = node;\r
-#if 0\r
-    fprintf(stderr, "Push: %d, %s\n", step, node->name);\r
-#endif\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltTestCompMatchDirect:\r
- * @ctxt:  a XSLT process context\r
- * @comp: the precompiled pattern\r
- * @node: a node\r
- *\r
- * Test whether the node matches the pattern, do a direct evalutation\r
- * and not a step by step evaluation.\r
- *\r
- * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure\r
- */\r
-static int\r
-xsltTestCompMatchDirect(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,\r
-                       xmlNodePtr node) {\r
-    xsltStepOpPtr sel = NULL;\r
-    xmlDocPtr prevdoc;\r
-    xmlDocPtr doc;\r
-    xmlXPathObjectPtr list;\r
-    int ix, j;\r
-    int nocache = 0;\r
-    int isRVT;\r
-\r
-    doc = node->doc;\r
-    if (XSLT_IS_RES_TREE_FRAG(doc))\r
-       isRVT = 1;\r
-    else\r
-       isRVT = 0;\r
-    sel = &comp->steps[0]; /* store extra in first step arbitrarily */\r
-\r
-    prevdoc = (xmlDocPtr)\r
-       XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);\r
-    ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);\r
-    list = (xmlXPathObjectPtr)\r
-       XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra);\r
-    \r
-    if ((list == NULL) || (prevdoc != doc)) {\r
-       xmlXPathObjectPtr newlist;\r
-       xmlNodePtr parent = node->parent;\r
-       xmlDocPtr olddoc;\r
-       xmlNodePtr oldnode;\r
-\r
-       oldnode = ctxt->xpathCtxt->node;\r
-       olddoc = ctxt->xpathCtxt->doc;\r
-       ctxt->xpathCtxt->node = node;\r
-       ctxt->xpathCtxt->doc = doc;\r
-       newlist = xmlXPathEval(comp->pattern, ctxt->xpathCtxt);\r
-       ctxt->xpathCtxt->node = oldnode;\r
-       ctxt->xpathCtxt->doc = olddoc;\r
-       if (newlist == NULL)\r
-           return(-1);\r
-       if (newlist->type != XPATH_NODESET) {\r
-           xmlXPathFreeObject(newlist);\r
-           return(-1);\r
-       }\r
-       ix = 0;\r
-\r
-       if ((parent == NULL) || (node->doc == NULL) || isRVT)\r
-           nocache = 1;\r
-       \r
-       if (nocache == 0) {\r
-           if (list != NULL)\r
-               xmlXPathFreeObject(list);\r
-           list = newlist;\r
-\r
-           XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) =\r
-               (void *) list;\r
-           XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =\r
-               (void *) doc;\r
-           XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =\r
-               0;\r
-           XSLT_RUNTIME_EXTRA_FREE(ctxt, sel->lenExtra) =\r
-               (xmlFreeFunc) xmlXPathFreeObject;\r
-       } else\r
-           list = newlist;\r
-    }\r
-    if ((list->nodesetval == NULL) ||\r
-       (list->nodesetval->nodeNr <= 0)) {\r
-       if (nocache == 1)\r
-           xmlXPathFreeObject(list);\r
-       return(0);\r
-    }\r
-    /* TODO: store the index and use it for the scan */\r
-    if (ix == 0) {\r
-       for (j = 0;j < list->nodesetval->nodeNr;j++) {\r
-           if (list->nodesetval->nodeTab[j] == node) {\r
-               if (nocache == 1)\r
-                   xmlXPathFreeObject(list);\r
-               return(1);\r
-           }\r
-       }\r
-    } else {\r
-    }\r
-    if (nocache == 1)\r
-       xmlXPathFreeObject(list);\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltTestCompMatch:\r
- * @ctxt:  a XSLT process context\r
- * @comp: the precompiled pattern\r
- * @node: a node\r
- * @mode:  the mode name or NULL\r
- * @modeURI:  the mode URI or NULL\r
- *\r
- * Test whether the node matches the pattern\r
- *\r
- * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure\r
- */\r
-static int\r
-xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,\r
-                 xmlNodePtr node, const xmlChar *mode,\r
-                 const xmlChar *modeURI) {\r
-    int i;\r
-    xsltStepOpPtr step, sel = NULL;\r
-    xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */\r
-\r
-    if ((comp == NULL) || (node == NULL) || (ctxt == NULL)) {\r
-       xsltTransformError(ctxt, NULL, node,\r
-               "xsltTestCompMatch: null arg\n");\r
-        return(-1);\r
-    }\r
-    if (mode != NULL) {\r
-       if (comp->mode == NULL)\r
-           return(0);\r
-       /*\r
-        * both mode strings must be interned on the stylesheet dictionary\r
-        */\r
-       if (comp->mode != mode)\r
-           return(0);\r
-    } else {\r
-       if (comp->mode != NULL)\r
-           return(0);\r
-    }\r
-    if (modeURI != NULL) {\r
-       if (comp->modeURI == NULL)\r
-           return(0);\r
-       /*\r
-        * both modeURI strings must be interned on the stylesheet dictionary\r
-        */\r
-       if (comp->modeURI != modeURI)\r
-           return(0);\r
-    } else {\r
-       if (comp->modeURI != NULL)\r
-           return(0);\r
-    }\r
-\r
-    i = 0;\r
-restart:\r
-    for (;i < comp->nbStep;i++) {\r
-       step = &comp->steps[i];\r
-       if (step->op != XSLT_OP_PREDICATE)\r
-           sel = step;\r
-       switch (step->op) {\r
-            case XSLT_OP_END:\r
-               goto found;\r
-            case XSLT_OP_ROOT:\r
-               if ((node->type == XML_DOCUMENT_NODE) ||\r
-#ifdef LIBXML_DOCB_ENABLED\r
-                   (node->type == XML_DOCB_DOCUMENT_NODE) ||\r
-#endif\r
-                   (node->type == XML_HTML_DOCUMENT_NODE))\r
-                   continue;\r
-               if ((node->type == XML_ELEMENT_NODE) && (node->name[0] == ' '))\r
-                   continue;\r
-               goto rollback;\r
-            case XSLT_OP_ELEM:\r
-               if (node->type != XML_ELEMENT_NODE)\r
-                   goto rollback;\r
-               if (step->value == NULL)\r
-                   continue;\r
-               if (step->value[0] != node->name[0])\r
-                   goto rollback;\r
-               if (!xmlStrEqual(step->value, node->name))\r
-                   goto rollback;\r
-\r
-               /* Namespace test */\r
-               if (node->ns == NULL) {\r
-                   if (step->value2 != NULL)\r
-                       goto rollback;\r
-               } else if (node->ns->href != NULL) {\r
-                   if (step->value2 == NULL)\r
-                       goto rollback;\r
-                   if (!xmlStrEqual(step->value2, node->ns->href))\r
-                       goto rollback;\r
-               }\r
-               continue;\r
-            case XSLT_OP_CHILD: {\r
-               xmlNodePtr lst;\r
-\r
-               if ((node->type != XML_ELEMENT_NODE) &&\r
-                   (node->type != XML_DOCUMENT_NODE) &&\r
-#ifdef LIBXML_DOCB_ENABLED\r
-                   (node->type != XML_DOCB_DOCUMENT_NODE) &&\r
-#endif\r
-                   (node->type != XML_HTML_DOCUMENT_NODE))\r
-                   goto rollback;\r
-\r
-               lst = node->children;\r
-\r
-               if (step->value != NULL) {\r
-                   while (lst != NULL) {\r
-                       if ((lst->type == XML_ELEMENT_NODE) &&\r
-                           (step->value[0] == lst->name[0]) &&\r
-                           (xmlStrEqual(step->value, lst->name)))\r
-                           break;\r
-                       lst = lst->next;\r
-                   }\r
-                   if (lst != NULL)\r
-                       continue;\r
-               }\r
-               goto rollback;\r
-           }\r
-            case XSLT_OP_ATTR:\r
-               if (node->type != XML_ATTRIBUTE_NODE)\r
-                   goto rollback;\r
-               if (step->value != NULL) {\r
-                   if (step->value[0] != node->name[0])\r
-                       goto rollback;\r
-                   if (!xmlStrEqual(step->value, node->name))\r
-                       goto rollback;\r
-               }\r
-               /* Namespace test */\r
-               if (node->ns == NULL) {\r
-                   if (step->value2 != NULL)\r
-                       goto rollback;\r
-               } else if (step->value2 != NULL) {\r
-                   if (!xmlStrEqual(step->value2, node->ns->href))\r
-                       goto rollback;\r
-               }\r
-               continue;\r
-            case XSLT_OP_PARENT:\r
-               if ((node->type == XML_DOCUMENT_NODE) ||\r
-                   (node->type == XML_HTML_DOCUMENT_NODE) ||\r
-#ifdef LIBXML_DOCB_ENABLED\r
-                   (node->type == XML_DOCB_DOCUMENT_NODE) ||\r
-#endif\r
-                   (node->type == XML_NAMESPACE_DECL))\r
-                   goto rollback;\r
-               node = node->parent;\r
-               if (node == NULL)\r
-                   goto rollback;\r
-               if (step->value == NULL)\r
-                   continue;\r
-               if (step->value[0] != node->name[0])\r
-                   goto rollback;\r
-               if (!xmlStrEqual(step->value, node->name))\r
-                   goto rollback;\r
-               /* Namespace test */\r
-               if (node->ns == NULL) {\r
-                   if (step->value2 != NULL)\r
-                       goto rollback;\r
-               } else if (node->ns->href != NULL) {\r
-                   if (step->value2 == NULL)\r
-                       goto rollback;\r
-                   if (!xmlStrEqual(step->value2, node->ns->href))\r
-                       goto rollback;\r
-               }\r
-               continue;\r
-            case XSLT_OP_ANCESTOR:\r
-               /* TODO: implement coalescing of ANCESTOR/NODE ops */\r
-               if (step->value == NULL) {\r
-                   step = &comp->steps[i+1];\r
-                   if (step->op == XSLT_OP_ROOT)\r
-                       goto found;\r
-                   /* added NS, ID and KEY as a result of bug 168208 */\r
-                   if ((step->op != XSLT_OP_ELEM) && \r
-                       (step->op != XSLT_OP_ALL) && \r
-                       (step->op != XSLT_OP_NS) &&\r
-                       (step->op != XSLT_OP_ID) &&\r
-                       (step->op != XSLT_OP_KEY))\r
-                       goto rollback;\r
-               }\r
-               if (node == NULL)\r
-                   goto rollback;\r
-               if ((node->type == XML_DOCUMENT_NODE) ||\r
-                   (node->type == XML_HTML_DOCUMENT_NODE) ||\r
-#ifdef LIBXML_DOCB_ENABLED\r
-                   (node->type == XML_DOCB_DOCUMENT_NODE) ||\r
-#endif\r
-                   (node->type == XML_NAMESPACE_DECL))\r
-                   goto rollback;\r
-               node = node->parent;\r
-               if ((step->op != XSLT_OP_ELEM) && step->op != XSLT_OP_ALL) {\r
-                   xsltPatPushState(&states, i, node);\r
-                   continue;\r
-               }\r
-               i++;\r
-               if (step->value == NULL) {\r
-                   xsltPatPushState(&states, i - 1, node);\r
-                   continue;\r
-               }\r
-               while (node != NULL) {\r
-                   if ((node->type == XML_ELEMENT_NODE) &&\r
-                       (step->value[0] == node->name[0]) &&\r
-                       (xmlStrEqual(step->value, node->name))) {\r
-                       /* Namespace test */\r
-                       if (node->ns == NULL) {\r
-                           if (step->value2 == NULL)\r
-                               break;\r
-                       } else if (node->ns->href != NULL) {\r
-                           if ((step->value2 != NULL) &&\r
-                               (xmlStrEqual(step->value2, node->ns->href)))\r
-                               break;\r
-                       }\r
-                   }\r
-                   node = node->parent;\r
-               }\r
-               if (node == NULL)\r
-                   goto rollback;\r
-               xsltPatPushState(&states, i - 1, node);\r
-               continue;\r
-            case XSLT_OP_ID: {\r
-               /* TODO Handle IDs decently, must be done differently */\r
-               xmlAttrPtr id;\r
-\r
-               if (node->type != XML_ELEMENT_NODE)\r
-                   goto rollback;\r
-\r
-               id = xmlGetID(node->doc, step->value);\r
-               if ((id == NULL) || (id->parent != node))\r
-                   goto rollback;\r
-               break;\r
-           }\r
-            case XSLT_OP_KEY: {\r
-               xmlNodeSetPtr list;\r
-               int indx;\r
-\r
-               list = xsltGetKey(ctxt, step->value,\r
-                                 step->value3, step->value2);\r
-               if (list == NULL)\r
-                   goto rollback;\r
-               for (indx = 0;indx < list->nodeNr;indx++)\r
-                   if (list->nodeTab[indx] == node)\r
-                       break;\r
-               if (indx >= list->nodeNr)\r
-                   goto rollback;\r
-               break;\r
-           }\r
-            case XSLT_OP_NS:\r
-               if (node->type != XML_ELEMENT_NODE)\r
-                   goto rollback;\r
-               if (node->ns == NULL) {\r
-                   if (step->value != NULL)\r
-                       goto rollback;\r
-               } else if (node->ns->href != NULL) {\r
-                   if (step->value == NULL)\r
-                       goto rollback;\r
-                   if (!xmlStrEqual(step->value, node->ns->href))\r
-                       goto rollback;\r
-               }\r
-               break;\r
-            case XSLT_OP_ALL:\r
-               if (node->type != XML_ELEMENT_NODE)\r
-                   goto rollback;\r
-               break;\r
-           case XSLT_OP_PREDICATE: {\r
-               xmlNodePtr oldNode;\r
-               xmlDocPtr doc;\r
-               int oldCS, oldCP;\r
-               int pos = 0, len = 0;\r
-               int isRVT;\r
-\r
-               /*\r
-                * when there is cascading XSLT_OP_PREDICATE, then use a\r
-                * direct computation approach. It's not done directly\r
-                * at the beginning of the routine to filter out as much\r
-                * as possible this costly computation.\r
-                */\r
-               if (comp->direct) {\r
-                   if (states.states != NULL) {\r
-                       /* Free the rollback states */\r
-                       xmlFree(states.states);\r
-                   }\r
-                   return(xsltTestCompMatchDirect(ctxt, comp, node));\r
-               }\r
-\r
-               doc = node->doc;\r
-               if (XSLT_IS_RES_TREE_FRAG(doc))\r
-                   isRVT = 1;\r
-               else\r
-                   isRVT = 0;\r
-\r
-               /*\r
-                * Depending on the last selection, one may need to\r
-                * recompute contextSize and proximityPosition.\r
-                */\r
-               oldCS = ctxt->xpathCtxt->contextSize;\r
-               oldCP = ctxt->xpathCtxt->proximityPosition;\r
-               if ((sel != NULL) &&\r
-                   (sel->op == XSLT_OP_ELEM) &&\r
-                   (sel->value != NULL) &&\r
-                   (node->type == XML_ELEMENT_NODE) &&\r
-                   (node->parent != NULL)) {\r
-                   xmlNodePtr previous;\r
-                   int ix, nocache = 0;\r
-\r
-                   previous = (xmlNodePtr)\r
-                       XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);\r
-                   ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);\r
-                   if ((previous != NULL) &&\r
-                       (previous->parent == node->parent)) {\r
-                       /*\r
-                        * just walk back to adjust the index\r
-                        */\r
-                       int indx = 0;\r
-                       xmlNodePtr sibling = node;\r
-\r
-                       while (sibling != NULL) {\r
-                           if (sibling == previous)\r
-                               break;\r
-                           if ((previous->type == XML_ELEMENT_NODE) &&\r
-                               (previous->name != NULL) &&\r
-                               (sibling->name != NULL) &&\r
-                               (previous->name[0] == sibling->name[0]) &&\r
-                               (xmlStrEqual(previous->name, sibling->name)))\r
-                           {\r
-                               if ((sel->value2 == NULL) ||\r
-                                   ((sibling->ns != NULL) &&\r
-                                    (xmlStrEqual(sel->value2,\r
-                                                 sibling->ns->href))))\r
-                                   indx++;\r
-                           }\r
-                           sibling = sibling->prev;\r
-                       }\r
-                       if (sibling == NULL) {\r
-                           /* hum going backward in document order ... */\r
-                           indx = 0;\r
-                           sibling = node;\r
-                           while (sibling != NULL) {\r
-                               if (sibling == previous)\r
-                                   break;\r
-                               if ((previous->type == XML_ELEMENT_NODE) &&\r
-                                   (previous->name != NULL) &&\r
-                                   (sibling->name != NULL) &&\r
-                                   (previous->name[0] == sibling->name[0]) &&\r
-                                   (xmlStrEqual(previous->name, sibling->name)))\r
-                               {\r
-                                   if ((sel->value2 == NULL) ||\r
-                                       ((sibling->ns != NULL) &&\r
-                                       (xmlStrEqual(sel->value2,\r
-                                       sibling->ns->href))))\r
-                                   {\r
-                                       indx--;\r
-                                   }\r
-                               }\r
-                               sibling = sibling->next;\r
-                           }\r
-                       }\r
-                       if (sibling != NULL) {\r
-                           pos = ix + indx;\r
-                           /*\r
-                            * If the node is in a Value Tree we need to\r
-                            * save len, but cannot cache the node!\r
-                            * (bugs 153137 and 158840)\r
-                            */\r
-                           if (node->doc != NULL) {\r
-                               len = XSLT_RUNTIME_EXTRA(ctxt,\r
-                                       sel->lenExtra, ival);\r
-                               if (!isRVT) {\r
-                                   XSLT_RUNTIME_EXTRA(ctxt,\r
-                                       sel->previousExtra, ptr) = node;\r
-                                   XSLT_RUNTIME_EXTRA(ctxt,\r
-                                       sel->indexExtra, ival) = pos;\r
-                               }\r
-                           }\r
-                           ix = pos;\r
-                       } else\r
-                           pos = 0;\r
-                   } else {\r
-                       /*\r
-                        * recompute the index\r
-                        */\r
-                       xmlNodePtr siblings = node->parent->children;\r
-                       xmlNodePtr parent = node->parent;\r
-\r
-                       while (siblings != NULL) {\r
-                           if (siblings->type == XML_ELEMENT_NODE) {\r
-                               if (siblings == node) {\r
-                                   len++;\r
-                                   pos = len;\r
-                               } else if ((node->name != NULL) &&\r
-                                          (siblings->name != NULL) &&\r
-                                   (node->name[0] == siblings->name[0]) &&\r
-                                   (xmlStrEqual(node->name, siblings->name))) {\r
-                                   if ((sel->value2 == NULL) ||\r
-                                       ((siblings->ns != NULL) &&\r
-                                        (xmlStrEqual(sel->value2,\r
-                                                     siblings->ns->href))))\r
-                                       len++;\r
-                               }\r
-                           }\r
-                           siblings = siblings->next;\r
-                       }\r
-                       if ((parent == NULL) || (node->doc == NULL))\r
-                           nocache = 1;\r
-                       else {\r
-                           while (parent->parent != NULL)\r
-                               parent = parent->parent;\r
-                           if (((parent->type != XML_DOCUMENT_NODE) &&\r
-                                (parent->type != XML_HTML_DOCUMENT_NODE)) ||\r
-                                (parent != (xmlNodePtr) node->doc))\r
-                               nocache = 1;\r
-                       }\r
-                   }\r
-                   if (pos != 0) {\r
-                       ctxt->xpathCtxt->contextSize = len;\r
-                       ctxt->xpathCtxt->proximityPosition = pos;\r
-                       /*\r
-                        * If the node is in a Value Tree we cannot\r
-                        * cache it !\r
-                        */\r
-                       if ((!isRVT) && (node->doc != NULL) &&\r
-                           (nocache == 0)) {\r
-                           XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =\r
-                               node;\r
-                           XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =\r
-                               pos;\r
-                           XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) =\r
-                               len;\r
-                       }\r
-                   }\r
-               } else if ((sel != NULL) && (sel->op == XSLT_OP_ALL) &&\r
-                          (node->type == XML_ELEMENT_NODE)) {\r
-                   xmlNodePtr previous;\r
-                   int ix, nocache = 0;\r
-\r
-                   previous = (xmlNodePtr)\r
-                       XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);\r
-                   ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);\r
-                   if ((previous != NULL) &&\r
-                       (previous->parent == node->parent)) {\r
-                       /*\r
-                        * just walk back to adjust the index\r
-                        */\r
-                       int indx = 0;\r
-                       xmlNodePtr sibling = node;\r
-\r
-                       while (sibling != NULL) {\r
-                           if (sibling == previous)\r
-                               break;\r
-                           if (sibling->type == XML_ELEMENT_NODE)\r
-                               indx++;\r
-                           sibling = sibling->prev;\r
-                       }\r
-                       if (sibling == NULL) {\r
-                           /* hum going backward in document order ... */\r
-                           indx = 0;\r
-                           sibling = node;\r
-                           while (sibling != NULL) {\r
-                               if (sibling == previous)\r
-                                   break;\r
-                               if (sibling->type == XML_ELEMENT_NODE)\r
-                                   indx--;\r
-                               sibling = sibling->next;\r
-                           }\r
-                       }\r
-                       if (sibling != NULL) {\r
-                           pos = ix + indx;\r
-                           /*\r
-                            * If the node is in a Value Tree we cannot\r
-                            * cache it !\r
-                            */\r
-                           if ((node->doc != NULL) && !isRVT) {\r
-                               len = XSLT_RUNTIME_EXTRA(ctxt,\r
-                                       sel->lenExtra, ival);\r
-                               XSLT_RUNTIME_EXTRA(ctxt,\r
-                                       sel->previousExtra, ptr) = node;\r
-                               XSLT_RUNTIME_EXTRA(ctxt,\r
-                                       sel->indexExtra, ival) = pos;\r
-                           }\r
-                       } else\r
-                           pos = 0;\r
-                   } else {\r
-                       /*\r
-                        * recompute the index\r
-                        */\r
-                       xmlNodePtr siblings = node->parent->children;\r
-                       xmlNodePtr parent = node->parent;\r
-\r
-                       while (siblings != NULL) {\r
-                           if (siblings->type == XML_ELEMENT_NODE) {\r
-                               len++;\r
-                               if (siblings == node) {\r
-                                   pos = len;\r
-                               }\r
-                           }\r
-                           siblings = siblings->next;\r
-                       }\r
-                       if ((parent == NULL) || (node->doc == NULL))\r
-                           nocache = 1;\r
-                       else {\r
-                           while (parent->parent != NULL)\r
-                               parent = parent->parent;\r
-                           if (((parent->type != XML_DOCUMENT_NODE) &&\r
-                                (parent->type != XML_HTML_DOCUMENT_NODE)) ||\r
-                                (parent != (xmlNodePtr) node->doc))\r
-                               nocache = 1;\r
-                       }\r
-                   }\r
-                   if (pos != 0) {\r
-                       ctxt->xpathCtxt->contextSize = len;\r
-                       ctxt->xpathCtxt->proximityPosition = pos;\r
-                       /*\r
-                        * If the node is in a Value Tree we cannot\r
-                        * cache it !\r
-                        */\r
-                       if ((node->doc != NULL) && (nocache == 0) && !isRVT) {\r
-                           XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =\r
-                               node;\r
-                           XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =\r
-                               pos;\r
-                           XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) =\r
-                               len;\r
-                       }\r
-                   }\r
-               }\r
-               oldNode = ctxt->node;\r
-               ctxt->node = node;\r
-\r
-               if (step->value == NULL)\r
-                   goto wrong_index;\r
-               if (step->comp == NULL)\r
-                   goto wrong_index;\r
-\r
-               if (!xsltEvalXPathPredicate(ctxt, step->comp, comp->nsList,\r
-                                           comp->nsNr))\r
-                   goto wrong_index;\r
-\r
-               if (pos != 0) {\r
-                   ctxt->xpathCtxt->contextSize = oldCS;\r
-                   ctxt->xpathCtxt->proximityPosition = oldCP;\r
-               }\r
-               ctxt->node = oldNode;\r
-               break;\r
-wrong_index:\r
-               if (pos != 0) {\r
-                   ctxt->xpathCtxt->contextSize = oldCS;\r
-                   ctxt->xpathCtxt->proximityPosition = oldCP;\r
-               }\r
-               ctxt->node = oldNode;\r
-               goto rollback;\r
-           }\r
-            case XSLT_OP_PI:\r
-               if (node->type != XML_PI_NODE)\r
-                   goto rollback;\r
-               if (step->value != NULL) {\r
-                   if (!xmlStrEqual(step->value, node->name))\r
-                       goto rollback;\r
-               }\r
-               break;\r
-            case XSLT_OP_COMMENT:\r
-               if (node->type != XML_COMMENT_NODE)\r
-                   goto rollback;\r
-               break;\r
-            case XSLT_OP_TEXT:\r
-               if ((node->type != XML_TEXT_NODE) &&\r
-                   (node->type != XML_CDATA_SECTION_NODE))\r
-                   goto rollback;\r
-               break;\r
-            case XSLT_OP_NODE:\r
-               switch (node->type) {\r
-                   case XML_ELEMENT_NODE:\r
-                   case XML_CDATA_SECTION_NODE:\r
-                   case XML_PI_NODE:\r
-                   case XML_COMMENT_NODE:\r
-                   case XML_TEXT_NODE:\r
-                       break;\r
-                   default:\r
-                       goto rollback;\r
-               }\r
-               break;\r
-       }\r
-    }\r
-found:\r
-    if (states.states != NULL) {\r
-        /* Free the rollback states */\r
-       xmlFree(states.states);\r
-    }\r
-    return(1);\r
-rollback:\r
-    /* got an error try to rollback */\r
-    if (states.states == NULL)\r
-       return(0);\r
-    if (states.nbstates <= 0) {\r
-       xmlFree(states.states);\r
-       return(0);\r
-    }\r
-    states.nbstates--;\r
-    i = states.states[states.nbstates].step;\r
-    node = states.states[states.nbstates].node;\r
-#if 0\r
-    fprintf(stderr, "Pop: %d, %s\n", i, node->name);\r
-#endif\r
-    goto restart;\r
-}\r
-\r
-/**\r
- * xsltTestCompMatchList:\r
- * @ctxt:  a XSLT process context\r
- * @node: a node\r
- * @comp: the precompiled pattern list\r
- *\r
- * Test whether the node matches one of the patterns in the list\r
- *\r
- * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure\r
- */\r
-int\r
-xsltTestCompMatchList(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                     xsltCompMatchPtr comp) {\r
-    int ret;\r
-\r
-    if ((ctxt == NULL) || (node == NULL))\r
-       return(-1);\r
-    while (comp != NULL) {\r
-       ret = xsltTestCompMatch(ctxt, comp, node, NULL, NULL);\r
-       if (ret == 1)\r
-           return(1);\r
-       comp = comp->next;\r
-    }\r
-    return(0);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Dedicated parser for templates                  *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-#define CUR (*ctxt->cur)\r
-#define SKIP(val) ctxt->cur += (val)\r
-#define NXT(val) ctxt->cur[(val)]\r
-#define CUR_PTR ctxt->cur\r
-\r
-#define SKIP_BLANKS                                                    \\r
-    while (IS_BLANK_CH(CUR)) NEXT\r
-\r
-#define CURRENT (*ctxt->cur)\r
-#define NEXT ((*ctxt->cur) ?  ctxt->cur++: ctxt->cur)\r
-\r
-\r
-#define PUSH(op, val, val2, novar)                                             \\r
-    if (xsltCompMatchAdd(ctxt, ctxt->comp, (op), (val), (val2), (novar))) goto error;\r
-\r
-#define SWAP()                                                 \\r
-    xsltSwapTopCompMatch(ctxt->comp);\r
-\r
-#define XSLT_ERROR(X)                                                  \\r
-    { xsltError(ctxt, __FILE__, __LINE__, X);                  \\r
-      ctxt->error = (X); return; }\r
-\r
-#define XSLT_ERROR0(X)                                                 \\r
-    { xsltError(ctxt, __FILE__, __LINE__, X);                  \\r
-      ctxt->error = (X); return(0); }\r
-\r
-/**\r
- * xsltScanLiteral:\r
- * @ctxt:  the XPath Parser context\r
- *\r
- * Parse an XPath Litteral:\r
- *\r
- * [29] Literal ::= '"' [^"]* '"'\r
- *                | "'" [^']* "'"\r
- *\r
- * Returns the Literal parsed or NULL\r
- */\r
-\r
-static xmlChar *\r
-xsltScanLiteral(xsltParserContextPtr ctxt) {\r
-    const xmlChar *q, *cur;\r
-    xmlChar *ret = NULL;\r
-    int val, len;\r
-\r
-    SKIP_BLANKS;\r
-    if (CUR == '"') {\r
-        NEXT;\r
-       cur = q = CUR_PTR;\r
-       val = xmlStringCurrentChar(NULL, cur, &len);\r
-       while ((IS_CHAR(val)) && (val != '"')) {\r
-           cur += len;\r
-           val = xmlStringCurrentChar(NULL, cur, &len);\r
-       }\r
-       if (!IS_CHAR(val)) {\r
-           ctxt->error = 1;\r
-           return(NULL);\r
-       } else {\r
-           ret = xmlStrndup(q, cur - q);\r
-        }\r
-       cur += len;\r
-       CUR_PTR = cur;\r
-    } else if (CUR == '\'') {\r
-        NEXT;\r
-       cur = q = CUR_PTR;\r
-       val = xmlStringCurrentChar(NULL, cur, &len);\r
-       while ((IS_CHAR(val)) && (val != '\'')) {\r
-           cur += len;\r
-           val = xmlStringCurrentChar(NULL, cur, &len);\r
-       }\r
-       if (!IS_CHAR(val)) {\r
-           ctxt->error = 1;\r
-           return(NULL);\r
-       } else {\r
-           ret = xmlStrndup(q, cur - q);\r
-        }\r
-       cur += len;\r
-       CUR_PTR = cur;\r
-    } else {\r
-       /* XP_ERROR(XPATH_START_LITERAL_ERROR); */\r
-       ctxt->error = 1;\r
-       return(NULL);\r
-    }\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltScanName:\r
- * @ctxt:  the XPath Parser context\r
- *\r
- * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | \r
- *                  CombiningChar | Extender\r
- *\r
- * [5] Name ::= (Letter | '_' | ':') (NameChar)*\r
- *\r
- * [6] Names ::= Name (S Name)*\r
- *\r
- * Returns the Name parsed or NULL\r
- */\r
-\r
-static xmlChar *\r
-xsltScanName(xsltParserContextPtr ctxt) {\r
-    const xmlChar *q, *cur;\r
-    xmlChar *ret = NULL;\r
-    int val, len;\r
-\r
-    SKIP_BLANKS;\r
-\r
-    cur = q = CUR_PTR;\r
-    val = xmlStringCurrentChar(NULL, cur, &len);\r
-    if (!IS_LETTER(val) && (val != '_') && (val != ':'))\r
-       return(NULL);\r
-\r
-    while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||\r
-           (val == '.') || (val == '-') ||\r
-          (val == '_') || \r
-          (IS_COMBINING(val)) ||\r
-          (IS_EXTENDER(val))) {\r
-       cur += len;\r
-       val = xmlStringCurrentChar(NULL, cur, &len);\r
-    }\r
-    ret = xmlStrndup(q, cur - q);\r
-    CUR_PTR = cur;\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltScanNCName:\r
- * @ctxt:  the XPath Parser context\r
- *\r
- * Parses a non qualified name\r
- *\r
- * Returns the Name parsed or NULL\r
- */\r
-\r
-static xmlChar *\r
-xsltScanNCName(xsltParserContextPtr ctxt) {\r
-    const xmlChar *q, *cur;\r
-    xmlChar *ret = NULL;\r
-    int val, len;\r
-\r
-    SKIP_BLANKS;\r
-\r
-    cur = q = CUR_PTR;\r
-    val = xmlStringCurrentChar(NULL, cur, &len);\r
-    if (!IS_LETTER(val) && (val != '_'))\r
-       return(NULL);\r
-\r
-    while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||\r
-           (val == '.') || (val == '-') ||\r
-          (val == '_') ||\r
-          (IS_COMBINING(val)) ||\r
-          (IS_EXTENDER(val))) {\r
-       cur += len;\r
-       val = xmlStringCurrentChar(NULL, cur, &len);\r
-    }\r
-    ret = xmlStrndup(q, cur - q);\r
-    CUR_PTR = cur;\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltScanQName:\r
- * @ctxt:  the XPath Parser context\r
- * @prefix:  the place to store the prefix\r
- *\r
- * Parse a qualified name\r
- *\r
- * Returns the Name parsed or NULL\r
- */\r
-\r
-static xmlChar *\r
-xsltScanQName(xsltParserContextPtr ctxt, xmlChar **prefix) {\r
-    xmlChar *ret = NULL;\r
-\r
-    *prefix = NULL;\r
-    ret = xsltScanNCName(ctxt);\r
-    if (CUR == ':') {\r
-        *prefix = ret;\r
-       NEXT;\r
-       ret = xsltScanNCName(ctxt);\r
-    }\r
-    return(ret);\r
-}\r
-\r
-/*\r
- * xsltCompileIdKeyPattern:\r
- * @ctxt:  the compilation context\r
- * @name:  a preparsed name\r
- * @aid:  whether id/key are allowed there\r
- * @novar:  flag to prohibit xslt var\r
- *\r
- * Compile the XSLT LocationIdKeyPattern\r
- * [3] IdKeyPattern ::= 'id' '(' Literal ')'\r
- *                    | 'key' '(' Literal ',' Literal ')'\r
- *\r
- * also handle NodeType and PI from:\r
- *\r
- * [7]  NodeTest ::= NameTest\r
- *                 | NodeType '(' ')'\r
- *                 | 'processing-instruction' '(' Literal ')'\r
- */\r
-static void\r
-xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name,\r
-               int aid, int novar) {\r
-    xmlChar *lit = NULL;\r
-    xmlChar *lit2 = NULL;\r
-\r
-    if (CUR != '(') {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-               "xsltCompileIdKeyPattern : ( expected\n");\r
-       ctxt->error = 1;\r
-       return;\r
-    }\r
-    if ((aid) && (xmlStrEqual(name, (const xmlChar *)"id"))) {\r
-       NEXT;\r
-       SKIP_BLANKS;\r
-        lit = xsltScanLiteral(ctxt);\r
-       if (ctxt->error)\r
-           return;\r
-       SKIP_BLANKS;\r
-       if (CUR != ')') {\r
-           xsltTransformError(NULL, NULL, NULL,\r
-                   "xsltCompileIdKeyPattern : ) expected\n");\r
-           ctxt->error = 1;\r
-           return;\r
-       }\r
-       NEXT;\r
-       PUSH(XSLT_OP_ID, lit, NULL, novar);\r
-    } else if ((aid) && (xmlStrEqual(name, (const xmlChar *)"key"))) {\r
-       NEXT;\r
-       SKIP_BLANKS;\r
-        lit = xsltScanLiteral(ctxt);\r
-       if (ctxt->error)\r
-           return;\r
-       SKIP_BLANKS;\r
-       if (CUR != ',') {\r
-           xsltTransformError(NULL, NULL, NULL,\r
-                   "xsltCompileIdKeyPattern : , expected\n");\r
-           ctxt->error = 1;\r
-           return;\r
-       }\r
-       NEXT;\r
-       SKIP_BLANKS;\r
-        lit2 = xsltScanLiteral(ctxt);\r
-       if (ctxt->error)\r
-           return;\r
-       SKIP_BLANKS;\r
-       if (CUR != ')') {\r
-           xsltTransformError(NULL, NULL, NULL,\r
-                   "xsltCompileIdKeyPattern : ) expected\n");\r
-           ctxt->error = 1;\r
-           return;\r
-       }\r
-       NEXT;\r
-       /* URGENT TODO: support namespace in keys */\r
-       PUSH(XSLT_OP_KEY, lit, lit2, novar);\r
-    } else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) {\r
-       NEXT;\r
-       SKIP_BLANKS;\r
-       if (CUR != ')') {\r
-           lit = xsltScanLiteral(ctxt);\r
-           if (ctxt->error)\r
-               return;\r
-           SKIP_BLANKS;\r
-           if (CUR != ')') {\r
-               xsltTransformError(NULL, NULL, NULL,\r
-                       "xsltCompileIdKeyPattern : ) expected\n");\r
-               ctxt->error = 1;\r
-               return;\r
-           }\r
-       }\r
-       NEXT;\r
-       PUSH(XSLT_OP_PI, lit, NULL, novar);\r
-    } else if (xmlStrEqual(name, (const xmlChar *)"text")) {\r
-       NEXT;\r
-       SKIP_BLANKS;\r
-       if (CUR != ')') {\r
-           xsltTransformError(NULL, NULL, NULL,\r
-                   "xsltCompileIdKeyPattern : ) expected\n");\r
-           ctxt->error = 1;\r
-           return;\r
-       }\r
-       NEXT;\r
-       PUSH(XSLT_OP_TEXT, NULL, NULL, novar);\r
-    } else if (xmlStrEqual(name, (const xmlChar *)"comment")) {\r
-       NEXT;\r
-       SKIP_BLANKS;\r
-       if (CUR != ')') {\r
-           xsltTransformError(NULL, NULL, NULL,\r
-                   "xsltCompileIdKeyPattern : ) expected\n");\r
-           ctxt->error = 1;\r
-           return;\r
-       }\r
-       NEXT;\r
-       PUSH(XSLT_OP_COMMENT, NULL, NULL, novar);\r
-    } else if (xmlStrEqual(name, (const xmlChar *)"node")) {\r
-       NEXT;\r
-       SKIP_BLANKS;\r
-       if (CUR != ')') {\r
-           xsltTransformError(NULL, NULL, NULL,\r
-                   "xsltCompileIdKeyPattern : ) expected\n");\r
-           ctxt->error = 1;\r
-           return;\r
-       }\r
-       NEXT;\r
-       PUSH(XSLT_OP_NODE, NULL, NULL, novar);\r
-    } else if (aid) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-           "xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type\n");\r
-       ctxt->error = 1;\r
-       return;\r
-    } else {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-           "xsltCompileIdKeyPattern : node type\n");\r
-       ctxt->error = 1;\r
-       return;\r
-    }\r
-error:\r
-    if (name != NULL)\r
-       xmlFree(name);\r
-}\r
-\r
-/**\r
- * xsltCompileStepPattern:\r
- * @ctxt:  the compilation context\r
- * @token:  a posible precompiled name\r
- * @novar: flag to prohibit xslt variables from pattern\r
- *\r
- * Compile the XSLT StepPattern and generates a precompiled\r
- * form suitable for fast matching.\r
- *\r
- * [5] StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest Predicate* \r
- * [6] ChildOrAttributeAxisSpecifier ::= AbbreviatedAxisSpecifier\r
- *                                     | ('child' | 'attribute') '::'\r
- * from XPath\r
- * [7]  NodeTest ::= NameTest\r
- *                 | NodeType '(' ')'\r
- *                 | 'processing-instruction' '(' Literal ')'\r
- * [8] Predicate ::= '[' PredicateExpr ']'\r
- * [9] PredicateExpr ::= Expr\r
- * [13] AbbreviatedAxisSpecifier ::= '@'?\r
- * [37] NameTest ::= '*' | NCName ':' '*' | QName\r
- */\r
-\r
-static void\r
-xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token, int novar) {\r
-    xmlChar *name = NULL;\r
-    const xmlChar *URI = NULL;\r
-    xmlChar *URL = NULL;\r
-    int level;\r
-\r
-    SKIP_BLANKS;\r
-    if ((token == NULL) && (CUR == '@')) {\r
-       xmlChar *prefix = NULL;\r
-\r
-       NEXT;\r
-       if (CUR == '*') {\r
-           NEXT;\r
-           PUSH(XSLT_OP_ATTR, NULL, NULL, novar);\r
-           goto parse_predicate;\r
-       }\r
-       token = xsltScanQName(ctxt, &prefix);\r
-       if (prefix != NULL) {\r
-           xmlNsPtr ns;\r
-\r
-           ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix);\r
-           if (ns == NULL) {\r
-               xsltTransformError(NULL, NULL, NULL,\r
-               "xsltCompileStepPattern : no namespace bound to prefix %s\n",\r
-                                prefix);\r
-           } else {\r
-               URL = xmlStrdup(ns->href);\r
-           }\r
-           xmlFree(prefix);\r
-       }\r
-       if (token == NULL) {\r
-           if (CUR == '*') {\r
-               NEXT;\r
-               PUSH(XSLT_OP_ATTR, NULL, URL, novar);\r
-               return;\r
-           }\r
-           xsltTransformError(NULL, NULL, NULL,\r
-                   "xsltCompileStepPattern : Name expected\n");\r
-           ctxt->error = 1;\r
-           goto error;\r
-       }\r
-       PUSH(XSLT_OP_ATTR, token, URL, novar);\r
-       goto parse_predicate;\r
-    }\r
-    if (token == NULL)\r
-       token = xsltScanName(ctxt);\r
-    if (token == NULL) {\r
-       if (CUR == '*') {\r
-           NEXT;\r
-           PUSH(XSLT_OP_ALL, token, NULL, novar);\r
-           goto parse_predicate;\r
-       } else {\r
-           xsltTransformError(NULL, NULL, NULL,\r
-                   "xsltCompileStepPattern : Name expected\n");\r
-           ctxt->error = 1;\r
-           goto error;\r
-       }\r
-    }\r
-\r
-\r
-    SKIP_BLANKS;\r
-    if (CUR == '(') {\r
-       xsltCompileIdKeyPattern(ctxt, token, 0, novar);\r
-       if (ctxt->error)\r
-           goto error;\r
-    } else if (CUR == ':') {\r
-       NEXT;\r
-       if (CUR != ':') {\r
-           xmlChar *prefix = token;\r
-           xmlNsPtr ns;\r
-\r
-           /*\r
-            * This is a namespace match\r
-            */\r
-           token = xsltScanName(ctxt);\r
-           ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix);\r
-           if (ns == NULL) {\r
-               xsltTransformError(NULL, NULL, NULL,\r
-           "xsltCompileStepPattern : no namespace bound to prefix %s\n",\r
-                                prefix);\r
-               ctxt->error = 1;\r
-               goto error;\r
-           } else {\r
-               URL = xmlStrdup(ns->href);\r
-           }\r
-           xmlFree(prefix);\r
-           if (token == NULL) {\r
-               if (CUR == '*') {\r
-                   NEXT;\r
-                   PUSH(XSLT_OP_NS, URL, NULL, novar);\r
-               } else {\r
-                   xsltTransformError(NULL, NULL, NULL,\r
-                           "xsltCompileStepPattern : Name expected\n");\r
-                   ctxt->error = 1;\r
-                   goto error;\r
-               }\r
-           } else {\r
-               PUSH(XSLT_OP_ELEM, token, URL, novar);\r
-           }\r
-       } else {\r
-           NEXT;\r
-           if (xmlStrEqual(token, (const xmlChar *) "child")) {\r
-               xmlFree(token);\r
-               token = xsltScanName(ctxt);\r
-               if (token == NULL) {\r
-                   if (CUR == '*') {\r
-                       NEXT;\r
-                       PUSH(XSLT_OP_ALL, token, NULL, novar);\r
-                       goto parse_predicate;\r
-                   } else {\r
-                       xsltTransformError(NULL, NULL, NULL,\r
-                           "xsltCompileStepPattern : QName expected\n");\r
-                       ctxt->error = 1;\r
-                       goto error;\r
-                   }\r
-               }\r
-               URI = xsltGetQNameURI(ctxt->elem, &token);\r
-               if (token == NULL) {\r
-                   ctxt->error = 1;\r
-                   goto error;\r
-               } else {\r
-                   name = xmlStrdup(token);\r
-                   if (URI != NULL)\r
-                       URL = xmlStrdup(URI);\r
-               }\r
-               PUSH(XSLT_OP_CHILD, name, URL, novar);\r
-           } else if (xmlStrEqual(token, (const xmlChar *) "attribute")) {\r
-               xmlFree(token);\r
-               token = xsltScanName(ctxt);\r
-               if (token == NULL) {\r
-                   xsltTransformError(NULL, NULL, NULL,\r
-                           "xsltCompileStepPattern : QName expected\n");\r
-                   ctxt->error = 1;\r
-                   goto error;\r
-               }\r
-               URI = xsltGetQNameURI(ctxt->elem, &token);\r
-               if (token == NULL) {\r
-                   ctxt->error = 1;\r
-                   goto error;\r
-               } else {\r
-                   name = xmlStrdup(token);\r
-                   if (URI != NULL)\r
-                       URL = xmlStrdup(URI);\r
-               }\r
-               PUSH(XSLT_OP_ATTR, name, URL, novar);\r
-           } else {\r
-               xsltTransformError(NULL, NULL, NULL,\r
-                   "xsltCompileStepPattern : 'child' or 'attribute' expected\n");\r
-               ctxt->error = 1;\r
-               goto error;\r
-           }\r
-           xmlFree(token);\r
-       }\r
-    } else if (CUR == '*') {\r
-       NEXT;\r
-       PUSH(XSLT_OP_ALL, token, NULL, novar);\r
-    } else {\r
-       URI = xsltGetQNameURI(ctxt->elem, &token);\r
-       if (token == NULL) {\r
-           ctxt->error = 1;\r
-           goto error;\r
-       }\r
-       if (URI != NULL)\r
-           URL = xmlStrdup(URI);\r
-       PUSH(XSLT_OP_ELEM, token, URL, novar);\r
-    }\r
-parse_predicate:\r
-    SKIP_BLANKS;\r
-    level = 0;\r
-    while (CUR == '[') {\r
-       const xmlChar *q;\r
-       xmlChar *ret = NULL;\r
-\r
-       level++;\r
-       NEXT;\r
-       q = CUR_PTR;\r
-       while (CUR != 0) {\r
-           /* Skip over nested predicates */\r
-           if (CUR == '[')\r
-               level++;\r
-           else if (CUR == ']') {\r
-               level--;\r
-               if (level == 0)\r
-                   break;\r
-           } else if (CUR == '"') {\r
-               NEXT;\r
-               while ((CUR != 0) && (CUR != '"'))\r
-                   NEXT;\r
-           } else if (CUR == '\'') {\r
-               NEXT;\r
-               while ((CUR != 0) && (CUR != '\''))\r
-                   NEXT;\r
-           }\r
-           NEXT;\r
-       }\r
-       if (CUR == 0) {\r
-           xsltTransformError(NULL, NULL, NULL,\r
-                   "xsltCompileStepPattern : ']' expected\n");\r
-           ctxt->error = 1;\r
-           return;\r
-        }\r
-       ret = xmlStrndup(q, CUR_PTR - q);\r
-       PUSH(XSLT_OP_PREDICATE, ret, NULL, novar);\r
-       /* push the predicate lower than local test */\r
-       SWAP();\r
-       NEXT;\r
-       SKIP_BLANKS;\r
-    }\r
-    return;\r
-error:\r
-    if (token != NULL)\r
-       xmlFree(token);\r
-    if (name != NULL)\r
-       xmlFree(name);\r
-}\r
-\r
-/**\r
- * xsltCompileRelativePathPattern:\r
- * @comp:  the compilation context\r
- * @token:  a posible precompiled name\r
- * @novar:  flag to prohibit xslt variables\r
- *\r
- * Compile the XSLT RelativePathPattern and generates a precompiled\r
- * form suitable for fast matching.\r
- *\r
- * [4] RelativePathPattern ::= StepPattern\r
- *                           | RelativePathPattern '/' StepPattern\r
- *                           | RelativePathPattern '//' StepPattern\r
- */\r
-static void\r
-xsltCompileRelativePathPattern(xsltParserContextPtr ctxt, xmlChar *token, int novar) {\r
-    xsltCompileStepPattern(ctxt, token, novar);\r
-    if (ctxt->error)\r
-       goto error;\r
-    SKIP_BLANKS;\r
-    while ((CUR != 0) && (CUR != '|')) {\r
-       if ((CUR == '/') && (NXT(1) == '/')) {\r
-           PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);\r
-           NEXT;\r
-           NEXT;\r
-           SKIP_BLANKS;\r
-           xsltCompileStepPattern(ctxt, NULL, novar);\r
-       } else if (CUR == '/') {\r
-           PUSH(XSLT_OP_PARENT, NULL, NULL, novar);\r
-           NEXT;\r
-           SKIP_BLANKS;\r
-           if ((CUR != 0) && (CUR != '|')) {\r
-               xsltCompileRelativePathPattern(ctxt, NULL, novar);\r
-           }\r
-       } else {\r
-           ctxt->error = 1;\r
-       }\r
-       if (ctxt->error)\r
-           goto error;\r
-       SKIP_BLANKS;\r
-    }\r
-error:\r
-    return;\r
-}\r
-\r
-/**\r
- * xsltCompileLocationPathPattern:\r
- * @ctxt:  the compilation context\r
- * @novar:  flag to prohibit xslt variables\r
- *\r
- * Compile the XSLT LocationPathPattern and generates a precompiled\r
- * form suitable for fast matching.\r
- *\r
- * [2] LocationPathPattern ::= '/' RelativePathPattern?\r
- *                           | IdKeyPattern (('/' | '//') RelativePathPattern)?\r
- *                           | '//'? RelativePathPattern\r
- */\r
-static void\r
-xsltCompileLocationPathPattern(xsltParserContextPtr ctxt, int novar) {\r
-    SKIP_BLANKS;\r
-    if ((CUR == '/') && (NXT(1) == '/')) {\r
-       /*\r
-        * since we reverse the query\r
-        * a leading // can be safely ignored\r
-        */\r
-       NEXT;\r
-       NEXT;\r
-       ctxt->comp->priority = 0.5;     /* '//' means not 0 priority */\r
-       xsltCompileRelativePathPattern(ctxt, NULL, novar);\r
-    } else if (CUR == '/') {\r
-       /*\r
-        * We need to find root as the parent\r
-        */\r
-       NEXT;\r
-       SKIP_BLANKS;\r
-       PUSH(XSLT_OP_ROOT, NULL, NULL, novar);\r
-       if ((CUR != 0) && (CUR != '|')) {\r
-           PUSH(XSLT_OP_PARENT, NULL, NULL, novar);\r
-           xsltCompileRelativePathPattern(ctxt, NULL, novar);\r
-       }\r
-    } else if (CUR == '*') {\r
-       xsltCompileRelativePathPattern(ctxt, NULL, novar);\r
-    } else if (CUR == '@') {\r
-       xsltCompileRelativePathPattern(ctxt, NULL, novar);\r
-    } else {\r
-       xmlChar *name;\r
-       name = xsltScanName(ctxt);\r
-       if (name == NULL) {\r
-           xsltTransformError(NULL, NULL, NULL,\r
-                   "xsltCompileLocationPathPattern : Name expected\n");\r
-           ctxt->error = 1;\r
-           return;\r
-       }\r
-       SKIP_BLANKS;\r
-       if ((CUR == '(') && !xmlXPathIsNodeType(name)) {\r
-           xsltCompileIdKeyPattern(ctxt, name, 1, novar);\r
-           if ((CUR == '/') && (NXT(1) == '/')) {\r
-               PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);\r
-               NEXT;\r
-               NEXT;\r
-               SKIP_BLANKS;\r
-               xsltCompileRelativePathPattern(ctxt, NULL, novar);\r
-           } else if (CUR == '/') {\r
-               PUSH(XSLT_OP_PARENT, NULL, NULL, novar);\r
-               NEXT;\r
-               SKIP_BLANKS;\r
-               xsltCompileRelativePathPattern(ctxt, NULL, novar);\r
-           }\r
-           return;\r
-       }\r
-       xsltCompileRelativePathPattern(ctxt, name, novar);\r
-    }\r
-error:\r
-    return;\r
-}\r
-\r
-/**\r
- * xsltCompilePatternInternal:\r
- * @pattern: an XSLT pattern\r
- * @doc:  the containing document\r
- * @node:  the containing element\r
- * @style:  the stylesheet\r
- * @runtime:  the transformation context, if done at run-time\r
- * @novar:  flag to prohibit xslt variables\r
- *\r
- * Compile the XSLT pattern and generates a list of precompiled form suitable\r
- * for fast matching.\r
- *\r
- * [1] Pattern ::= LocationPathPattern | Pattern '|' LocationPathPattern\r
- *\r
- * Returns the generated pattern list or NULL in case of failure\r
- */\r
-\r
-static xsltCompMatchPtr\r
-xsltCompilePatternInternal(const xmlChar *pattern, xmlDocPtr doc,\r
-                  xmlNodePtr node, xsltStylesheetPtr style,\r
-                  xsltTransformContextPtr runtime, int novar) {\r
-    xsltParserContextPtr ctxt = NULL;\r
-    xsltCompMatchPtr element, first = NULL, previous = NULL;\r
-    int current, start, end, level, j;\r
-\r
-    if (pattern == NULL) {\r
-       xsltTransformError(NULL, NULL, node,\r
-                        "xsltCompilePattern : NULL pattern\n");\r
-       return(NULL);\r
-    }\r
-\r
-    ctxt = xsltNewParserContext(style, runtime);\r
-    if (ctxt == NULL)\r
-       return(NULL);\r
-    ctxt->doc = doc;\r
-    ctxt->elem = node;\r
-    current = end = 0;\r
-    while (pattern[current] != 0) {\r
-       start = current;\r
-       while (IS_BLANK_CH(pattern[current]))\r
-           current++;\r
-       end = current;\r
-       level = 0;\r
-       while ((pattern[end] != 0) && ((pattern[end] != '|') || (level != 0))) {\r
-           if (pattern[end] == '[')\r
-               level++;\r
-           else if (pattern[end] == ']')\r
-               level--;\r
-           else if (pattern[end] == '\'') {\r
-               end++;\r
-               while ((pattern[end] != 0) && (pattern[end] != '\''))\r
-                   end++;\r
-           } else if (pattern[end] == '"') {\r
-               end++;\r
-               while ((pattern[end] != 0) && (pattern[end] != '"'))\r
-                   end++;\r
-           }\r
-           end++;\r
-       }\r
-       if (current == end) {\r
-           xsltTransformError(NULL, NULL, node,\r
-                            "xsltCompilePattern : NULL pattern\n");\r
-           goto error;\r
-       }\r
-       element = xsltNewCompMatch();\r
-       if (element == NULL) {\r
-           goto error;\r
-       }\r
-       if (first == NULL)\r
-           first = element;\r
-       else if (previous != NULL)\r
-           previous->next = element;\r
-       previous = element;\r
-\r
-       ctxt->comp = element;\r
-       ctxt->base = xmlStrndup(&pattern[start], end - start);\r
-       if (ctxt->base == NULL)\r
-           goto error;\r
-       ctxt->cur = &(ctxt->base)[current - start];\r
-       element->pattern = ctxt->base;\r
-       element->nsList = xmlGetNsList(doc, node);\r
-       j = 0;\r
-       if (element->nsList != NULL) {\r
-           while (element->nsList[j] != NULL)\r
-               j++;\r
-       }\r
-       element->nsNr = j;\r
-\r
-\r
-#ifdef WITH_XSLT_DEBUG_PATTERN\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-                        "xsltCompilePattern : parsing '%s'\n",\r
-                        element->pattern);\r
-#endif\r
-       /*\r
-        Preset default priority to be zero.\r
-        This may be changed by xsltCompileLocationPathPattern.\r
-        */\r
-       element->priority = 0;\r
-       xsltCompileLocationPathPattern(ctxt, novar);\r
-       if (ctxt->error) {\r
-           xsltTransformError(NULL, style, node,\r
-                            "xsltCompilePattern : failed to compile '%s'\n",\r
-                            element->pattern);\r
-           if (style != NULL) style->errors++;\r
-           goto error;\r
-       }\r
-\r
-       /*\r
-        * Reverse for faster interpretation.\r
-        */\r
-       xsltReverseCompMatch(element);\r
-\r
-       /*\r
-        * Set-up the priority\r
-        */\r
-       if (element->priority == 0) {   /* if not yet determined */\r
-           if (((element->steps[0].op == XSLT_OP_ELEM) ||\r
-                (element->steps[0].op == XSLT_OP_ATTR) ||\r
-                (element->steps[0].op == XSLT_OP_PI)) &&\r
-               (element->steps[0].value != NULL) &&\r
-               (element->steps[1].op == XSLT_OP_END)) {\r
-               ;       /* previously preset */\r
-           } else if ((element->steps[0].op == XSLT_OP_ATTR) &&\r
-                      (element->steps[0].value2 != NULL) &&\r
-                      (element->steps[1].op == XSLT_OP_END)) {\r
-                       element->priority = -0.25;\r
-           } else if ((element->steps[0].op == XSLT_OP_NS) &&\r
-                      (element->steps[0].value != NULL) &&\r
-                      (element->steps[1].op == XSLT_OP_END)) {\r
-                       element->priority = -0.25;\r
-           } else if ((element->steps[0].op == XSLT_OP_ATTR) &&\r
-                      (element->steps[0].value == NULL) &&\r
-                      (element->steps[0].value2 == NULL) &&\r
-                      (element->steps[1].op == XSLT_OP_END)) {\r
-                       element->priority = -0.5;\r
-           } else if (((element->steps[0].op == XSLT_OP_PI) ||\r
-                      (element->steps[0].op == XSLT_OP_TEXT) ||\r
-                      (element->steps[0].op == XSLT_OP_ALL) ||\r
-                      (element->steps[0].op == XSLT_OP_NODE) ||\r
-                      (element->steps[0].op == XSLT_OP_COMMENT)) &&\r
-                      (element->steps[1].op == XSLT_OP_END)) {\r
-                       element->priority = -0.5;\r
-           } else {\r
-               element->priority = 0.5;\r
-           }\r
-       }\r
-#ifdef WITH_XSLT_DEBUG_PATTERN\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-                    "xsltCompilePattern : parsed %s, default priority %f\n",\r
-                        element->pattern, element->priority);\r
-#endif\r
-       if (pattern[end] == '|')\r
-           end++;\r
-       current = end;\r
-    }\r
-    if (end == 0) {\r
-       xsltTransformError(NULL, style, node,\r
-                        "xsltCompilePattern : NULL pattern\n");\r
-       if (style != NULL) style->errors++;\r
-       goto error;\r
-    }\r
-\r
-    xsltFreeParserContext(ctxt);\r
-    return(first);\r
-\r
-error:\r
-    if (ctxt != NULL)\r
-       xsltFreeParserContext(ctxt);\r
-    if (first != NULL)\r
-       xsltFreeCompMatchList(first);\r
-    return(NULL);\r
-}\r
-\r
-/**\r
- * xsltCompilePattern:\r
- * @pattern: an XSLT pattern\r
- * @doc:  the containing document\r
- * @node:  the containing element\r
- * @style:  the stylesheet\r
- * @runtime:  the transformation context, if done at run-time\r
- *\r
- * Compile the XSLT pattern and generates a list of precompiled form suitable\r
- * for fast matching.\r
- *\r
- * [1] Pattern ::= LocationPathPattern | Pattern '|' LocationPathPattern\r
- *\r
- * Returns the generated pattern list or NULL in case of failure\r
- */\r
-\r
-xsltCompMatchPtr\r
-xsltCompilePattern(const xmlChar *pattern, xmlDocPtr doc,\r
-                  xmlNodePtr node, xsltStylesheetPtr style,\r
-                  xsltTransformContextPtr runtime) {\r
-    return (xsltCompilePatternInternal(pattern, doc, node, style, runtime, 0));\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Module interfaces                               *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltAddTemplate:\r
- * @style: an XSLT stylesheet\r
- * @cur: an XSLT template\r
- * @mode:  the mode name or NULL\r
- * @modeURI:  the mode URI or NULL\r
- *\r
- * Register the XSLT pattern associated to @cur\r
- *\r
- * Returns -1 in case of error, 0 otherwise\r
- */\r
-int\r
-xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur,\r
-               const xmlChar *mode, const xmlChar *modeURI) {\r
-    xsltCompMatchPtr pat, list, *top = NULL, next;\r
-    const xmlChar *name = NULL;\r
-    float priority;              /* the priority */\r
-\r
-    if ((style == NULL) || (cur == NULL) || (cur->match == NULL))\r
-       return(-1);\r
-\r
-    priority = cur->priority;\r
-    pat = xsltCompilePatternInternal(cur->match, style->doc, cur->elem,\r
-                   style, NULL, 1);\r
-    while (pat) {\r
-       next = pat->next;\r
-       pat->next = NULL;\r
-       name = NULL;\r
-       \r
-       pat->template = cur;\r
-       if (mode != NULL)\r
-           pat->mode = xmlDictLookup(style->dict, mode, -1);\r
-       if (modeURI != NULL)\r
-           pat->modeURI = xmlDictLookup(style->dict, modeURI, -1);\r
-       if (priority != XSLT_PAT_NO_PRIORITY)\r
-           pat->priority = priority;\r
-\r
-       /*\r
-        * insert it in the hash table list corresponding to its lookup name\r
-        */\r
-       switch (pat->steps[0].op) {\r
-        case XSLT_OP_ATTR:\r
-           if (pat->steps[0].value != NULL)\r
-               name = pat->steps[0].value;\r
-           else\r
-               top = (xsltCompMatchPtr *) &(style->attrMatch);\r
-           break;\r
-        case XSLT_OP_CHILD:\r
-        case XSLT_OP_PARENT:\r
-        case XSLT_OP_ANCESTOR:\r
-           top = (xsltCompMatchPtr *) &(style->elemMatch);\r
-           break;\r
-        case XSLT_OP_ROOT:\r
-           top = (xsltCompMatchPtr *) &(style->rootMatch);\r
-           break;\r
-        case XSLT_OP_KEY:\r
-           top = (xsltCompMatchPtr *) &(style->keyMatch);\r
-           break;\r
-        case XSLT_OP_ID:\r
-           /* TODO optimize ID !!! */\r
-        case XSLT_OP_NS:\r
-        case XSLT_OP_ALL:\r
-           top = (xsltCompMatchPtr *) &(style->elemMatch);\r
-           break;\r
-        case XSLT_OP_END:\r
-       case XSLT_OP_PREDICATE:\r
-           xsltTransformError(NULL, style, NULL,\r
-                            "xsltAddTemplate: invalid compiled pattern\n");\r
-           xsltFreeCompMatch(pat);\r
-           return(-1);\r
-           /*\r
-            * TODO: some flags at the top level about type based patterns\r
-            *       would be faster than inclusion in the hash table.\r
-            */\r
-       case XSLT_OP_PI:\r
-           if (pat->steps[0].value != NULL)\r
-               name = pat->steps[0].value;\r
-           else\r
-               top = (xsltCompMatchPtr *) &(style->piMatch);\r
-           break;\r
-       case XSLT_OP_COMMENT:\r
-           top = (xsltCompMatchPtr *) &(style->commentMatch);\r
-           break;\r
-       case XSLT_OP_TEXT:\r
-           top = (xsltCompMatchPtr *) &(style->textMatch);\r
-           break;\r
-        case XSLT_OP_ELEM:\r
-       case XSLT_OP_NODE:\r
-           if (pat->steps[0].value != NULL)\r
-               name = pat->steps[0].value;\r
-           else\r
-               top = (xsltCompMatchPtr *) &(style->elemMatch);\r
-           break;\r
-       }\r
-       if (name != NULL) {\r
-           if (style->templatesHash == NULL) {\r
-               style->templatesHash = xmlHashCreate(1024);\r
-               if (style->templatesHash == NULL) {\r
-                   xsltFreeCompMatch(pat);\r
-                   return(-1);\r
-               }\r
-               xmlHashAddEntry3(style->templatesHash, name, mode, modeURI, pat);\r
-           } else {\r
-               list = (xsltCompMatchPtr) xmlHashLookup3(style->templatesHash,\r
-                                                        name, mode, modeURI);\r
-               if (list == NULL) {\r
-                   xmlHashAddEntry3(style->templatesHash, name,\r
-                                    mode, modeURI, pat);\r
-               } else {\r
-                   /*\r
-                    * Note '<=' since one must choose among the matching\r
-                    * template rules that are left, the one that occurs\r
-                    * last in the stylesheet\r
-                    */\r
-                   if (list->priority <= pat->priority) {\r
-                       pat->next = list;\r
-                       xmlHashUpdateEntry3(style->templatesHash, name,\r
-                                           mode, modeURI, pat, NULL);\r
-                   } else {\r
-                       while (list->next != NULL) {\r
-                           if (list->next->priority <= pat->priority)\r
-                               break;\r
-                           list = list->next;\r
-                       }\r
-                       pat->next = list->next;\r
-                       list->next = pat;\r
-                   }\r
-               }\r
-           }\r
-       } else if (top != NULL) {\r
-           list = *top;\r
-           if (list == NULL) {\r
-               *top = pat;\r
-               pat->next = NULL;\r
-           } else if (list->priority <= pat->priority) {\r
-               pat->next = list;\r
-               *top = pat;\r
-           } else {\r
-               while (list->next != NULL) {\r
-                   if (list->next->priority <= pat->priority)\r
-                       break;\r
-                   list = list->next;\r
-               }\r
-               pat->next = list->next;\r
-               list->next = pat;\r
-           }\r
-       } else {\r
-           xsltTransformError(NULL, style, NULL,\r
-                            "xsltAddTemplate: invalid compiled pattern\n");\r
-           xsltFreeCompMatch(pat);\r
-           return(-1);\r
-       }\r
-#ifdef WITH_XSLT_DEBUG_PATTERN\r
-       if (mode)\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-                        "added pattern : '%s' mode '%s' priority %f\n",\r
-                            pat->pattern, pat->mode, pat->priority);\r
-       else\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-                        "added pattern : '%s' priority %f\n",\r
-                            pat->pattern, pat->priority);\r
-#endif\r
-\r
-       pat = next;\r
-    }\r
-    return(0);\r
-}\r
-\r
-#ifdef XSLT_REFACTORED_KEYCOMP\r
-static int\r
-xsltComputeAllKeys(xsltTransformContextPtr ctxt, xmlNodePtr contextNode)\r
-{\r
-    xsltStylesheetPtr style, style2;\r
-    xsltKeyDefPtr keyd, keyd2;\r
-    xsltKeyTablePtr table;\r
-\r
-    if ((ctxt == NULL) || (contextNode == NULL)) {\r
-       xsltTransformError(ctxt, NULL, ctxt->inst,\r
-           "Internal error in xsltComputeAllKeys(): "\r
-           "Bad arguments.\n");\r
-       return(-1);\r
-    }\r
-    \r
-    if (ctxt->document == NULL) {\r
-       /*\r
-       * The document info will only be NULL if we have a RTF.\r
-       */\r
-       if (contextNode->doc->_private != NULL)\r
-           goto doc_info_mismatch;\r
-       /*\r
-       * On-demand creation of the document info (needed for keys).\r
-       */\r
-       ctxt->document = xsltNewDocument(ctxt, contextNode->doc);\r
-       if (ctxt->document == NULL)\r
-           return(-1);\r
-    }\r
-\r
-    if (ctxt->document->nbKeysComputed == ctxt->nbKeys)\r
-       return(0);\r
-    /*\r
-    * TODO: This could be further optimized\r
-    */\r
-    style = ctxt->style;\r
-    while (style) {\r
-       keyd = (xsltKeyDefPtr) style->keys;\r
-       while (keyd != NULL) {\r
-           /*\r
-           * Check if keys with this QName have been already\r
-           * computed.\r
-           */\r
-           table = (xsltKeyTablePtr) ctxt->document->keys;\r
-           while (table) {\r
-               if (((keyd->nameURI != NULL) == (table->nameURI != NULL)) &&\r
-                   xmlStrEqual(keyd->name, table->name) &&\r
-                   xmlStrEqual(keyd->nameURI, table->nameURI))\r
-               {\r
-                   break;\r
-               }               \r
-               table = table->next;\r
-           }\r
-           if (table == NULL) {\r
-               /*\r
-               * Keys with this QName have not been yet computed.\r
-               */\r
-               style2 = ctxt->style;\r
-               while (style2 != NULL) {\r
-                   keyd2 = (xsltKeyDefPtr) style2->keys;\r
-                   while (keyd2 != NULL) {\r
-                       if (((keyd2->nameURI != NULL) ==\r
-                            (keyd->nameURI != NULL)) &&\r
-                           xmlStrEqual(keyd2->name, keyd->name) &&\r
-                           xmlStrEqual(keyd2->nameURI, keyd->nameURI))\r
-                       {\r
-                           xsltInitCtxtKey(ctxt, ctxt->document, keyd2);\r
-                           if (ctxt->document->nbKeysComputed == ctxt->nbKeys)\r
-                               return(0);\r
-                       }\r
-                       keyd2 = keyd2->next;\r
-                   }\r
-                   style2 = xsltNextImport(style2);\r
-               }\r
-           }\r
-           keyd = keyd->next;\r
-       }\r
-       style = xsltNextImport(style);\r
-    }\r
-    return(0);\r
-\r
-doc_info_mismatch:\r
-    xsltTransformError(ctxt, NULL, ctxt->inst,\r
-       "Internal error in xsltComputeAllKeys(): "\r
-       "The context's document info doesn't match the "\r
-       "document info of the current result tree.\n");\r
-    ctxt->state = XSLT_STATE_STOPPED;\r
-    return(-1);\r
-}\r
-#endif\r
-\r
-/**\r
- * xsltGetTemplate:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the node being processed\r
- * @style:  the current style\r
- *\r
- * Finds the template applying to this node, if @style is non-NULL\r
- * it means one needs to look for the next imported template in scope.\r
- *\r
- * Returns the xsltTemplatePtr or NULL if not found\r
- */\r
-xsltTemplatePtr\r
-xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-               xsltStylesheetPtr style)\r
-{\r
-    xsltStylesheetPtr curstyle;\r
-    xsltTemplatePtr ret = NULL;\r
-    const xmlChar *name = NULL;\r
-    xsltCompMatchPtr list = NULL;\r
-    float priority;\r
-    int keyed = 0;\r
-\r
-    if ((ctxt == NULL) || (node == NULL))\r
-       return(NULL);\r
-\r
-    if (style == NULL) {\r
-       curstyle = ctxt->style;\r
-    } else {\r
-       curstyle = xsltNextImport(style);\r
-    }\r
-\r
-    while ((curstyle != NULL) && (curstyle != style)) {\r
-       priority = XSLT_PAT_NO_PRIORITY;\r
-       /* TODO : handle IDs/keys here ! */\r
-       if (curstyle->templatesHash != NULL) {\r
-           /*\r
-            * Use the top name as selector\r
-            */\r
-           switch (node->type) {\r
-               case XML_ELEMENT_NODE:\r
-                   if (node->name[0] == ' ')\r
-                       break;\r
-               case XML_ATTRIBUTE_NODE:\r
-               case XML_PI_NODE:\r
-                   name = node->name;\r
-                   break;\r
-               case XML_DOCUMENT_NODE:\r
-               case XML_HTML_DOCUMENT_NODE:\r
-               case XML_TEXT_NODE:\r
-               case XML_CDATA_SECTION_NODE:\r
-               case XML_COMMENT_NODE:\r
-               case XML_ENTITY_REF_NODE:\r
-               case XML_ENTITY_NODE:\r
-               case XML_DOCUMENT_TYPE_NODE:\r
-               case XML_DOCUMENT_FRAG_NODE:\r
-               case XML_NOTATION_NODE:\r
-               case XML_DTD_NODE:\r
-               case XML_ELEMENT_DECL:\r
-               case XML_ATTRIBUTE_DECL:\r
-               case XML_ENTITY_DECL:\r
-               case XML_NAMESPACE_DECL:\r
-               case XML_XINCLUDE_START:\r
-               case XML_XINCLUDE_END:\r
-                   break;\r
-               default:\r
-                   return(NULL);\r
-\r
-           }\r
-       }\r
-       if (name != NULL) {\r
-           /*\r
-            * find the list of applicable expressions based on the name\r
-            */\r
-           list = (xsltCompMatchPtr) xmlHashLookup3(curstyle->templatesHash,\r
-                                            name, ctxt->mode, ctxt->modeURI);\r
-       } else\r
-           list = NULL;\r
-       while (list != NULL) {\r
-           if (xsltTestCompMatch(ctxt, list, node,\r
-                                 ctxt->mode, ctxt->modeURI)) {\r
-               ret = list->template;\r
-               priority = list->priority;\r
-               break;\r
-           }\r
-           list = list->next;\r
-       }\r
-       list = NULL;\r
-\r
-       /*\r
-        * find alternate generic matches\r
-        */\r
-       switch (node->type) {\r
-           case XML_ELEMENT_NODE:\r
-               if (node->name[0] == ' ')\r
-                   list = curstyle->rootMatch;\r
-               else\r
-                   list = curstyle->elemMatch;\r
-               if (node->psvi != NULL) keyed = 1;\r
-               break;\r
-           case XML_ATTRIBUTE_NODE: {\r
-               xmlAttrPtr attr;\r
-\r
-               list = curstyle->attrMatch;\r
-               attr = (xmlAttrPtr) node;\r
-               if (attr->psvi != NULL) keyed = 1;\r
-               break;\r
-           }\r
-           case XML_PI_NODE:\r
-               list = curstyle->piMatch;\r
-               if (node->psvi != NULL) keyed = 1;\r
-               break;\r
-           case XML_DOCUMENT_NODE:\r
-           case XML_HTML_DOCUMENT_NODE: {\r
-               xmlDocPtr doc;\r
-\r
-               list = curstyle->rootMatch;\r
-               doc = (xmlDocPtr) node;\r
-               if (doc->psvi != NULL) keyed = 1;\r
-               break;\r
-           }\r
-           case XML_TEXT_NODE:\r
-           case XML_CDATA_SECTION_NODE:\r
-               list = curstyle->textMatch;\r
-               if (node->psvi != NULL) keyed = 1;\r
-               break;\r
-           case XML_COMMENT_NODE:\r
-               list = curstyle->commentMatch;\r
-               if (node->psvi != NULL) keyed = 1;\r
-               break;\r
-           case XML_ENTITY_REF_NODE:\r
-           case XML_ENTITY_NODE:\r
-           case XML_DOCUMENT_TYPE_NODE:\r
-           case XML_DOCUMENT_FRAG_NODE:\r
-           case XML_NOTATION_NODE:\r
-           case XML_DTD_NODE:\r
-           case XML_ELEMENT_DECL:\r
-           case XML_ATTRIBUTE_DECL:\r
-           case XML_ENTITY_DECL:\r
-           case XML_NAMESPACE_DECL:\r
-           case XML_XINCLUDE_START:\r
-           case XML_XINCLUDE_END:\r
-               break;\r
-           default:\r
-               break;\r
-       }\r
-       while ((list != NULL) &&\r
-              ((ret == NULL)  || (list->priority > priority))) {\r
-           if (xsltTestCompMatch(ctxt, list, node,\r
-                                 ctxt->mode, ctxt->modeURI)) {\r
-               ret = list->template;\r
-               priority = list->priority;\r
-               break;\r
-           }\r
-           list = list->next;\r
-       }\r
-       /*\r
-        * Some of the tests for elements can also apply to documents\r
-        */\r
-       if ((node->type == XML_DOCUMENT_NODE) ||\r
-           (node->type == XML_HTML_DOCUMENT_NODE) ||\r
-           (node->type == XML_TEXT_NODE)) {\r
-           list = curstyle->elemMatch;\r
-           while ((list != NULL) &&\r
-                  ((ret == NULL)  || (list->priority > priority))) {\r
-               if (xsltTestCompMatch(ctxt, list, node,\r
-                                     ctxt->mode, ctxt->modeURI)) {\r
-                   ret = list->template;\r
-                   priority = list->priority;\r
-                   break;\r
-               }\r
-               list = list->next;\r
-           }\r
-       } else if ((node->type == XML_PI_NODE) ||\r
-                  (node->type == XML_COMMENT_NODE)) {\r
-           list = curstyle->elemMatch;\r
-           while ((list != NULL) &&\r
-                  ((ret == NULL)  || (list->priority > priority))) {\r
-               if (xsltTestCompMatch(ctxt, list, node,\r
-                                     ctxt->mode, ctxt->modeURI)) {\r
-                   ret = list->template;\r
-                   priority = list->priority;\r
-                   break;\r
-               }\r
-               list = list->next;\r
-           }\r
-       }\r
-\r
-#ifdef XSLT_REFACTORED_KEYCOMP\r
-keyed_match:\r
-#endif\r
-       if (keyed) {\r
-           list = curstyle->keyMatch;\r
-           while ((list != NULL) &&\r
-                  ((ret == NULL)  || (list->priority > priority))) {\r
-               if (xsltTestCompMatch(ctxt, list, node,\r
-                                     ctxt->mode, ctxt->modeURI)) {\r
-                   ret = list->template;\r
-                   priority = list->priority;\r
-                   break;\r
-               }\r
-               list = list->next;\r
-           }\r
-       }\r
-#ifdef XSLT_REFACTORED_KEYCOMP \r
-       else if (ctxt->hasTemplKeyPatterns &&\r
-           ((ctxt->document == NULL) ||\r
-            (ctxt->document->nbKeysComputed < ctxt->nbKeys)))\r
-       {\r
-           /*\r
-           * Compute all remaining keys for this document.\r
-           *\r
-           * REVISIT TODO: I think this could be further optimized.\r
-           */\r
-           if (xsltComputeAllKeys(ctxt, node) == -1)\r
-               goto error;\r
-\r
-           switch (node->type) {\r
-               case XML_ELEMENT_NODE:              \r
-                   if (node->psvi != NULL) keyed = 1;\r
-                   break;\r
-               case XML_ATTRIBUTE_NODE:\r
-                   if (((xmlAttrPtr) node)->psvi != NULL) keyed = 1;\r
-                   break;\r
-               case XML_TEXT_NODE:\r
-               case XML_CDATA_SECTION_NODE:\r
-               case XML_COMMENT_NODE:\r
-               case XML_PI_NODE:               \r
-                   if (node->psvi != NULL) keyed = 1;\r
-                   break;\r
-               case XML_DOCUMENT_NODE:\r
-               case XML_HTML_DOCUMENT_NODE:\r
-                   if (((xmlDocPtr) node)->psvi != NULL) keyed = 1;\r
-                   break;              \r
-               default:\r
-                   break;\r
-           }\r
-           if (keyed)\r
-               goto keyed_match;\r
-       }\r
-#endif /* XSLT_REFACTORED_KEYCOMP */\r
-       if (ret != NULL)\r
-           return(ret);\r
-\r
-       /*\r
-        * Cycle on next curstylesheet import.\r
-        */\r
-       curstyle = xsltNextImport(curstyle);\r
-    }\r
-\r
-error:\r
-    return(NULL);\r
-}\r
-\r
-/**\r
- * xsltCleanupTemplates:\r
- * @style: an XSLT stylesheet\r
- *\r
- * Cleanup the state of the templates used by the stylesheet and\r
- * the ones it imports.\r
- */\r
-void\r
-xsltCleanupTemplates(xsltStylesheetPtr style ATTRIBUTE_UNUSED) {\r
-}\r
-\r
-/**\r
- * xsltFreeTemplateHashes:\r
- * @style: an XSLT stylesheet\r
- *\r
- * Free up the memory used by xsltAddTemplate/xsltGetTemplate mechanism\r
- */\r
-void\r
-xsltFreeTemplateHashes(xsltStylesheetPtr style) {\r
-    if (style->templatesHash != NULL)\r
-       xmlHashFree((xmlHashTablePtr) style->templatesHash,\r
-                   (xmlHashDeallocator) xsltFreeCompMatchList);\r
-    if (style->rootMatch != NULL)\r
-        xsltFreeCompMatchList(style->rootMatch);\r
-    if (style->keyMatch != NULL)\r
-        xsltFreeCompMatchList(style->keyMatch);\r
-    if (style->elemMatch != NULL)\r
-        xsltFreeCompMatchList(style->elemMatch);\r
-    if (style->attrMatch != NULL)\r
-        xsltFreeCompMatchList(style->attrMatch);\r
-    if (style->parentMatch != NULL)\r
-        xsltFreeCompMatchList(style->parentMatch);\r
-    if (style->textMatch != NULL)\r
-        xsltFreeCompMatchList(style->textMatch);\r
-    if (style->piMatch != NULL)\r
-        xsltFreeCompMatchList(style->piMatch);\r
-    if (style->commentMatch != NULL)\r
-        xsltFreeCompMatchList(style->commentMatch);\r
-}\r
-\r
+/*
+ * pattern.c: Implemetation of the template match compilation and lookup
+ *
+ * Reference:
+ *   http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+/*
+ * TODO: handle pathological cases like *[*[@a="b"]]
+ * TODO: detect [number] at compilation, optimize accordingly
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/valid.h>
+#include <libxml/hash.h>
+#include <libxml/xmlerror.h>
+#include <libxml/parserInternals.h>
+#include "xslt.h"
+#include "xsltInternals.h"
+#include "xsltutils.h"
+#include "imports.h"
+#include "templates.h"
+#include "keys.h"
+#include "pattern.h"
+#include "documents.h"
+
+#ifdef WITH_XSLT_DEBUG
+#define WITH_XSLT_DEBUG_PATTERN
+#endif
+
+/*
+ * Types are private:
+ */
+
+typedef enum {
+    XSLT_OP_END=0,
+    XSLT_OP_ROOT,
+    XSLT_OP_ELEM,
+    XSLT_OP_CHILD,
+    XSLT_OP_ATTR,
+    XSLT_OP_PARENT,
+    XSLT_OP_ANCESTOR,
+    XSLT_OP_ID,
+    XSLT_OP_KEY,
+    XSLT_OP_NS,
+    XSLT_OP_ALL,
+    XSLT_OP_PI,
+    XSLT_OP_COMMENT,
+    XSLT_OP_TEXT,
+    XSLT_OP_NODE,
+    XSLT_OP_PREDICATE
+} xsltOp;
+
+typedef struct _xsltStepState xsltStepState;
+typedef xsltStepState *xsltStepStatePtr;
+struct _xsltStepState {
+    int step;
+    xmlNodePtr node;
+};
+
+typedef struct _xsltStepStates xsltStepStates;
+typedef xsltStepStates *xsltStepStatesPtr;
+struct _xsltStepStates {
+    int nbstates;
+    int maxstates;
+    xsltStepStatePtr states;
+};
+
+typedef struct _xsltStepOp xsltStepOp;
+typedef xsltStepOp *xsltStepOpPtr;
+struct _xsltStepOp {
+    xsltOp op;
+    xmlChar *value;
+    xmlChar *value2;
+    xmlChar *value3;
+    xmlXPathCompExprPtr comp;
+    /*
+     * Optimisations for count
+     */
+    int        previousExtra;
+    int        indexExtra;
+    int        lenExtra;
+};
+
+struct _xsltCompMatch {
+    struct _xsltCompMatch *next; /* siblings in the name hash */
+    float priority;              /* the priority */
+    const xmlChar *pattern;       /* the pattern */
+    const xmlChar *mode;         /* the mode */
+    const xmlChar *modeURI;      /* the mode URI */
+    xsltTemplatePtr template;    /* the associated template */
+
+    int direct;
+    /* TODO fix the statically allocated size steps[] */
+    int nbStep;
+    int maxStep;
+    xmlNsPtr *nsList;          /* the namespaces in scope */
+    int nsNr;                  /* the number of namespaces in scope */
+    xsltStepOp steps[40];        /* ops for computation */
+};
+
+typedef struct _xsltParserContext xsltParserContext;
+typedef xsltParserContext *xsltParserContextPtr;
+struct _xsltParserContext {
+    xsltStylesheetPtr style;           /* the stylesheet */
+    xsltTransformContextPtr ctxt;      /* the transformation or NULL */
+    const xmlChar *cur;                        /* the current char being parsed */
+    const xmlChar *base;               /* the full expression */
+    xmlDocPtr      doc;                        /* the source document */
+    xmlNodePtr    elem;                        /* the source element */
+    int error;                         /* error code */
+    xsltCompMatchPtr comp;             /* the result */
+};
+
+/************************************************************************
+ *                                                                     *
+ *                     Type functions                                  *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltNewCompMatch:
+ *
+ * Create a new XSLT CompMatch
+ *
+ * Returns the newly allocated xsltCompMatchPtr or NULL in case of error
+ */
+static xsltCompMatchPtr
+xsltNewCompMatch(void) {
+    xsltCompMatchPtr cur;
+
+    cur = (xsltCompMatchPtr) xmlMalloc(sizeof(xsltCompMatch));
+    if (cur == NULL) {
+       xsltTransformError(NULL, NULL, NULL,
+               "xsltNewCompMatch : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltCompMatch));
+    cur->maxStep = 40;
+    cur->nsNr = 0;
+    cur->nsList = NULL;
+    cur->direct = 0;
+    return(cur);
+}
+
+/**
+ * xsltFreeCompMatch:
+ * @comp:  an XSLT comp
+ *
+ * Free up the memory allocated by @comp
+ */
+static void
+xsltFreeCompMatch(xsltCompMatchPtr comp) {
+    xsltStepOpPtr op;
+    int i;
+
+    if (comp == NULL)
+       return;
+    if (comp->pattern != NULL)
+       xmlFree((xmlChar *)comp->pattern);
+    if (comp->nsList != NULL)
+       xmlFree(comp->nsList);
+    for (i = 0;i < comp->nbStep;i++) {
+       op = &comp->steps[i];
+       if (op->value != NULL)
+           xmlFree(op->value);
+       if (op->value2 != NULL)
+           xmlFree(op->value2);
+       if (op->value3 != NULL)
+           xmlFree(op->value3);
+       if (op->comp != NULL)
+           xmlXPathFreeCompExpr(op->comp);
+    }
+    memset(comp, -1, sizeof(xsltCompMatch));
+    xmlFree(comp);
+}
+
+/**
+ * xsltFreeCompMatchList:
+ * @comp:  an XSLT comp list
+ *
+ * Free up the memory allocated by all the elements of @comp
+ */
+void
+xsltFreeCompMatchList(xsltCompMatchPtr comp) {
+    xsltCompMatchPtr cur;
+
+    while (comp != NULL) {
+       cur = comp;
+       comp = comp->next;
+       xsltFreeCompMatch(cur);
+    }
+}
+
+/**
+ * xsltNormalizeCompSteps:
+ * @payload: pointer to template hash table entry
+ * @data: pointer to the stylesheet
+ * @name: template match name
+ *
+ * This is a hashtable scanner function to normalize the compiled
+ * steps of an imported stylesheet.
+ */
+void xsltNormalizeCompSteps(void *payload,
+        void *data, const xmlChar *name ATTRIBUTE_UNUSED) {
+    xsltCompMatchPtr comp = payload;
+    xsltStylesheetPtr style = data;
+    int ix;
+
+    for (ix = 0; ix < comp->nbStep; ix++) {
+        comp->steps[ix].previousExtra += style->extrasNr;
+        comp->steps[ix].indexExtra += style->extrasNr;
+        comp->steps[ix].lenExtra += style->extrasNr;
+    }
+}
+
+/**
+ * xsltNewParserContext:
+ * @style:  the stylesheet
+ * @ctxt:  the transformation context, if done at run-time
+ *
+ * Create a new XSLT ParserContext
+ *
+ * Returns the newly allocated xsltParserContextPtr or NULL in case of error
+ */
+static xsltParserContextPtr
+xsltNewParserContext(xsltStylesheetPtr style, xsltTransformContextPtr ctxt) {
+    xsltParserContextPtr cur;
+
+    cur = (xsltParserContextPtr) xmlMalloc(sizeof(xsltParserContext));
+    if (cur == NULL) {
+       xsltTransformError(NULL, NULL, NULL,
+               "xsltNewParserContext : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltParserContext));
+    cur->style = style;
+    cur->ctxt = ctxt;
+    return(cur);
+}
+
+/**
+ * xsltFreeParserContext:
+ * @ctxt:  an XSLT parser context
+ *
+ * Free up the memory allocated by @ctxt
+ */
+static void
+xsltFreeParserContext(xsltParserContextPtr ctxt) {
+    if (ctxt == NULL)
+       return;
+    memset(ctxt, -1, sizeof(xsltParserContext));
+    xmlFree(ctxt);
+}
+
+/**
+ * xsltCompMatchAdd:
+ * @comp:  the compiled match expression
+ * @op:  an op
+ * @value:  the first value
+ * @value2:  the second value
+ * @novar:  flag to set XML_XPATH_NOVAR
+ *
+ * Add an step to an XSLT Compiled Match
+ *
+ * Returns -1 in case of failure, 0 otherwise.
+ */
+static int
+xsltCompMatchAdd(xsltParserContextPtr ctxt, xsltCompMatchPtr comp,
+                 xsltOp op, xmlChar * value, xmlChar * value2, int novar)
+{
+    if (comp->nbStep >= 40) {
+        xsltTransformError(NULL, NULL, NULL,
+                         "xsltCompMatchAdd: overflow\n");
+        return (-1);
+    }
+    comp->steps[comp->nbStep].op = op;
+    comp->steps[comp->nbStep].value = value;
+    comp->steps[comp->nbStep].value2 = value2;
+    if (ctxt->ctxt != NULL) {
+       comp->steps[comp->nbStep].previousExtra =
+           xsltAllocateExtraCtxt(ctxt->ctxt);
+       comp->steps[comp->nbStep].indexExtra =
+           xsltAllocateExtraCtxt(ctxt->ctxt);
+       comp->steps[comp->nbStep].lenExtra =
+           xsltAllocateExtraCtxt(ctxt->ctxt);
+    } else {
+       comp->steps[comp->nbStep].previousExtra =
+           xsltAllocateExtra(ctxt->style);
+       comp->steps[comp->nbStep].indexExtra =
+           xsltAllocateExtra(ctxt->style);
+       comp->steps[comp->nbStep].lenExtra =
+           xsltAllocateExtra(ctxt->style);
+    }
+    if (op == XSLT_OP_PREDICATE) {
+       xmlXPathContextPtr xctxt;
+
+       if (ctxt->style != NULL)
+           xctxt = xmlXPathNewContext(ctxt->style->doc);
+       else
+           xctxt = xmlXPathNewContext(NULL);
+#ifdef XML_XPATH_NOVAR
+       if (novar != 0)
+           xctxt->flags = XML_XPATH_NOVAR;
+#endif
+       if (ctxt->style != NULL)
+           xctxt->dict = ctxt->style->dict;
+       comp->steps[comp->nbStep].comp = xmlXPathCtxtCompile(xctxt, value);
+       xmlXPathFreeContext(xctxt);
+       if (comp->steps[comp->nbStep].comp == NULL) {
+           xsltTransformError(NULL, ctxt->style, ctxt->elem,
+                   "Failed to compile predicate\n");
+           if (ctxt->style != NULL)
+               ctxt->style->errors++;
+       }
+    }
+    comp->nbStep++;
+    return (0);
+}
+
+/**
+ * xsltSwapTopCompMatch:
+ * @comp:  the compiled match expression
+ *
+ * reverse the two top steps.
+ */
+static void
+xsltSwapTopCompMatch(xsltCompMatchPtr comp) {
+    int i;
+    int j = comp->nbStep - 1;
+
+    if (j > 0) {
+       register xmlChar *tmp;
+       register xsltOp op;
+       register xmlXPathCompExprPtr expr; 
+       i = j - 1;
+       tmp = comp->steps[i].value;
+       comp->steps[i].value = comp->steps[j].value;
+       comp->steps[j].value = tmp;
+       tmp = comp->steps[i].value2;
+       comp->steps[i].value2 = comp->steps[j].value2;
+       comp->steps[j].value2 = tmp;
+       op = comp->steps[i].op;
+       comp->steps[i].op = comp->steps[j].op;
+       comp->steps[j].op = op;
+       expr = comp->steps[i].comp;
+       comp->steps[i].comp = comp->steps[j].comp;
+       comp->steps[j].comp = expr;
+    }
+}
+
+/**
+ * xsltReverseCompMatch:
+ * @comp:  the compiled match expression
+ *
+ * reverse all the stack of expressions
+ */
+static void
+xsltReverseCompMatch(xsltCompMatchPtr comp) {
+    int i = 0;
+    int j = comp->nbStep - 1;
+
+    while (j > i) {
+       register xmlChar *tmp;
+       register xsltOp op;
+       register xmlXPathCompExprPtr expr; 
+       tmp = comp->steps[i].value;
+       comp->steps[i].value = comp->steps[j].value;
+       comp->steps[j].value = tmp;
+       tmp = comp->steps[i].value2;
+       comp->steps[i].value2 = comp->steps[j].value2;
+       comp->steps[j].value2 = tmp;
+       op = comp->steps[i].op;
+       comp->steps[i].op = comp->steps[j].op;
+       comp->steps[j].op = op;
+       expr = comp->steps[i].comp;
+       comp->steps[i].comp = comp->steps[j].comp;
+       comp->steps[j].comp = expr;
+       j--;
+       i++;
+    }
+    comp->steps[comp->nbStep++].op = XSLT_OP_END;
+    /*
+     * detect consecutive XSLT_OP_PREDICATE indicating a direct
+     * matching should be done.
+     */
+    for (i = 0;i < comp->nbStep - 1;i++) {
+        if ((comp->steps[i].op == XSLT_OP_PREDICATE) &&
+           (comp->steps[i + 1].op == XSLT_OP_PREDICATE)) {
+
+           comp->direct = 1;
+           if (comp->pattern[0] != '/') {
+               xmlChar *query;
+
+               query = xmlStrdup((const xmlChar *)"//");
+               query = xmlStrcat(query, comp->pattern);
+
+               xmlFree((xmlChar *) comp->pattern);
+               comp->pattern = query;
+           }
+           break;
+       }
+    }
+}
+
+/************************************************************************
+ *                                                                     *
+ *             The interpreter for the precompiled patterns            *
+ *                                                                     *
+ ************************************************************************/
+
+static int
+xsltPatPushState(xsltStepStates *states, int step, xmlNodePtr node) {
+    if ((states->states == NULL) || (states->maxstates <= 0)) {
+        states->maxstates = 4;
+       states->nbstates = 0;
+       states->states = xmlMalloc(4 * sizeof(xsltStepState));
+    }
+    else if (states->maxstates <= states->nbstates) {
+        xsltStepState *tmp;
+
+       tmp = (xsltStepStatePtr) xmlRealloc(states->states,
+                              2 * states->maxstates * sizeof(xsltStepState));
+       if (tmp == NULL)
+           return(-1);
+       states->states = tmp;
+       states->maxstates *= 2;
+    }
+    states->states[states->nbstates].step = step;
+    states->states[states->nbstates++].node = node;
+#if 0
+    fprintf(stderr, "Push: %d, %s\n", step, node->name);
+#endif
+    return(0);
+}
+
+/**
+ * xsltTestCompMatchDirect:
+ * @ctxt:  a XSLT process context
+ * @comp: the precompiled pattern
+ * @node: a node
+ *
+ * Test whether the node matches the pattern, do a direct evalutation
+ * and not a step by step evaluation.
+ *
+ * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
+ */
+static int
+xsltTestCompMatchDirect(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
+                       xmlNodePtr node) {
+    xsltStepOpPtr sel = NULL;
+    xmlDocPtr prevdoc;
+    xmlDocPtr doc;
+    xmlXPathObjectPtr list;
+    int ix, j;
+    int nocache = 0;
+    int isRVT;
+
+    doc = node->doc;
+    if (XSLT_IS_RES_TREE_FRAG(doc))
+       isRVT = 1;
+    else
+       isRVT = 0;
+    sel = &comp->steps[0]; /* store extra in first step arbitrarily */
+
+    prevdoc = (xmlDocPtr)
+       XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
+    ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);
+    list = (xmlXPathObjectPtr)
+       XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra);
+    
+    if ((list == NULL) || (prevdoc != doc)) {
+       xmlXPathObjectPtr newlist;
+       xmlNodePtr parent = node->parent;
+       xmlDocPtr olddoc;
+       xmlNodePtr oldnode;
+
+       oldnode = ctxt->xpathCtxt->node;
+       olddoc = ctxt->xpathCtxt->doc;
+       ctxt->xpathCtxt->node = node;
+       ctxt->xpathCtxt->doc = doc;
+       newlist = xmlXPathEval(comp->pattern, ctxt->xpathCtxt);
+       ctxt->xpathCtxt->node = oldnode;
+       ctxt->xpathCtxt->doc = olddoc;
+       if (newlist == NULL)
+           return(-1);
+       if (newlist->type != XPATH_NODESET) {
+           xmlXPathFreeObject(newlist);
+           return(-1);
+       }
+       ix = 0;
+
+       if ((parent == NULL) || (node->doc == NULL) || isRVT)
+           nocache = 1;
+       
+       if (nocache == 0) {
+           if (list != NULL)
+               xmlXPathFreeObject(list);
+           list = newlist;
+
+           XSLT_RUNTIME_EXTRA_LST(ctxt, sel->lenExtra) =
+               (void *) list;
+           XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =
+               (void *) doc;
+           XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =
+               0;
+           XSLT_RUNTIME_EXTRA_FREE(ctxt, sel->lenExtra) =
+               (xmlFreeFunc) xmlXPathFreeObject;
+       } else
+           list = newlist;
+    }
+    if ((list->nodesetval == NULL) ||
+       (list->nodesetval->nodeNr <= 0)) {
+       if (nocache == 1)
+           xmlXPathFreeObject(list);
+       return(0);
+    }
+    /* TODO: store the index and use it for the scan */
+    if (ix == 0) {
+       for (j = 0;j < list->nodesetval->nodeNr;j++) {
+           if (list->nodesetval->nodeTab[j] == node) {
+               if (nocache == 1)
+                   xmlXPathFreeObject(list);
+               return(1);
+           }
+       }
+    } else {
+    }
+    if (nocache == 1)
+       xmlXPathFreeObject(list);
+    return(0);
+}
+
+/**
+ * xsltTestCompMatch:
+ * @ctxt:  a XSLT process context
+ * @comp: the precompiled pattern
+ * @node: a node
+ * @mode:  the mode name or NULL
+ * @modeURI:  the mode URI or NULL
+ *
+ * Test whether the node matches the pattern
+ *
+ * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
+ */
+static int
+xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp,
+                 xmlNodePtr node, const xmlChar *mode,
+                 const xmlChar *modeURI) {
+    int i;
+    xsltStepOpPtr step, sel = NULL;
+    xsltStepStates states = {0, 0, NULL}; /* // may require backtrack */
+
+    if ((comp == NULL) || (node == NULL) || (ctxt == NULL)) {
+       xsltTransformError(ctxt, NULL, node,
+               "xsltTestCompMatch: null arg\n");
+        return(-1);
+    }
+    if (mode != NULL) {
+       if (comp->mode == NULL)
+           return(0);
+       /*
+        * both mode strings must be interned on the stylesheet dictionary
+        */
+       if (comp->mode != mode)
+           return(0);
+    } else {
+       if (comp->mode != NULL)
+           return(0);
+    }
+    if (modeURI != NULL) {
+       if (comp->modeURI == NULL)
+           return(0);
+       /*
+        * both modeURI strings must be interned on the stylesheet dictionary
+        */
+       if (comp->modeURI != modeURI)
+           return(0);
+    } else {
+       if (comp->modeURI != NULL)
+           return(0);
+    }
+
+    i = 0;
+restart:
+    for (;i < comp->nbStep;i++) {
+       step = &comp->steps[i];
+       if (step->op != XSLT_OP_PREDICATE)
+           sel = step;
+       switch (step->op) {
+            case XSLT_OP_END:
+               goto found;
+            case XSLT_OP_ROOT:
+               if ((node->type == XML_DOCUMENT_NODE) ||
+#ifdef LIBXML_DOCB_ENABLED
+                   (node->type == XML_DOCB_DOCUMENT_NODE) ||
+#endif
+                   (node->type == XML_HTML_DOCUMENT_NODE))
+                   continue;
+               if ((node->type == XML_ELEMENT_NODE) && (node->name[0] == ' '))
+                   continue;
+               goto rollback;
+            case XSLT_OP_ELEM:
+               if (node->type != XML_ELEMENT_NODE)
+                   goto rollback;
+               if (step->value == NULL)
+                   continue;
+               if (step->value[0] != node->name[0])
+                   goto rollback;
+               if (!xmlStrEqual(step->value, node->name))
+                   goto rollback;
+
+               /* Namespace test */
+               if (node->ns == NULL) {
+                   if (step->value2 != NULL)
+                       goto rollback;
+               } else if (node->ns->href != NULL) {
+                   if (step->value2 == NULL)
+                       goto rollback;
+                   if (!xmlStrEqual(step->value2, node->ns->href))
+                       goto rollback;
+               }
+               continue;
+            case XSLT_OP_CHILD: {
+               xmlNodePtr lst;
+
+               if ((node->type != XML_ELEMENT_NODE) &&
+                   (node->type != XML_DOCUMENT_NODE) &&
+#ifdef LIBXML_DOCB_ENABLED
+                   (node->type != XML_DOCB_DOCUMENT_NODE) &&
+#endif
+                   (node->type != XML_HTML_DOCUMENT_NODE))
+                   goto rollback;
+
+               lst = node->children;
+
+               if (step->value != NULL) {
+                   while (lst != NULL) {
+                       if ((lst->type == XML_ELEMENT_NODE) &&
+                           (step->value[0] == lst->name[0]) &&
+                           (xmlStrEqual(step->value, lst->name)))
+                           break;
+                       lst = lst->next;
+                   }
+                   if (lst != NULL)
+                       continue;
+               }
+               goto rollback;
+           }
+            case XSLT_OP_ATTR:
+               if (node->type != XML_ATTRIBUTE_NODE)
+                   goto rollback;
+               if (step->value != NULL) {
+                   if (step->value[0] != node->name[0])
+                       goto rollback;
+                   if (!xmlStrEqual(step->value, node->name))
+                       goto rollback;
+               }
+               /* Namespace test */
+               if (node->ns == NULL) {
+                   if (step->value2 != NULL)
+                       goto rollback;
+               } else if (step->value2 != NULL) {
+                   if (!xmlStrEqual(step->value2, node->ns->href))
+                       goto rollback;
+               }
+               continue;
+            case XSLT_OP_PARENT:
+               if ((node->type == XML_DOCUMENT_NODE) ||
+                   (node->type == XML_HTML_DOCUMENT_NODE) ||
+#ifdef LIBXML_DOCB_ENABLED
+                   (node->type == XML_DOCB_DOCUMENT_NODE) ||
+#endif
+                   (node->type == XML_NAMESPACE_DECL))
+                   goto rollback;
+               node = node->parent;
+               if (node == NULL)
+                   goto rollback;
+               if (step->value == NULL)
+                   continue;
+               if (step->value[0] != node->name[0])
+                   goto rollback;
+               if (!xmlStrEqual(step->value, node->name))
+                   goto rollback;
+               /* Namespace test */
+               if (node->ns == NULL) {
+                   if (step->value2 != NULL)
+                       goto rollback;
+               } else if (node->ns->href != NULL) {
+                   if (step->value2 == NULL)
+                       goto rollback;
+                   if (!xmlStrEqual(step->value2, node->ns->href))
+                       goto rollback;
+               }
+               continue;
+            case XSLT_OP_ANCESTOR:
+               /* TODO: implement coalescing of ANCESTOR/NODE ops */
+               if (step->value == NULL) {
+                   step = &comp->steps[i+1];
+                   if (step->op == XSLT_OP_ROOT)
+                       goto found;
+                   /* added NS, ID and KEY as a result of bug 168208 */
+                   if ((step->op != XSLT_OP_ELEM) && 
+                       (step->op != XSLT_OP_ALL) && 
+                       (step->op != XSLT_OP_NS) &&
+                       (step->op != XSLT_OP_ID) &&
+                       (step->op != XSLT_OP_KEY))
+                       goto rollback;
+               }
+               if (node == NULL)
+                   goto rollback;
+               if ((node->type == XML_DOCUMENT_NODE) ||
+                   (node->type == XML_HTML_DOCUMENT_NODE) ||
+#ifdef LIBXML_DOCB_ENABLED
+                   (node->type == XML_DOCB_DOCUMENT_NODE) ||
+#endif
+                   (node->type == XML_NAMESPACE_DECL))
+                   goto rollback;
+               node = node->parent;
+               if ((step->op != XSLT_OP_ELEM) && step->op != XSLT_OP_ALL) {
+                   xsltPatPushState(&states, i, node);
+                   continue;
+               }
+               i++;
+               if (step->value == NULL) {
+                   xsltPatPushState(&states, i - 1, node);
+                   continue;
+               }
+               while (node != NULL) {
+                   if ((node->type == XML_ELEMENT_NODE) &&
+                       (step->value[0] == node->name[0]) &&
+                       (xmlStrEqual(step->value, node->name))) {
+                       /* Namespace test */
+                       if (node->ns == NULL) {
+                           if (step->value2 == NULL)
+                               break;
+                       } else if (node->ns->href != NULL) {
+                           if ((step->value2 != NULL) &&
+                               (xmlStrEqual(step->value2, node->ns->href)))
+                               break;
+                       }
+                   }
+                   node = node->parent;
+               }
+               if (node == NULL)
+                   goto rollback;
+               xsltPatPushState(&states, i - 1, node);
+               continue;
+            case XSLT_OP_ID: {
+               /* TODO Handle IDs decently, must be done differently */
+               xmlAttrPtr id;
+
+               if (node->type != XML_ELEMENT_NODE)
+                   goto rollback;
+
+               id = xmlGetID(node->doc, step->value);
+               if ((id == NULL) || (id->parent != node))
+                   goto rollback;
+               break;
+           }
+            case XSLT_OP_KEY: {
+               xmlNodeSetPtr list;
+               int indx;
+
+               list = xsltGetKey(ctxt, step->value,
+                                 step->value3, step->value2);
+               if (list == NULL)
+                   goto rollback;
+               for (indx = 0;indx < list->nodeNr;indx++)
+                   if (list->nodeTab[indx] == node)
+                       break;
+               if (indx >= list->nodeNr)
+                   goto rollback;
+               break;
+           }
+            case XSLT_OP_NS:
+               if (node->type != XML_ELEMENT_NODE)
+                   goto rollback;
+               if (node->ns == NULL) {
+                   if (step->value != NULL)
+                       goto rollback;
+               } else if (node->ns->href != NULL) {
+                   if (step->value == NULL)
+                       goto rollback;
+                   if (!xmlStrEqual(step->value, node->ns->href))
+                       goto rollback;
+               }
+               break;
+            case XSLT_OP_ALL:
+               if (node->type != XML_ELEMENT_NODE)
+                   goto rollback;
+               break;
+           case XSLT_OP_PREDICATE: {
+               xmlNodePtr oldNode;
+               xmlDocPtr doc;
+               int oldCS, oldCP;
+               int pos = 0, len = 0;
+               int isRVT;
+
+               /*
+                * when there is cascading XSLT_OP_PREDICATE, then use a
+                * direct computation approach. It's not done directly
+                * at the beginning of the routine to filter out as much
+                * as possible this costly computation.
+                */
+               if (comp->direct) {
+                   if (states.states != NULL) {
+                       /* Free the rollback states */
+                       xmlFree(states.states);
+                   }
+                   return(xsltTestCompMatchDirect(ctxt, comp, node));
+               }
+
+               doc = node->doc;
+               if (XSLT_IS_RES_TREE_FRAG(doc))
+                   isRVT = 1;
+               else
+                   isRVT = 0;
+
+               /*
+                * Depending on the last selection, one may need to
+                * recompute contextSize and proximityPosition.
+                */
+               oldCS = ctxt->xpathCtxt->contextSize;
+               oldCP = ctxt->xpathCtxt->proximityPosition;
+               if ((sel != NULL) &&
+                   (sel->op == XSLT_OP_ELEM) &&
+                   (sel->value != NULL) &&
+                   (node->type == XML_ELEMENT_NODE) &&
+                   (node->parent != NULL)) {
+                   xmlNodePtr previous;
+                   int ix, nocache = 0;
+
+                   previous = (xmlNodePtr)
+                       XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
+                   ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);
+                   if ((previous != NULL) &&
+                       (previous->parent == node->parent)) {
+                       /*
+                        * just walk back to adjust the index
+                        */
+                       int indx = 0;
+                       xmlNodePtr sibling = node;
+
+                       while (sibling != NULL) {
+                           if (sibling == previous)
+                               break;
+                           if ((previous->type == XML_ELEMENT_NODE) &&
+                               (previous->name != NULL) &&
+                               (sibling->name != NULL) &&
+                               (previous->name[0] == sibling->name[0]) &&
+                               (xmlStrEqual(previous->name, sibling->name)))
+                           {
+                               if ((sel->value2 == NULL) ||
+                                   ((sibling->ns != NULL) &&
+                                    (xmlStrEqual(sel->value2,
+                                                 sibling->ns->href))))
+                                   indx++;
+                           }
+                           sibling = sibling->prev;
+                       }
+                       if (sibling == NULL) {
+                           /* hum going backward in document order ... */
+                           indx = 0;
+                           sibling = node;
+                           while (sibling != NULL) {
+                               if (sibling == previous)
+                                   break;
+                               if ((previous->type == XML_ELEMENT_NODE) &&
+                                   (previous->name != NULL) &&
+                                   (sibling->name != NULL) &&
+                                   (previous->name[0] == sibling->name[0]) &&
+                                   (xmlStrEqual(previous->name, sibling->name)))
+                               {
+                                   if ((sel->value2 == NULL) ||
+                                       ((sibling->ns != NULL) &&
+                                       (xmlStrEqual(sel->value2,
+                                       sibling->ns->href))))
+                                   {
+                                       indx--;
+                                   }
+                               }
+                               sibling = sibling->next;
+                           }
+                       }
+                       if (sibling != NULL) {
+                           pos = ix + indx;
+                           /*
+                            * If the node is in a Value Tree we need to
+                            * save len, but cannot cache the node!
+                            * (bugs 153137 and 158840)
+                            */
+                           if (node->doc != NULL) {
+                               len = XSLT_RUNTIME_EXTRA(ctxt,
+                                       sel->lenExtra, ival);
+                               if (!isRVT) {
+                                   XSLT_RUNTIME_EXTRA(ctxt,
+                                       sel->previousExtra, ptr) = node;
+                                   XSLT_RUNTIME_EXTRA(ctxt,
+                                       sel->indexExtra, ival) = pos;
+                               }
+                           }
+                           ix = pos;
+                       } else
+                           pos = 0;
+                   } else {
+                       /*
+                        * recompute the index
+                        */
+                       xmlNodePtr siblings = node->parent->children;
+                       xmlNodePtr parent = node->parent;
+
+                       while (siblings != NULL) {
+                           if (siblings->type == XML_ELEMENT_NODE) {
+                               if (siblings == node) {
+                                   len++;
+                                   pos = len;
+                               } else if ((node->name != NULL) &&
+                                          (siblings->name != NULL) &&
+                                   (node->name[0] == siblings->name[0]) &&
+                                   (xmlStrEqual(node->name, siblings->name))) {
+                                   if ((sel->value2 == NULL) ||
+                                       ((siblings->ns != NULL) &&
+                                        (xmlStrEqual(sel->value2,
+                                                     siblings->ns->href))))
+                                       len++;
+                               }
+                           }
+                           siblings = siblings->next;
+                       }
+                       if ((parent == NULL) || (node->doc == NULL))
+                           nocache = 1;
+                       else {
+                           while (parent->parent != NULL)
+                               parent = parent->parent;
+                           if (((parent->type != XML_DOCUMENT_NODE) &&
+                                (parent->type != XML_HTML_DOCUMENT_NODE)) ||
+                                (parent != (xmlNodePtr) node->doc))
+                               nocache = 1;
+                       }
+                   }
+                   if (pos != 0) {
+                       ctxt->xpathCtxt->contextSize = len;
+                       ctxt->xpathCtxt->proximityPosition = pos;
+                       /*
+                        * If the node is in a Value Tree we cannot
+                        * cache it !
+                        */
+                       if ((!isRVT) && (node->doc != NULL) &&
+                           (nocache == 0)) {
+                           XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =
+                               node;
+                           XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =
+                               pos;
+                           XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) =
+                               len;
+                       }
+                   }
+               } else if ((sel != NULL) && (sel->op == XSLT_OP_ALL) &&
+                          (node->type == XML_ELEMENT_NODE)) {
+                   xmlNodePtr previous;
+                   int ix, nocache = 0;
+
+                   previous = (xmlNodePtr)
+                       XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr);
+                   ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival);
+                   if ((previous != NULL) &&
+                       (previous->parent == node->parent)) {
+                       /*
+                        * just walk back to adjust the index
+                        */
+                       int indx = 0;
+                       xmlNodePtr sibling = node;
+
+                       while (sibling != NULL) {
+                           if (sibling == previous)
+                               break;
+                           if (sibling->type == XML_ELEMENT_NODE)
+                               indx++;
+                           sibling = sibling->prev;
+                       }
+                       if (sibling == NULL) {
+                           /* hum going backward in document order ... */
+                           indx = 0;
+                           sibling = node;
+                           while (sibling != NULL) {
+                               if (sibling == previous)
+                                   break;
+                               if (sibling->type == XML_ELEMENT_NODE)
+                                   indx--;
+                               sibling = sibling->next;
+                           }
+                       }
+                       if (sibling != NULL) {
+                           pos = ix + indx;
+                           /*
+                            * If the node is in a Value Tree we cannot
+                            * cache it !
+                            */
+                           if ((node->doc != NULL) && !isRVT) {
+                               len = XSLT_RUNTIME_EXTRA(ctxt,
+                                       sel->lenExtra, ival);
+                               XSLT_RUNTIME_EXTRA(ctxt,
+                                       sel->previousExtra, ptr) = node;
+                               XSLT_RUNTIME_EXTRA(ctxt,
+                                       sel->indexExtra, ival) = pos;
+                           }
+                       } else
+                           pos = 0;
+                   } else {
+                       /*
+                        * recompute the index
+                        */
+                       xmlNodePtr siblings = node->parent->children;
+                       xmlNodePtr parent = node->parent;
+
+                       while (siblings != NULL) {
+                           if (siblings->type == XML_ELEMENT_NODE) {
+                               len++;
+                               if (siblings == node) {
+                                   pos = len;
+                               }
+                           }
+                           siblings = siblings->next;
+                       }
+                       if ((parent == NULL) || (node->doc == NULL))
+                           nocache = 1;
+                       else {
+                           while (parent->parent != NULL)
+                               parent = parent->parent;
+                           if (((parent->type != XML_DOCUMENT_NODE) &&
+                                (parent->type != XML_HTML_DOCUMENT_NODE)) ||
+                                (parent != (xmlNodePtr) node->doc))
+                               nocache = 1;
+                       }
+                   }
+                   if (pos != 0) {
+                       ctxt->xpathCtxt->contextSize = len;
+                       ctxt->xpathCtxt->proximityPosition = pos;
+                       /*
+                        * If the node is in a Value Tree we cannot
+                        * cache it !
+                        */
+                       if ((node->doc != NULL) && (nocache == 0) && !isRVT) {
+                           XSLT_RUNTIME_EXTRA(ctxt, sel->previousExtra, ptr) =
+                               node;
+                           XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival) =
+                               pos;
+                           XSLT_RUNTIME_EXTRA(ctxt, sel->lenExtra, ival) =
+                               len;
+                       }
+                   }
+               }
+               oldNode = ctxt->node;
+               ctxt->node = node;
+
+               if (step->value == NULL)
+                   goto wrong_index;
+               if (step->comp == NULL)
+                   goto wrong_index;
+
+               if (!xsltEvalXPathPredicate(ctxt, step->comp, comp->nsList,
+                                           comp->nsNr))
+                   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;
+               goto rollback;
+           }
+            case XSLT_OP_PI:
+               if (node->type != XML_PI_NODE)
+                   goto rollback;
+               if (step->value != NULL) {
+                   if (!xmlStrEqual(step->value, node->name))
+                       goto rollback;
+               }
+               break;
+            case XSLT_OP_COMMENT:
+               if (node->type != XML_COMMENT_NODE)
+                   goto rollback;
+               break;
+            case XSLT_OP_TEXT:
+               if ((node->type != XML_TEXT_NODE) &&
+                   (node->type != XML_CDATA_SECTION_NODE))
+                   goto rollback;
+               break;
+            case XSLT_OP_NODE:
+               switch (node->type) {
+                   case XML_ELEMENT_NODE:
+                   case XML_CDATA_SECTION_NODE:
+                   case XML_PI_NODE:
+                   case XML_COMMENT_NODE:
+                   case XML_TEXT_NODE:
+                       break;
+                   default:
+                       goto rollback;
+               }
+               break;
+       }
+    }
+found:
+    if (states.states != NULL) {
+        /* Free the rollback states */
+       xmlFree(states.states);
+    }
+    return(1);
+rollback:
+    /* got an error try to rollback */
+    if (states.states == NULL)
+       return(0);
+    if (states.nbstates <= 0) {
+       xmlFree(states.states);
+       return(0);
+    }
+    states.nbstates--;
+    i = states.states[states.nbstates].step;
+    node = states.states[states.nbstates].node;
+#if 0
+    fprintf(stderr, "Pop: %d, %s\n", i, node->name);
+#endif
+    goto restart;
+}
+
+/**
+ * xsltTestCompMatchList:
+ * @ctxt:  a XSLT process context
+ * @node: a node
+ * @comp: the precompiled pattern list
+ *
+ * Test whether the node matches one of the patterns in the list
+ *
+ * Returns 1 if it matches, 0 if it doesn't and -1 in case of failure
+ */
+int
+xsltTestCompMatchList(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                     xsltCompMatchPtr comp) {
+    int ret;
+
+    if ((ctxt == NULL) || (node == NULL))
+       return(-1);
+    while (comp != NULL) {
+       ret = xsltTestCompMatch(ctxt, comp, node, NULL, NULL);
+       if (ret == 1)
+           return(1);
+       comp = comp->next;
+    }
+    return(0);
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Dedicated parser for templates                  *
+ *                                                                     *
+ ************************************************************************/
+
+#define CUR (*ctxt->cur)
+#define SKIP(val) ctxt->cur += (val)
+#define NXT(val) ctxt->cur[(val)]
+#define CUR_PTR ctxt->cur
+
+#define SKIP_BLANKS                                                    \
+    while (IS_BLANK_CH(CUR)) NEXT
+
+#define CURRENT (*ctxt->cur)
+#define NEXT ((*ctxt->cur) ?  ctxt->cur++: ctxt->cur)
+
+
+#define PUSH(op, val, val2, novar)                                             \
+    if (xsltCompMatchAdd(ctxt, ctxt->comp, (op), (val), (val2), (novar))) goto error;
+
+#define SWAP()                                                 \
+    xsltSwapTopCompMatch(ctxt->comp);
+
+#define XSLT_ERROR(X)                                                  \
+    { xsltError(ctxt, __FILE__, __LINE__, X);                  \
+      ctxt->error = (X); return; }
+
+#define XSLT_ERROR0(X)                                                 \
+    { xsltError(ctxt, __FILE__, __LINE__, X);                  \
+      ctxt->error = (X); return(0); }
+
+/**
+ * xsltScanLiteral:
+ * @ctxt:  the XPath Parser context
+ *
+ * Parse an XPath Litteral:
+ *
+ * [29] Literal ::= '"' [^"]* '"'
+ *                | "'" [^']* "'"
+ *
+ * Returns the Literal parsed or NULL
+ */
+
+static xmlChar *
+xsltScanLiteral(xsltParserContextPtr ctxt) {
+    const xmlChar *q, *cur;
+    xmlChar *ret = NULL;
+    int val, len;
+
+    SKIP_BLANKS;
+    if (CUR == '"') {
+        NEXT;
+       cur = q = CUR_PTR;
+       val = xmlStringCurrentChar(NULL, cur, &len);
+       while ((IS_CHAR(val)) && (val != '"')) {
+           cur += len;
+           val = xmlStringCurrentChar(NULL, cur, &len);
+       }
+       if (!IS_CHAR(val)) {
+           ctxt->error = 1;
+           return(NULL);
+       } else {
+           ret = xmlStrndup(q, cur - q);
+        }
+       cur += len;
+       CUR_PTR = cur;
+    } else if (CUR == '\'') {
+        NEXT;
+       cur = q = CUR_PTR;
+       val = xmlStringCurrentChar(NULL, cur, &len);
+       while ((IS_CHAR(val)) && (val != '\'')) {
+           cur += len;
+           val = xmlStringCurrentChar(NULL, cur, &len);
+       }
+       if (!IS_CHAR(val)) {
+           ctxt->error = 1;
+           return(NULL);
+       } else {
+           ret = xmlStrndup(q, cur - q);
+        }
+       cur += len;
+       CUR_PTR = cur;
+    } else {
+       /* XP_ERROR(XPATH_START_LITERAL_ERROR); */
+       ctxt->error = 1;
+       return(NULL);
+    }
+    return(ret);
+}
+
+/**
+ * xsltScanName:
+ * @ctxt:  the XPath Parser context
+ *
+ * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | 
+ *                  CombiningChar | Extender
+ *
+ * [5] Name ::= (Letter | '_' | ':') (NameChar)*
+ *
+ * [6] Names ::= Name (S Name)*
+ *
+ * Returns the Name parsed or NULL
+ */
+
+static xmlChar *
+xsltScanName(xsltParserContextPtr ctxt) {
+    const xmlChar *q, *cur;
+    xmlChar *ret = NULL;
+    int val, len;
+
+    SKIP_BLANKS;
+
+    cur = q = CUR_PTR;
+    val = xmlStringCurrentChar(NULL, cur, &len);
+    if (!IS_LETTER(val) && (val != '_') && (val != ':'))
+       return(NULL);
+
+    while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||
+           (val == '.') || (val == '-') ||
+          (val == '_') || 
+          (IS_COMBINING(val)) ||
+          (IS_EXTENDER(val))) {
+       cur += len;
+       val = xmlStringCurrentChar(NULL, cur, &len);
+    }
+    ret = xmlStrndup(q, cur - q);
+    CUR_PTR = cur;
+    return(ret);
+}
+
+/**
+ * xsltScanNCName:
+ * @ctxt:  the XPath Parser context
+ *
+ * Parses a non qualified name
+ *
+ * Returns the Name parsed or NULL
+ */
+
+static xmlChar *
+xsltScanNCName(xsltParserContextPtr ctxt) {
+    const xmlChar *q, *cur;
+    xmlChar *ret = NULL;
+    int val, len;
+
+    SKIP_BLANKS;
+
+    cur = q = CUR_PTR;
+    val = xmlStringCurrentChar(NULL, cur, &len);
+    if (!IS_LETTER(val) && (val != '_'))
+       return(NULL);
+
+    while ((IS_LETTER(val)) || (IS_DIGIT(val)) ||
+           (val == '.') || (val == '-') ||
+          (val == '_') ||
+          (IS_COMBINING(val)) ||
+          (IS_EXTENDER(val))) {
+       cur += len;
+       val = xmlStringCurrentChar(NULL, cur, &len);
+    }
+    ret = xmlStrndup(q, cur - q);
+    CUR_PTR = cur;
+    return(ret);
+}
+
+/**
+ * xsltScanQName:
+ * @ctxt:  the XPath Parser context
+ * @prefix:  the place to store the prefix
+ *
+ * Parse a qualified name
+ *
+ * Returns the Name parsed or NULL
+ */
+
+static xmlChar *
+xsltScanQName(xsltParserContextPtr ctxt, xmlChar **prefix) {
+    xmlChar *ret = NULL;
+
+    *prefix = NULL;
+    ret = xsltScanNCName(ctxt);
+    if (CUR == ':') {
+        *prefix = ret;
+       NEXT;
+       ret = xsltScanNCName(ctxt);
+    }
+    return(ret);
+}
+
+/*
+ * xsltCompileIdKeyPattern:
+ * @ctxt:  the compilation context
+ * @name:  a preparsed name
+ * @aid:  whether id/key are allowed there
+ * @novar:  flag to prohibit xslt var
+ *
+ * Compile the XSLT LocationIdKeyPattern
+ * [3] IdKeyPattern ::= 'id' '(' Literal ')'
+ *                    | 'key' '(' Literal ',' Literal ')'
+ *
+ * also handle NodeType and PI from:
+ *
+ * [7]  NodeTest ::= NameTest
+ *                 | NodeType '(' ')'
+ *                 | 'processing-instruction' '(' Literal ')'
+ */
+static void
+xsltCompileIdKeyPattern(xsltParserContextPtr ctxt, xmlChar *name,
+               int aid, int novar) {
+    xmlChar *lit = NULL;
+    xmlChar *lit2 = NULL;
+
+    if (CUR != '(') {
+       xsltTransformError(NULL, NULL, NULL,
+               "xsltCompileIdKeyPattern : ( expected\n");
+       ctxt->error = 1;
+       return;
+    }
+    if ((aid) && (xmlStrEqual(name, (const xmlChar *)"id"))) {
+       NEXT;
+       SKIP_BLANKS;
+        lit = xsltScanLiteral(ctxt);
+       if (ctxt->error)
+           return;
+       SKIP_BLANKS;
+       if (CUR != ')') {
+           xsltTransformError(NULL, NULL, NULL,
+                   "xsltCompileIdKeyPattern : ) expected\n");
+           ctxt->error = 1;
+           return;
+       }
+       NEXT;
+       PUSH(XSLT_OP_ID, lit, NULL, novar);
+    } else if ((aid) && (xmlStrEqual(name, (const xmlChar *)"key"))) {
+       NEXT;
+       SKIP_BLANKS;
+        lit = xsltScanLiteral(ctxt);
+       if (ctxt->error)
+           return;
+       SKIP_BLANKS;
+       if (CUR != ',') {
+           xsltTransformError(NULL, NULL, NULL,
+                   "xsltCompileIdKeyPattern : , expected\n");
+           ctxt->error = 1;
+           return;
+       }
+       NEXT;
+       SKIP_BLANKS;
+        lit2 = xsltScanLiteral(ctxt);
+       if (ctxt->error)
+           return;
+       SKIP_BLANKS;
+       if (CUR != ')') {
+           xsltTransformError(NULL, NULL, NULL,
+                   "xsltCompileIdKeyPattern : ) expected\n");
+           ctxt->error = 1;
+           return;
+       }
+       NEXT;
+       /* URGENT TODO: support namespace in keys */
+       PUSH(XSLT_OP_KEY, lit, lit2, novar);
+    } else if (xmlStrEqual(name, (const xmlChar *)"processing-instruction")) {
+       NEXT;
+       SKIP_BLANKS;
+       if (CUR != ')') {
+           lit = xsltScanLiteral(ctxt);
+           if (ctxt->error)
+               return;
+           SKIP_BLANKS;
+           if (CUR != ')') {
+               xsltTransformError(NULL, NULL, NULL,
+                       "xsltCompileIdKeyPattern : ) expected\n");
+               ctxt->error = 1;
+               return;
+           }
+       }
+       NEXT;
+       PUSH(XSLT_OP_PI, lit, NULL, novar);
+    } else if (xmlStrEqual(name, (const xmlChar *)"text")) {
+       NEXT;
+       SKIP_BLANKS;
+       if (CUR != ')') {
+           xsltTransformError(NULL, NULL, NULL,
+                   "xsltCompileIdKeyPattern : ) expected\n");
+           ctxt->error = 1;
+           return;
+       }
+       NEXT;
+       PUSH(XSLT_OP_TEXT, NULL, NULL, novar);
+    } else if (xmlStrEqual(name, (const xmlChar *)"comment")) {
+       NEXT;
+       SKIP_BLANKS;
+       if (CUR != ')') {
+           xsltTransformError(NULL, NULL, NULL,
+                   "xsltCompileIdKeyPattern : ) expected\n");
+           ctxt->error = 1;
+           return;
+       }
+       NEXT;
+       PUSH(XSLT_OP_COMMENT, NULL, NULL, novar);
+    } else if (xmlStrEqual(name, (const xmlChar *)"node")) {
+       NEXT;
+       SKIP_BLANKS;
+       if (CUR != ')') {
+           xsltTransformError(NULL, NULL, NULL,
+                   "xsltCompileIdKeyPattern : ) expected\n");
+           ctxt->error = 1;
+           return;
+       }
+       NEXT;
+       PUSH(XSLT_OP_NODE, NULL, NULL, novar);
+    } else if (aid) {
+       xsltTransformError(NULL, NULL, NULL,
+           "xsltCompileIdKeyPattern : expecting 'key' or 'id' or node type\n");
+       ctxt->error = 1;
+       return;
+    } else {
+       xsltTransformError(NULL, NULL, NULL,
+           "xsltCompileIdKeyPattern : node type\n");
+       ctxt->error = 1;
+       return;
+    }
+error:
+    if (name != NULL)
+       xmlFree(name);
+}
+
+/**
+ * xsltCompileStepPattern:
+ * @ctxt:  the compilation context
+ * @token:  a posible precompiled name
+ * @novar: flag to prohibit xslt variables from pattern
+ *
+ * Compile the XSLT StepPattern and generates a precompiled
+ * form suitable for fast matching.
+ *
+ * [5] StepPattern ::= ChildOrAttributeAxisSpecifier NodeTest Predicate* 
+ * [6] ChildOrAttributeAxisSpecifier ::= AbbreviatedAxisSpecifier
+ *                                     | ('child' | 'attribute') '::'
+ * from XPath
+ * [7]  NodeTest ::= NameTest
+ *                 | NodeType '(' ')'
+ *                 | 'processing-instruction' '(' Literal ')'
+ * [8] Predicate ::= '[' PredicateExpr ']'
+ * [9] PredicateExpr ::= Expr
+ * [13] AbbreviatedAxisSpecifier ::= '@'?
+ * [37] NameTest ::= '*' | NCName ':' '*' | QName
+ */
+
+static void
+xsltCompileStepPattern(xsltParserContextPtr ctxt, xmlChar *token, int novar) {
+    xmlChar *name = NULL;
+    const xmlChar *URI = NULL;
+    xmlChar *URL = NULL;
+    int level;
+
+    SKIP_BLANKS;
+    if ((token == NULL) && (CUR == '@')) {
+       xmlChar *prefix = NULL;
+
+       NEXT;
+       if (CUR == '*') {
+           NEXT;
+           PUSH(XSLT_OP_ATTR, NULL, NULL, novar);
+           goto parse_predicate;
+       }
+       token = xsltScanQName(ctxt, &prefix);
+       if (prefix != NULL) {
+           xmlNsPtr ns;
+
+           ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix);
+           if (ns == NULL) {
+               xsltTransformError(NULL, NULL, NULL,
+               "xsltCompileStepPattern : no namespace bound to prefix %s\n",
+                                prefix);
+           } else {
+               URL = xmlStrdup(ns->href);
+           }
+           xmlFree(prefix);
+       }
+       if (token == NULL) {
+           if (CUR == '*') {
+               NEXT;
+               PUSH(XSLT_OP_ATTR, NULL, URL, novar);
+               return;
+           }
+           xsltTransformError(NULL, NULL, NULL,
+                   "xsltCompileStepPattern : Name expected\n");
+           ctxt->error = 1;
+           goto error;
+       }
+       PUSH(XSLT_OP_ATTR, token, URL, novar);
+       goto parse_predicate;
+    }
+    if (token == NULL)
+       token = xsltScanName(ctxt);
+    if (token == NULL) {
+       if (CUR == '*') {
+           NEXT;
+           PUSH(XSLT_OP_ALL, token, NULL, novar);
+           goto parse_predicate;
+       } else {
+           xsltTransformError(NULL, NULL, NULL,
+                   "xsltCompileStepPattern : Name expected\n");
+           ctxt->error = 1;
+           goto error;
+       }
+    }
+
+
+    SKIP_BLANKS;
+    if (CUR == '(') {
+       xsltCompileIdKeyPattern(ctxt, token, 0, novar);
+       if (ctxt->error)
+           goto error;
+    } else if (CUR == ':') {
+       NEXT;
+       if (CUR != ':') {
+           xmlChar *prefix = token;
+           xmlNsPtr ns;
+
+           /*
+            * This is a namespace match
+            */
+           token = xsltScanName(ctxt);
+           ns = xmlSearchNs(ctxt->doc, ctxt->elem, prefix);
+           if (ns == NULL) {
+               xsltTransformError(NULL, NULL, NULL,
+           "xsltCompileStepPattern : no namespace bound to prefix %s\n",
+                                prefix);
+               ctxt->error = 1;
+               goto error;
+           } else {
+               URL = xmlStrdup(ns->href);
+           }
+           xmlFree(prefix);
+           if (token == NULL) {
+               if (CUR == '*') {
+                   NEXT;
+                   PUSH(XSLT_OP_NS, URL, NULL, novar);
+               } else {
+                   xsltTransformError(NULL, NULL, NULL,
+                           "xsltCompileStepPattern : Name expected\n");
+                   ctxt->error = 1;
+                   goto error;
+               }
+           } else {
+               PUSH(XSLT_OP_ELEM, token, URL, novar);
+           }
+       } else {
+           NEXT;
+           if (xmlStrEqual(token, (const xmlChar *) "child")) {
+               xmlFree(token);
+               token = xsltScanName(ctxt);
+               if (token == NULL) {
+                   if (CUR == '*') {
+                       NEXT;
+                       PUSH(XSLT_OP_ALL, token, NULL, novar);
+                       goto parse_predicate;
+                   } else {
+                       xsltTransformError(NULL, NULL, NULL,
+                           "xsltCompileStepPattern : QName expected\n");
+                       ctxt->error = 1;
+                       goto error;
+                   }
+               }
+               URI = xsltGetQNameURI(ctxt->elem, &token);
+               if (token == NULL) {
+                   ctxt->error = 1;
+                   goto error;
+               } else {
+                   name = xmlStrdup(token);
+                   if (URI != NULL)
+                       URL = xmlStrdup(URI);
+               }
+               PUSH(XSLT_OP_CHILD, name, URL, novar);
+           } else if (xmlStrEqual(token, (const xmlChar *) "attribute")) {
+               xmlFree(token);
+               token = xsltScanName(ctxt);
+               if (token == NULL) {
+                   xsltTransformError(NULL, NULL, NULL,
+                           "xsltCompileStepPattern : QName expected\n");
+                   ctxt->error = 1;
+                   goto error;
+               }
+               URI = xsltGetQNameURI(ctxt->elem, &token);
+               if (token == NULL) {
+                   ctxt->error = 1;
+                   goto error;
+               } else {
+                   name = xmlStrdup(token);
+                   if (URI != NULL)
+                       URL = xmlStrdup(URI);
+               }
+               PUSH(XSLT_OP_ATTR, name, URL, novar);
+           } else {
+               xsltTransformError(NULL, NULL, NULL,
+                   "xsltCompileStepPattern : 'child' or 'attribute' expected\n");
+               ctxt->error = 1;
+               goto error;
+           }
+           xmlFree(token);
+       }
+    } else if (CUR == '*') {
+       NEXT;
+       PUSH(XSLT_OP_ALL, token, NULL, novar);
+    } else {
+       URI = xsltGetQNameURI(ctxt->elem, &token);
+       if (token == NULL) {
+           ctxt->error = 1;
+           goto error;
+       }
+       if (URI != NULL)
+           URL = xmlStrdup(URI);
+       PUSH(XSLT_OP_ELEM, token, URL, novar);
+    }
+parse_predicate:
+    SKIP_BLANKS;
+    level = 0;
+    while (CUR == '[') {
+       const xmlChar *q;
+       xmlChar *ret = NULL;
+
+       level++;
+       NEXT;
+       q = CUR_PTR;
+       while (CUR != 0) {
+           /* Skip over nested predicates */
+           if (CUR == '[')
+               level++;
+           else if (CUR == ']') {
+               level--;
+               if (level == 0)
+                   break;
+           } else if (CUR == '"') {
+               NEXT;
+               while ((CUR != 0) && (CUR != '"'))
+                   NEXT;
+           } else if (CUR == '\'') {
+               NEXT;
+               while ((CUR != 0) && (CUR != '\''))
+                   NEXT;
+           }
+           NEXT;
+       }
+       if (CUR == 0) {
+           xsltTransformError(NULL, NULL, NULL,
+                   "xsltCompileStepPattern : ']' expected\n");
+           ctxt->error = 1;
+           return;
+        }
+       ret = xmlStrndup(q, CUR_PTR - q);
+       PUSH(XSLT_OP_PREDICATE, ret, NULL, novar);
+       /* push the predicate lower than local test */
+       SWAP();
+       NEXT;
+       SKIP_BLANKS;
+    }
+    return;
+error:
+    if (token != NULL)
+       xmlFree(token);
+    if (name != NULL)
+       xmlFree(name);
+}
+
+/**
+ * xsltCompileRelativePathPattern:
+ * @comp:  the compilation context
+ * @token:  a posible precompiled name
+ * @novar:  flag to prohibit xslt variables
+ *
+ * Compile the XSLT RelativePathPattern and generates a precompiled
+ * form suitable for fast matching.
+ *
+ * [4] RelativePathPattern ::= StepPattern
+ *                           | RelativePathPattern '/' StepPattern
+ *                           | RelativePathPattern '//' StepPattern
+ */
+static void
+xsltCompileRelativePathPattern(xsltParserContextPtr ctxt, xmlChar *token, int novar) {
+    xsltCompileStepPattern(ctxt, token, novar);
+    if (ctxt->error)
+       goto error;
+    SKIP_BLANKS;
+    while ((CUR != 0) && (CUR != '|')) {
+       if ((CUR == '/') && (NXT(1) == '/')) {
+           PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);
+           NEXT;
+           NEXT;
+           SKIP_BLANKS;
+           xsltCompileStepPattern(ctxt, NULL, novar);
+       } else if (CUR == '/') {
+           PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
+           NEXT;
+           SKIP_BLANKS;
+           if ((CUR != 0) && (CUR != '|')) {
+               xsltCompileRelativePathPattern(ctxt, NULL, novar);
+           }
+       } else {
+           ctxt->error = 1;
+       }
+       if (ctxt->error)
+           goto error;
+       SKIP_BLANKS;
+    }
+error:
+    return;
+}
+
+/**
+ * xsltCompileLocationPathPattern:
+ * @ctxt:  the compilation context
+ * @novar:  flag to prohibit xslt variables
+ *
+ * Compile the XSLT LocationPathPattern and generates a precompiled
+ * form suitable for fast matching.
+ *
+ * [2] LocationPathPattern ::= '/' RelativePathPattern?
+ *                           | IdKeyPattern (('/' | '//') RelativePathPattern)?
+ *                           | '//'? RelativePathPattern
+ */
+static void
+xsltCompileLocationPathPattern(xsltParserContextPtr ctxt, int novar) {
+    SKIP_BLANKS;
+    if ((CUR == '/') && (NXT(1) == '/')) {
+       /*
+        * since we reverse the query
+        * a leading // can be safely ignored
+        */
+       NEXT;
+       NEXT;
+       ctxt->comp->priority = 0.5;     /* '//' means not 0 priority */
+       xsltCompileRelativePathPattern(ctxt, NULL, novar);
+    } else if (CUR == '/') {
+       /*
+        * We need to find root as the parent
+        */
+       NEXT;
+       SKIP_BLANKS;
+       PUSH(XSLT_OP_ROOT, NULL, NULL, novar);
+       if ((CUR != 0) && (CUR != '|')) {
+           PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
+           xsltCompileRelativePathPattern(ctxt, NULL, novar);
+       }
+    } else if (CUR == '*') {
+       xsltCompileRelativePathPattern(ctxt, NULL, novar);
+    } else if (CUR == '@') {
+       xsltCompileRelativePathPattern(ctxt, NULL, novar);
+    } else {
+       xmlChar *name;
+       name = xsltScanName(ctxt);
+       if (name == NULL) {
+           xsltTransformError(NULL, NULL, NULL,
+                   "xsltCompileLocationPathPattern : Name expected\n");
+           ctxt->error = 1;
+           return;
+       }
+       SKIP_BLANKS;
+       if ((CUR == '(') && !xmlXPathIsNodeType(name)) {
+           xsltCompileIdKeyPattern(ctxt, name, 1, novar);
+           if ((CUR == '/') && (NXT(1) == '/')) {
+               PUSH(XSLT_OP_ANCESTOR, NULL, NULL, novar);
+               NEXT;
+               NEXT;
+               SKIP_BLANKS;
+               xsltCompileRelativePathPattern(ctxt, NULL, novar);
+           } else if (CUR == '/') {
+               PUSH(XSLT_OP_PARENT, NULL, NULL, novar);
+               NEXT;
+               SKIP_BLANKS;
+               xsltCompileRelativePathPattern(ctxt, NULL, novar);
+           }
+           return;
+       }
+       xsltCompileRelativePathPattern(ctxt, name, novar);
+    }
+error:
+    return;
+}
+
+/**
+ * xsltCompilePatternInternal:
+ * @pattern: an XSLT pattern
+ * @doc:  the containing document
+ * @node:  the containing element
+ * @style:  the stylesheet
+ * @runtime:  the transformation context, if done at run-time
+ * @novar:  flag to prohibit xslt variables
+ *
+ * Compile the XSLT pattern and generates a list of precompiled form suitable
+ * for fast matching.
+ *
+ * [1] Pattern ::= LocationPathPattern | Pattern '|' LocationPathPattern
+ *
+ * Returns the generated pattern list or NULL in case of failure
+ */
+
+static xsltCompMatchPtr
+xsltCompilePatternInternal(const xmlChar *pattern, xmlDocPtr doc,
+                  xmlNodePtr node, xsltStylesheetPtr style,
+                  xsltTransformContextPtr runtime, int novar) {
+    xsltParserContextPtr ctxt = NULL;
+    xsltCompMatchPtr element, first = NULL, previous = NULL;
+    int current, start, end, level, j;
+
+    if (pattern == NULL) {
+       xsltTransformError(NULL, NULL, node,
+                        "xsltCompilePattern : NULL pattern\n");
+       return(NULL);
+    }
+
+    ctxt = xsltNewParserContext(style, runtime);
+    if (ctxt == NULL)
+       return(NULL);
+    ctxt->doc = doc;
+    ctxt->elem = node;
+    current = end = 0;
+    while (pattern[current] != 0) {
+       start = current;
+       while (IS_BLANK_CH(pattern[current]))
+           current++;
+       end = current;
+       level = 0;
+       while ((pattern[end] != 0) && ((pattern[end] != '|') || (level != 0))) {
+           if (pattern[end] == '[')
+               level++;
+           else if (pattern[end] == ']')
+               level--;
+           else if (pattern[end] == '\'') {
+               end++;
+               while ((pattern[end] != 0) && (pattern[end] != '\''))
+                   end++;
+           } else if (pattern[end] == '"') {
+               end++;
+               while ((pattern[end] != 0) && (pattern[end] != '"'))
+                   end++;
+           }
+           end++;
+       }
+       if (current == end) {
+           xsltTransformError(NULL, NULL, node,
+                            "xsltCompilePattern : NULL pattern\n");
+           goto error;
+       }
+       element = xsltNewCompMatch();
+       if (element == NULL) {
+           goto error;
+       }
+       if (first == NULL)
+           first = element;
+       else if (previous != NULL)
+           previous->next = element;
+       previous = element;
+
+       ctxt->comp = element;
+       ctxt->base = xmlStrndup(&pattern[start], end - start);
+       if (ctxt->base == NULL)
+           goto error;
+       ctxt->cur = &(ctxt->base)[current - start];
+       element->pattern = ctxt->base;
+       element->nsList = xmlGetNsList(doc, node);
+       j = 0;
+       if (element->nsList != NULL) {
+           while (element->nsList[j] != NULL)
+               j++;
+       }
+       element->nsNr = j;
+
+
+#ifdef WITH_XSLT_DEBUG_PATTERN
+       xsltGenericDebug(xsltGenericDebugContext,
+                        "xsltCompilePattern : parsing '%s'\n",
+                        element->pattern);
+#endif
+       /*
+        Preset default priority to be zero.
+        This may be changed by xsltCompileLocationPathPattern.
+        */
+       element->priority = 0;
+       xsltCompileLocationPathPattern(ctxt, novar);
+       if (ctxt->error) {
+           xsltTransformError(NULL, style, node,
+                            "xsltCompilePattern : failed to compile '%s'\n",
+                            element->pattern);
+           if (style != NULL) style->errors++;
+           goto error;
+       }
+
+       /*
+        * Reverse for faster interpretation.
+        */
+       xsltReverseCompMatch(element);
+
+       /*
+        * Set-up the priority
+        */
+       if (element->priority == 0) {   /* if not yet determined */
+           if (((element->steps[0].op == XSLT_OP_ELEM) ||
+                (element->steps[0].op == XSLT_OP_ATTR) ||
+                (element->steps[0].op == XSLT_OP_PI)) &&
+               (element->steps[0].value != NULL) &&
+               (element->steps[1].op == XSLT_OP_END)) {
+               ;       /* previously preset */
+           } else if ((element->steps[0].op == XSLT_OP_ATTR) &&
+                      (element->steps[0].value2 != NULL) &&
+                      (element->steps[1].op == XSLT_OP_END)) {
+                       element->priority = -0.25;
+           } else if ((element->steps[0].op == XSLT_OP_NS) &&
+                      (element->steps[0].value != NULL) &&
+                      (element->steps[1].op == XSLT_OP_END)) {
+                       element->priority = -0.25;
+           } else if ((element->steps[0].op == XSLT_OP_ATTR) &&
+                      (element->steps[0].value == NULL) &&
+                      (element->steps[0].value2 == NULL) &&
+                      (element->steps[1].op == XSLT_OP_END)) {
+                       element->priority = -0.5;
+           } else if (((element->steps[0].op == XSLT_OP_PI) ||
+                      (element->steps[0].op == XSLT_OP_TEXT) ||
+                      (element->steps[0].op == XSLT_OP_ALL) ||
+                      (element->steps[0].op == XSLT_OP_NODE) ||
+                      (element->steps[0].op == XSLT_OP_COMMENT)) &&
+                      (element->steps[1].op == XSLT_OP_END)) {
+                       element->priority = -0.5;
+           } else {
+               element->priority = 0.5;
+           }
+       }
+#ifdef WITH_XSLT_DEBUG_PATTERN
+       xsltGenericDebug(xsltGenericDebugContext,
+                    "xsltCompilePattern : parsed %s, default priority %f\n",
+                        element->pattern, element->priority);
+#endif
+       if (pattern[end] == '|')
+           end++;
+       current = end;
+    }
+    if (end == 0) {
+       xsltTransformError(NULL, style, node,
+                        "xsltCompilePattern : NULL pattern\n");
+       if (style != NULL) style->errors++;
+       goto error;
+    }
+
+    xsltFreeParserContext(ctxt);
+    return(first);
+
+error:
+    if (ctxt != NULL)
+       xsltFreeParserContext(ctxt);
+    if (first != NULL)
+       xsltFreeCompMatchList(first);
+    return(NULL);
+}
+
+/**
+ * xsltCompilePattern:
+ * @pattern: an XSLT pattern
+ * @doc:  the containing document
+ * @node:  the containing element
+ * @style:  the stylesheet
+ * @runtime:  the transformation context, if done at run-time
+ *
+ * Compile the XSLT pattern and generates a list of precompiled form suitable
+ * for fast matching.
+ *
+ * [1] Pattern ::= LocationPathPattern | Pattern '|' LocationPathPattern
+ *
+ * Returns the generated pattern list or NULL in case of failure
+ */
+
+xsltCompMatchPtr
+xsltCompilePattern(const xmlChar *pattern, xmlDocPtr doc,
+                  xmlNodePtr node, xsltStylesheetPtr style,
+                  xsltTransformContextPtr runtime) {
+    return (xsltCompilePatternInternal(pattern, doc, node, style, runtime, 0));
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Module interfaces                               *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltAddTemplate:
+ * @style: an XSLT stylesheet
+ * @cur: an XSLT template
+ * @mode:  the mode name or NULL
+ * @modeURI:  the mode URI or NULL
+ *
+ * Register the XSLT pattern associated to @cur
+ *
+ * Returns -1 in case of error, 0 otherwise
+ */
+int
+xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur,
+               const xmlChar *mode, const xmlChar *modeURI) {
+    xsltCompMatchPtr pat, list, *top = NULL, next;
+    const xmlChar *name = NULL;
+    float priority;              /* the priority */
+
+    if ((style == NULL) || (cur == NULL) || (cur->match == NULL))
+       return(-1);
+
+    priority = cur->priority;
+    pat = xsltCompilePatternInternal(cur->match, style->doc, cur->elem,
+                   style, NULL, 1);
+    while (pat) {
+       next = pat->next;
+       pat->next = NULL;
+       name = NULL;
+       
+       pat->template = cur;
+       if (mode != NULL)
+           pat->mode = xmlDictLookup(style->dict, mode, -1);
+       if (modeURI != NULL)
+           pat->modeURI = xmlDictLookup(style->dict, modeURI, -1);
+       if (priority != XSLT_PAT_NO_PRIORITY)
+           pat->priority = priority;
+
+       /*
+        * insert it in the hash table list corresponding to its lookup name
+        */
+       switch (pat->steps[0].op) {
+        case XSLT_OP_ATTR:
+           if (pat->steps[0].value != NULL)
+               name = pat->steps[0].value;
+           else
+               top = (xsltCompMatchPtr *) &(style->attrMatch);
+           break;
+        case XSLT_OP_CHILD:
+        case XSLT_OP_PARENT:
+        case XSLT_OP_ANCESTOR:
+           top = (xsltCompMatchPtr *) &(style->elemMatch);
+           break;
+        case XSLT_OP_ROOT:
+           top = (xsltCompMatchPtr *) &(style->rootMatch);
+           break;
+        case XSLT_OP_KEY:
+           top = (xsltCompMatchPtr *) &(style->keyMatch);
+           break;
+        case XSLT_OP_ID:
+           /* TODO optimize ID !!! */
+        case XSLT_OP_NS:
+        case XSLT_OP_ALL:
+           top = (xsltCompMatchPtr *) &(style->elemMatch);
+           break;
+        case XSLT_OP_END:
+       case XSLT_OP_PREDICATE:
+           xsltTransformError(NULL, style, NULL,
+                            "xsltAddTemplate: invalid compiled pattern\n");
+           xsltFreeCompMatch(pat);
+           return(-1);
+           /*
+            * TODO: some flags at the top level about type based patterns
+            *       would be faster than inclusion in the hash table.
+            */
+       case XSLT_OP_PI:
+           if (pat->steps[0].value != NULL)
+               name = pat->steps[0].value;
+           else
+               top = (xsltCompMatchPtr *) &(style->piMatch);
+           break;
+       case XSLT_OP_COMMENT:
+           top = (xsltCompMatchPtr *) &(style->commentMatch);
+           break;
+       case XSLT_OP_TEXT:
+           top = (xsltCompMatchPtr *) &(style->textMatch);
+           break;
+        case XSLT_OP_ELEM:
+       case XSLT_OP_NODE:
+           if (pat->steps[0].value != NULL)
+               name = pat->steps[0].value;
+           else
+               top = (xsltCompMatchPtr *) &(style->elemMatch);
+           break;
+       }
+       if (name != NULL) {
+           if (style->templatesHash == NULL) {
+               style->templatesHash = xmlHashCreate(1024);
+               if (style->templatesHash == NULL) {
+                   xsltFreeCompMatch(pat);
+                   return(-1);
+               }
+               xmlHashAddEntry3(style->templatesHash, name, mode, modeURI, pat);
+           } else {
+               list = (xsltCompMatchPtr) xmlHashLookup3(style->templatesHash,
+                                                        name, mode, modeURI);
+               if (list == NULL) {
+                   xmlHashAddEntry3(style->templatesHash, name,
+                                    mode, modeURI, pat);
+               } else {
+                   /*
+                    * Note '<=' since one must choose among the matching
+                    * template rules that are left, the one that occurs
+                    * last in the stylesheet
+                    */
+                   if (list->priority <= pat->priority) {
+                       pat->next = list;
+                       xmlHashUpdateEntry3(style->templatesHash, name,
+                                           mode, modeURI, pat, NULL);
+                   } else {
+                       while (list->next != NULL) {
+                           if (list->next->priority <= pat->priority)
+                               break;
+                           list = list->next;
+                       }
+                       pat->next = list->next;
+                       list->next = pat;
+                   }
+               }
+           }
+       } else if (top != NULL) {
+           list = *top;
+           if (list == NULL) {
+               *top = pat;
+               pat->next = NULL;
+           } else if (list->priority <= pat->priority) {
+               pat->next = list;
+               *top = pat;
+           } else {
+               while (list->next != NULL) {
+                   if (list->next->priority <= pat->priority)
+                       break;
+                   list = list->next;
+               }
+               pat->next = list->next;
+               list->next = pat;
+           }
+       } else {
+           xsltTransformError(NULL, style, NULL,
+                            "xsltAddTemplate: invalid compiled pattern\n");
+           xsltFreeCompMatch(pat);
+           return(-1);
+       }
+#ifdef WITH_XSLT_DEBUG_PATTERN
+       if (mode)
+           xsltGenericDebug(xsltGenericDebugContext,
+                        "added pattern : '%s' mode '%s' priority %f\n",
+                            pat->pattern, pat->mode, pat->priority);
+       else
+           xsltGenericDebug(xsltGenericDebugContext,
+                        "added pattern : '%s' priority %f\n",
+                            pat->pattern, pat->priority);
+#endif
+
+       pat = next;
+    }
+    return(0);
+}
+
+#ifdef XSLT_REFACTORED_KEYCOMP
+static int
+xsltComputeAllKeys(xsltTransformContextPtr ctxt, xmlNodePtr contextNode)
+{
+    xsltStylesheetPtr style, style2;
+    xsltKeyDefPtr keyd, keyd2;
+    xsltKeyTablePtr table;
+
+    if ((ctxt == NULL) || (contextNode == NULL)) {
+       xsltTransformError(ctxt, NULL, ctxt->inst,
+           "Internal error in xsltComputeAllKeys(): "
+           "Bad arguments.\n");
+       return(-1);
+    }
+    
+    if (ctxt->document == NULL) {
+       /*
+       * The document info will only be NULL if we have a RTF.
+       */
+       if (contextNode->doc->_private != NULL)
+           goto doc_info_mismatch;
+       /*
+       * On-demand creation of the document info (needed for keys).
+       */
+       ctxt->document = xsltNewDocument(ctxt, contextNode->doc);
+       if (ctxt->document == NULL)
+           return(-1);
+    }
+
+    if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
+       return(0);
+    /*
+    * TODO: This could be further optimized
+    */
+    style = ctxt->style;
+    while (style) {
+       keyd = (xsltKeyDefPtr) style->keys;
+       while (keyd != NULL) {
+           /*
+           * Check if keys with this QName have been already
+           * computed.
+           */
+           table = (xsltKeyTablePtr) ctxt->document->keys;
+           while (table) {
+               if (((keyd->nameURI != NULL) == (table->nameURI != NULL)) &&
+                   xmlStrEqual(keyd->name, table->name) &&
+                   xmlStrEqual(keyd->nameURI, table->nameURI))
+               {
+                   break;
+               }               
+               table = table->next;
+           }
+           if (table == NULL) {
+               /*
+               * Keys with this QName have not been yet computed.
+               */
+               style2 = ctxt->style;
+               while (style2 != NULL) {
+                   keyd2 = (xsltKeyDefPtr) style2->keys;
+                   while (keyd2 != NULL) {
+                       if (((keyd2->nameURI != NULL) ==
+                            (keyd->nameURI != NULL)) &&
+                           xmlStrEqual(keyd2->name, keyd->name) &&
+                           xmlStrEqual(keyd2->nameURI, keyd->nameURI))
+                       {
+                           xsltInitCtxtKey(ctxt, ctxt->document, keyd2);
+                           if (ctxt->document->nbKeysComputed == ctxt->nbKeys)
+                               return(0);
+                       }
+                       keyd2 = keyd2->next;
+                   }
+                   style2 = xsltNextImport(style2);
+               }
+           }
+           keyd = keyd->next;
+       }
+       style = xsltNextImport(style);
+    }
+    return(0);
+
+doc_info_mismatch:
+    xsltTransformError(ctxt, NULL, ctxt->inst,
+       "Internal error in xsltComputeAllKeys(): "
+       "The context's document info doesn't match the "
+       "document info of the current result tree.\n");
+    ctxt->state = XSLT_STATE_STOPPED;
+    return(-1);
+}
+#endif
+
+/**
+ * xsltGetTemplate:
+ * @ctxt:  a XSLT process context
+ * @node:  the node being processed
+ * @style:  the current style
+ *
+ * Finds the template applying to this node, if @style is non-NULL
+ * it means one needs to look for the next imported template in scope.
+ *
+ * Returns the xsltTemplatePtr or NULL if not found
+ */
+xsltTemplatePtr
+xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
+               xsltStylesheetPtr style)
+{
+    xsltStylesheetPtr curstyle;
+    xsltTemplatePtr ret = NULL;
+    const xmlChar *name = NULL;
+    xsltCompMatchPtr list = NULL;
+    float priority;
+    int keyed = 0;
+
+    if ((ctxt == NULL) || (node == NULL))
+       return(NULL);
+
+    if (style == NULL) {
+       curstyle = ctxt->style;
+    } else {
+       curstyle = xsltNextImport(style);
+    }
+
+    while ((curstyle != NULL) && (curstyle != style)) {
+       priority = XSLT_PAT_NO_PRIORITY;
+       /* TODO : handle IDs/keys here ! */
+       if (curstyle->templatesHash != NULL) {
+           /*
+            * Use the top name as selector
+            */
+           switch (node->type) {
+               case XML_ELEMENT_NODE:
+                   if (node->name[0] == ' ')
+                       break;
+               case XML_ATTRIBUTE_NODE:
+               case XML_PI_NODE:
+                   name = node->name;
+                   break;
+               case XML_DOCUMENT_NODE:
+               case XML_HTML_DOCUMENT_NODE:
+               case XML_TEXT_NODE:
+               case XML_CDATA_SECTION_NODE:
+               case XML_COMMENT_NODE:
+               case XML_ENTITY_REF_NODE:
+               case XML_ENTITY_NODE:
+               case XML_DOCUMENT_TYPE_NODE:
+               case XML_DOCUMENT_FRAG_NODE:
+               case XML_NOTATION_NODE:
+               case XML_DTD_NODE:
+               case XML_ELEMENT_DECL:
+               case XML_ATTRIBUTE_DECL:
+               case XML_ENTITY_DECL:
+               case XML_NAMESPACE_DECL:
+               case XML_XINCLUDE_START:
+               case XML_XINCLUDE_END:
+                   break;
+               default:
+                   return(NULL);
+
+           }
+       }
+       if (name != NULL) {
+           /*
+            * find the list of applicable expressions based on the name
+            */
+           list = (xsltCompMatchPtr) xmlHashLookup3(curstyle->templatesHash,
+                                            name, ctxt->mode, ctxt->modeURI);
+       } else
+           list = NULL;
+       while (list != NULL) {
+           if (xsltTestCompMatch(ctxt, list, node,
+                                 ctxt->mode, ctxt->modeURI)) {
+               ret = list->template;
+               priority = list->priority;
+               break;
+           }
+           list = list->next;
+       }
+       list = NULL;
+
+       /*
+        * find alternate generic matches
+        */
+       switch (node->type) {
+           case XML_ELEMENT_NODE:
+               if (node->name[0] == ' ')
+                   list = curstyle->rootMatch;
+               else
+                   list = curstyle->elemMatch;
+               if (node->psvi != NULL) keyed = 1;
+               break;
+           case XML_ATTRIBUTE_NODE: {
+               xmlAttrPtr attr;
+
+               list = curstyle->attrMatch;
+               attr = (xmlAttrPtr) node;
+               if (attr->psvi != NULL) keyed = 1;
+               break;
+           }
+           case XML_PI_NODE:
+               list = curstyle->piMatch;
+               if (node->psvi != NULL) keyed = 1;
+               break;
+           case XML_DOCUMENT_NODE:
+           case XML_HTML_DOCUMENT_NODE: {
+               xmlDocPtr doc;
+
+               list = curstyle->rootMatch;
+               doc = (xmlDocPtr) node;
+               if (doc->psvi != NULL) keyed = 1;
+               break;
+           }
+           case XML_TEXT_NODE:
+           case XML_CDATA_SECTION_NODE:
+               list = curstyle->textMatch;
+               if (node->psvi != NULL) keyed = 1;
+               break;
+           case XML_COMMENT_NODE:
+               list = curstyle->commentMatch;
+               if (node->psvi != NULL) keyed = 1;
+               break;
+           case XML_ENTITY_REF_NODE:
+           case XML_ENTITY_NODE:
+           case XML_DOCUMENT_TYPE_NODE:
+           case XML_DOCUMENT_FRAG_NODE:
+           case XML_NOTATION_NODE:
+           case XML_DTD_NODE:
+           case XML_ELEMENT_DECL:
+           case XML_ATTRIBUTE_DECL:
+           case XML_ENTITY_DECL:
+           case XML_NAMESPACE_DECL:
+           case XML_XINCLUDE_START:
+           case XML_XINCLUDE_END:
+               break;
+           default:
+               break;
+       }
+       while ((list != NULL) &&
+              ((ret == NULL)  || (list->priority > priority))) {
+           if (xsltTestCompMatch(ctxt, list, node,
+                                 ctxt->mode, ctxt->modeURI)) {
+               ret = list->template;
+               priority = list->priority;
+               break;
+           }
+           list = list->next;
+       }
+       /*
+        * Some of the tests for elements can also apply to documents
+        */
+       if ((node->type == XML_DOCUMENT_NODE) ||
+           (node->type == XML_HTML_DOCUMENT_NODE) ||
+           (node->type == XML_TEXT_NODE)) {
+           list = curstyle->elemMatch;
+           while ((list != NULL) &&
+                  ((ret == NULL)  || (list->priority > priority))) {
+               if (xsltTestCompMatch(ctxt, list, node,
+                                     ctxt->mode, ctxt->modeURI)) {
+                   ret = list->template;
+                   priority = list->priority;
+                   break;
+               }
+               list = list->next;
+           }
+       } else if ((node->type == XML_PI_NODE) ||
+                  (node->type == XML_COMMENT_NODE)) {
+           list = curstyle->elemMatch;
+           while ((list != NULL) &&
+                  ((ret == NULL)  || (list->priority > priority))) {
+               if (xsltTestCompMatch(ctxt, list, node,
+                                     ctxt->mode, ctxt->modeURI)) {
+                   ret = list->template;
+                   priority = list->priority;
+                   break;
+               }
+               list = list->next;
+           }
+       }
+
+#ifdef XSLT_REFACTORED_KEYCOMP
+keyed_match:
+#endif
+       if (keyed) {
+           list = curstyle->keyMatch;
+           while ((list != NULL) &&
+                  ((ret == NULL)  || (list->priority > priority))) {
+               if (xsltTestCompMatch(ctxt, list, node,
+                                     ctxt->mode, ctxt->modeURI)) {
+                   ret = list->template;
+                   priority = list->priority;
+                   break;
+               }
+               list = list->next;
+           }
+       }
+#ifdef XSLT_REFACTORED_KEYCOMP 
+       else if (ctxt->hasTemplKeyPatterns &&
+           ((ctxt->document == NULL) ||
+            (ctxt->document->nbKeysComputed < ctxt->nbKeys)))
+       {
+           /*
+           * Compute all remaining keys for this document.
+           *
+           * REVISIT TODO: I think this could be further optimized.
+           */
+           if (xsltComputeAllKeys(ctxt, node) == -1)
+               goto error;
+
+           switch (node->type) {
+               case XML_ELEMENT_NODE:              
+                   if (node->psvi != NULL) keyed = 1;
+                   break;
+               case XML_ATTRIBUTE_NODE:
+                   if (((xmlAttrPtr) node)->psvi != NULL) keyed = 1;
+                   break;
+               case XML_TEXT_NODE:
+               case XML_CDATA_SECTION_NODE:
+               case XML_COMMENT_NODE:
+               case XML_PI_NODE:               
+                   if (node->psvi != NULL) keyed = 1;
+                   break;
+               case XML_DOCUMENT_NODE:
+               case XML_HTML_DOCUMENT_NODE:
+                   if (((xmlDocPtr) node)->psvi != NULL) keyed = 1;
+                   break;              
+               default:
+                   break;
+           }
+           if (keyed)
+               goto keyed_match;
+       }
+#endif /* XSLT_REFACTORED_KEYCOMP */
+       if (ret != NULL)
+           return(ret);
+
+       /*
+        * Cycle on next curstylesheet import.
+        */
+       curstyle = xsltNextImport(curstyle);
+    }
+
+error:
+    return(NULL);
+}
+
+/**
+ * xsltCleanupTemplates:
+ * @style: an XSLT stylesheet
+ *
+ * Cleanup the state of the templates used by the stylesheet and
+ * the ones it imports.
+ */
+void
+xsltCleanupTemplates(xsltStylesheetPtr style ATTRIBUTE_UNUSED) {
+}
+
+/**
+ * xsltFreeTemplateHashes:
+ * @style: an XSLT stylesheet
+ *
+ * Free up the memory used by xsltAddTemplate/xsltGetTemplate mechanism
+ */
+void
+xsltFreeTemplateHashes(xsltStylesheetPtr style) {
+    if (style->templatesHash != NULL)
+       xmlHashFree((xmlHashTablePtr) style->templatesHash,
+                   (xmlHashDeallocator) xsltFreeCompMatchList);
+    if (style->rootMatch != NULL)
+        xsltFreeCompMatchList(style->rootMatch);
+    if (style->keyMatch != NULL)
+        xsltFreeCompMatchList(style->keyMatch);
+    if (style->elemMatch != NULL)
+        xsltFreeCompMatchList(style->elemMatch);
+    if (style->attrMatch != NULL)
+        xsltFreeCompMatchList(style->attrMatch);
+    if (style->parentMatch != NULL)
+        xsltFreeCompMatchList(style->parentMatch);
+    if (style->textMatch != NULL)
+        xsltFreeCompMatchList(style->textMatch);
+    if (style->piMatch != NULL)
+        xsltFreeCompMatchList(style->piMatch);
+    if (style->commentMatch != NULL)
+        xsltFreeCompMatchList(style->commentMatch);
+}
+
index f85543e..0420e73 100644 (file)
-/*\r
- * preproc.c: Preprocessing of style operations\r
- *\r
- * References:\r
- *   http://www.w3.org/TR/1999/REC-xslt-19991116\r
- *\r
- *   Michael Kay "XSLT Programmer's Reference" pp 637-643\r
- *   Writing Multiple Output Files\r
- *\r
- *   XSLT-1.1 Working Draft\r
- *   http://www.w3.org/TR/xslt11#multiple-output\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * daniel@veillard.com\r
- */\r
-\r
-#define IN_LIBXSLT\r
-#include "libxslt.h"\r
-\r
-#include <string.h>\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/parser.h>\r
-#include <libxml/tree.h>\r
-#include <libxml/valid.h>\r
-#include <libxml/hash.h>\r
-#include <libxml/uri.h>\r
-#include <libxml/encoding.h>\r
-#include <libxml/xmlerror.h>\r
-#include "xslt.h"\r
-#include "xsltutils.h"\r
-#include "xsltInternals.h"\r
-#include "transform.h"\r
-#include "templates.h"\r
-#include "variables.h"\r
-#include "numbersInternals.h"\r
-#include "preproc.h"\r
-#include "extra.h"\r
-#include "imports.h"\r
-#include "extensions.h"\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
-#define WITH_XSLT_DEBUG_PREPROC\r
-#endif\r
-\r
-const xmlChar *xsltExtMarker = (const xmlChar *) "Extension Element";\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Grammar checks                                  *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * Grammar checks are now performed in xslt.c.\r
-    */\r
-#else\r
-/**\r
- * xsltCheckTopLevelElement:\r
- * @style: the XSLT stylesheet\r
- * @inst: the XSLT instruction\r
- * @err: raise an error or not\r
- *\r
- * Check that the instruction is instanciated as a top level element.\r
- *\r
- * Returns -1 in case of error, 0 if failed and 1 in case of success\r
- */\r
-static int\r
-xsltCheckTopLevelElement(xsltStylesheetPtr style, xmlNodePtr inst, int err) {\r
-    xmlNodePtr parent;\r
-    if ((style == NULL) || (inst == NULL) || (inst->ns == NULL))\r
-        return(-1);\r
-    \r
-    parent = inst->parent;\r
-    if (parent == NULL) {\r
-        if (err) {\r
-           xsltTransformError(NULL, style, inst,\r
-                   "internal problem: element has no parent\n");\r
-           style->errors++;\r
-       }\r
-       return(0);\r
-    }\r
-    if ((parent->ns == NULL) ||\r
-        ((parent->ns != inst->ns) &&\r
-        (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||\r
-       ((!xmlStrEqual(parent->name, BAD_CAST "stylesheet")) &&\r
-        (!xmlStrEqual(parent->name, BAD_CAST "transform")))) {\r
-       if (err) {\r
-           xsltTransformError(NULL, style, inst,\r
-                   "element %s only allowed as child of stylesheet\n",\r
-                              inst->name);\r
-           style->errors++;\r
-       }\r
-       return(0);\r
-    }\r
-    return(1);\r
-}\r
-\r
-/**\r
- * xsltCheckInstructionElement:\r
- * @style: the XSLT stylesheet\r
- * @inst: the XSLT instruction\r
- *\r
- * Check that the instruction is instanciated as an instruction element.\r
- */\r
-static void\r
-xsltCheckInstructionElement(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-    xmlNodePtr parent;\r
-    int has_ext;\r
-\r
-    if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) ||\r
-        (style->literal_result))\r
-        return;\r
-\r
-    has_ext = (style->extInfos != NULL);\r
-    \r
-    parent = inst->parent;\r
-    if (parent == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-               "internal problem: element has no parent\n");\r
-       style->errors++;\r
-       return;\r
-    }\r
-    while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) {\r
-        if (((parent->ns == inst->ns) ||\r
-            ((parent->ns != NULL) &&\r
-             (xmlStrEqual(parent->ns->href, inst->ns->href)))) &&\r
-           ((xmlStrEqual(parent->name, BAD_CAST "template")) ||\r
-            (xmlStrEqual(parent->name, BAD_CAST "param")) ||\r
-            (xmlStrEqual(parent->name, BAD_CAST "attribute")) ||\r
-            (xmlStrEqual(parent->name, BAD_CAST "variable")))) {\r
-           return;\r
-       }\r
-\r
-       /*\r
-        * if we are within an extension element all bets are off\r
-        * about the semantic there e.g. xsl:param within func:function\r
-        */\r
-       if ((has_ext) && (parent->ns != NULL) &&\r
-           (xmlHashLookup(style->extInfos, parent->ns->href) != NULL))\r
-           return;\r
-       \r
-        parent = parent->parent;\r
-    }\r
-    xsltTransformError(NULL, style, inst,\r
-           "element %s only allowed within a template, variable or param\n",\r
-                          inst->name);\r
-    style->errors++;\r
-}\r
-\r
-/**\r
- * xsltCheckParentElement:\r
- * @style: the XSLT stylesheet\r
- * @inst: the XSLT instruction\r
- * @allow1: allowed parent1\r
- * @allow2: allowed parent2\r
- *\r
- * Check that the instruction is instanciated as the childre of one of the\r
- * possible parents.\r
- */\r
-static void\r
-xsltCheckParentElement(xsltStylesheetPtr style, xmlNodePtr inst,\r
-                       const xmlChar *allow1, const xmlChar *allow2) {\r
-    xmlNodePtr parent;\r
-\r
-    if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) ||\r
-        (style->literal_result))\r
-        return;\r
-\r
-    parent = inst->parent;\r
-    if (parent == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-               "internal problem: element has no parent\n");\r
-       style->errors++;\r
-       return;\r
-    }\r
-    if (((parent->ns == inst->ns) ||\r
-        ((parent->ns != NULL) &&\r
-         (xmlStrEqual(parent->ns->href, inst->ns->href)))) &&\r
-       ((xmlStrEqual(parent->name, allow1)) ||\r
-        (xmlStrEqual(parent->name, allow2)))) {\r
-       return;\r
-    }\r
-\r
-    if (style->extInfos != NULL) {\r
-       while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) {\r
-           /*\r
-            * if we are within an extension element all bets are off\r
-            * about the semantic there e.g. xsl:param within func:function\r
-            */\r
-           if ((parent->ns != NULL) &&\r
-               (xmlHashLookup(style->extInfos, parent->ns->href) != NULL))\r
-               return;\r
-           \r
-           parent = parent->parent;\r
-       }\r
-    }\r
-    xsltTransformError(NULL, style, inst,\r
-                      "element %s is not allowed within that context\n",\r
-                      inst->name);\r
-    style->errors++;\r
-}\r
-#endif\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     handling of precomputed data                    *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltNewStylePreComp:\r
- * @style:  the XSLT stylesheet\r
- * @type:  the construct type\r
- *\r
- * Create a new XSLT Style precomputed block\r
- *\r
- * Returns the newly allocated specialized structure\r
- *         or NULL in case of error\r
- */\r
-static xsltStylePreCompPtr\r
-xsltNewStylePreComp(xsltStylesheetPtr style, xsltStyleType type) {\r
-    xsltStylePreCompPtr cur;\r
-#ifdef XSLT_REFACTORED\r
-    size_t size;\r
-#endif\r
-\r
-    if (style == NULL)\r
-        return(NULL);\r
-   \r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * URGENT TODO: Use specialized factory functions in order\r
-    *   to avoid this ugliness.\r
-    */\r
-    switch (type) {\r
-        case XSLT_FUNC_COPY:\r
-            size = sizeof(xsltStyleItemCopy); break;\r
-        case XSLT_FUNC_SORT:\r
-            size = sizeof(xsltStyleItemSort); break;\r
-        case XSLT_FUNC_TEXT:\r
-            size = sizeof(xsltStyleItemText); break;\r
-        case XSLT_FUNC_ELEMENT:\r
-            size = sizeof(xsltStyleItemElement); break;\r
-        case XSLT_FUNC_ATTRIBUTE:\r
-            size = sizeof(xsltStyleItemAttribute); break;\r
-        case XSLT_FUNC_COMMENT:\r
-            size = sizeof(xsltStyleItemComment); break;\r
-        case XSLT_FUNC_PI:\r
-            size = sizeof(xsltStyleItemPI); break;\r
-        case XSLT_FUNC_COPYOF:\r
-            size = sizeof(xsltStyleItemCopyOf); break;\r
-        case XSLT_FUNC_VALUEOF:\r
-            size = sizeof(xsltStyleItemValueOf); break;;\r
-        case XSLT_FUNC_NUMBER:\r
-            size = sizeof(xsltStyleItemNumber); break;\r
-        case XSLT_FUNC_APPLYIMPORTS:\r
-            size = sizeof(xsltStyleItemApplyImports); break;\r
-        case XSLT_FUNC_CALLTEMPLATE:\r
-            size = sizeof(xsltStyleItemCallTemplate); break;\r
-        case XSLT_FUNC_APPLYTEMPLATES:\r
-            size = sizeof(xsltStyleItemApplyTemplates); break;\r
-        case XSLT_FUNC_CHOOSE:\r
-            size = sizeof(xsltStyleItemChoose); break;\r
-        case XSLT_FUNC_IF:\r
-            size = sizeof(xsltStyleItemIf); break;\r
-        case XSLT_FUNC_FOREACH:\r
-            size = sizeof(xsltStyleItemForEach); break;\r
-        case XSLT_FUNC_DOCUMENT:\r
-            size = sizeof(xsltStyleItemDocument); break;\r
-       case XSLT_FUNC_WITHPARAM:\r
-           size = sizeof(xsltStyleItemWithParam); break;\r
-       case XSLT_FUNC_PARAM:\r
-           size = sizeof(xsltStyleItemParam); break;\r
-       case XSLT_FUNC_VARIABLE:\r
-           size = sizeof(xsltStyleItemVariable); break;\r
-       case XSLT_FUNC_WHEN:\r
-           size = sizeof(xsltStyleItemWhen); break;\r
-       case XSLT_FUNC_OTHERWISE:\r
-           size = sizeof(xsltStyleItemOtherwise); break;\r
-       default:        \r
-           xsltTransformError(NULL, style, NULL,\r
-                   "xsltNewStylePreComp : invalid type %d\n", type);\r
-           style->errors++;\r
-           return(NULL);\r
-    }\r
-    /*\r
-    * Create the structure.\r
-    */\r
-    cur = (xsltStylePreCompPtr) xmlMalloc(size);\r
-    if (cur == NULL) {\r
-       xsltTransformError(NULL, style, NULL,\r
-               "xsltNewStylePreComp : malloc failed\n");\r
-       style->errors++;\r
-       return(NULL);\r
-    }\r
-    memset(cur, 0, size);\r
-\r
-#else /* XSLT_REFACTORED */\r
-    /*\r
-    * Old behaviour.\r
-    */\r
-    cur = (xsltStylePreCompPtr) xmlMalloc(sizeof(xsltStylePreComp));\r
-    if (cur == NULL) {\r
-       xsltTransformError(NULL, style, NULL,\r
-               "xsltNewStylePreComp : malloc failed\n");\r
-       style->errors++;\r
-       return(NULL);\r
-    }\r
-    memset(cur, 0, sizeof(xsltStylePreComp));\r
-#endif /* XSLT_REFACTORED */\r
-\r
-    /*\r
-    * URGENT TODO: Better to move this to spezialized factory functions.\r
-    */\r
-    cur->type = type;\r
-    switch (cur->type) {\r
-        case XSLT_FUNC_COPY:\r
-            cur->func = (xsltTransformFunction) xsltCopy;break;\r
-        case XSLT_FUNC_SORT:\r
-            cur->func = (xsltTransformFunction) xsltSort;break;\r
-        case XSLT_FUNC_TEXT:\r
-            cur->func = (xsltTransformFunction) xsltText;break;\r
-        case XSLT_FUNC_ELEMENT:\r
-            cur->func = (xsltTransformFunction) xsltElement;break;\r
-        case XSLT_FUNC_ATTRIBUTE:\r
-            cur->func = (xsltTransformFunction) xsltAttribute;break;\r
-        case XSLT_FUNC_COMMENT:\r
-            cur->func = (xsltTransformFunction) xsltComment;break;\r
-        case XSLT_FUNC_PI:\r
-            cur->func = (xsltTransformFunction) xsltProcessingInstruction;\r
-           break;\r
-        case XSLT_FUNC_COPYOF:\r
-            cur->func = (xsltTransformFunction) xsltCopyOf;break;\r
-        case XSLT_FUNC_VALUEOF:\r
-            cur->func = (xsltTransformFunction) xsltValueOf;break;\r
-        case XSLT_FUNC_NUMBER:\r
-            cur->func = (xsltTransformFunction) xsltNumber;break;\r
-        case XSLT_FUNC_APPLYIMPORTS:\r
-            cur->func = (xsltTransformFunction) xsltApplyImports;break;\r
-        case XSLT_FUNC_CALLTEMPLATE:\r
-            cur->func = (xsltTransformFunction) xsltCallTemplate;break;\r
-        case XSLT_FUNC_APPLYTEMPLATES:\r
-            cur->func = (xsltTransformFunction) xsltApplyTemplates;break;\r
-        case XSLT_FUNC_CHOOSE:\r
-            cur->func = (xsltTransformFunction) xsltChoose;break;\r
-        case XSLT_FUNC_IF:\r
-            cur->func = (xsltTransformFunction) xsltIf;break;\r
-        case XSLT_FUNC_FOREACH:\r
-            cur->func = (xsltTransformFunction) xsltForEach;break;\r
-        case XSLT_FUNC_DOCUMENT:\r
-            cur->func = (xsltTransformFunction) xsltDocumentElem;break;\r
-       case XSLT_FUNC_WITHPARAM:\r
-       case XSLT_FUNC_PARAM:       \r
-       case XSLT_FUNC_VARIABLE:            \r
-       case XSLT_FUNC_WHEN:\r
-           break;\r
-       default:\r
-       if (cur->func == NULL) {\r
-           xsltTransformError(NULL, style, NULL,\r
-                   "xsltNewStylePreComp : no function for type %d\n", type);\r
-           style->errors++;\r
-       }\r
-    }\r
-    cur->next = style->preComps;\r
-    style->preComps = (xsltElemPreCompPtr) cur;\r
-\r
-    return(cur);\r
-}\r
-\r
-/**\r
- * xsltFreeStylePreComp:\r
- * @comp:  an XSLT Style precomputed block\r
- *\r
- * Free up the memory allocated by @comp\r
- */\r
-static void\r
-xsltFreeStylePreComp(xsltStylePreCompPtr comp) {\r
-    if (comp == NULL)\r
-       return;\r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * URGENT TODO: Implement destructors.\r
-    */\r
-    switch (comp->type) {\r
-       case XSLT_FUNC_LITERAL_RESULT_ELEMENT:\r
-           break;\r
-       case XSLT_FUNC_COPY:\r
-            break;\r
-        case XSLT_FUNC_SORT: {\r
-               xsltStyleItemSortPtr item = (xsltStyleItemSortPtr) comp;\r
-               if (item->comp != NULL)\r
-                   xmlXPathFreeCompExpr(item->comp);\r
-           }\r
-            break;\r
-        case XSLT_FUNC_TEXT:\r
-            break;\r
-        case XSLT_FUNC_ELEMENT:\r
-            break;\r
-        case XSLT_FUNC_ATTRIBUTE:\r
-            break;\r
-        case XSLT_FUNC_COMMENT:\r
-            break;\r
-        case XSLT_FUNC_PI:\r
-           break;\r
-        case XSLT_FUNC_COPYOF: {\r
-               xsltStyleItemCopyOfPtr item = (xsltStyleItemCopyOfPtr) comp;\r
-               if (item->comp != NULL)\r
-                   xmlXPathFreeCompExpr(item->comp);\r
-           }\r
-            break;\r
-        case XSLT_FUNC_VALUEOF: {\r
-               xsltStyleItemValueOfPtr item = (xsltStyleItemValueOfPtr) comp;\r
-               if (item->comp != NULL)\r
-                   xmlXPathFreeCompExpr(item->comp);\r
-           }\r
-            break;\r
-        case XSLT_FUNC_NUMBER:\r
-            break;\r
-        case XSLT_FUNC_APPLYIMPORTS:\r
-            break;\r
-        case XSLT_FUNC_CALLTEMPLATE:\r
-            break;\r
-        case XSLT_FUNC_APPLYTEMPLATES: {\r
-               xsltStyleItemApplyTemplatesPtr item =\r
-                   (xsltStyleItemApplyTemplatesPtr) comp;\r
-               if (item->comp != NULL)\r
-                   xmlXPathFreeCompExpr(item->comp);\r
-           }\r
-            break;\r
-        case XSLT_FUNC_CHOOSE:\r
-            break;\r
-        case XSLT_FUNC_IF: {\r
-               xsltStyleItemIfPtr item = (xsltStyleItemIfPtr) comp;\r
-               if (item->comp != NULL)\r
-                   xmlXPathFreeCompExpr(item->comp);\r
-           }\r
-            break;\r
-        case XSLT_FUNC_FOREACH: {\r
-               xsltStyleItemForEachPtr item =\r
-                   (xsltStyleItemForEachPtr) comp;\r
-               if (item->comp != NULL)\r
-                   xmlXPathFreeCompExpr(item->comp);\r
-           }\r
-            break;\r
-        case XSLT_FUNC_DOCUMENT:\r
-            break;\r
-       case XSLT_FUNC_WITHPARAM: {\r
-               xsltStyleItemWithParamPtr item =\r
-                   (xsltStyleItemWithParamPtr) comp;\r
-               if (item->comp != NULL)\r
-                   xmlXPathFreeCompExpr(item->comp);\r
-           }\r
-           break;\r
-       case XSLT_FUNC_PARAM: {\r
-               xsltStyleItemParamPtr item =\r
-                   (xsltStyleItemParamPtr) comp;\r
-               if (item->comp != NULL)\r
-                   xmlXPathFreeCompExpr(item->comp);\r
-           }\r
-           break;\r
-       case XSLT_FUNC_VARIABLE: {\r
-               xsltStyleItemVariablePtr item =\r
-                   (xsltStyleItemVariablePtr) comp;\r
-               if (item->comp != NULL)\r
-                   xmlXPathFreeCompExpr(item->comp);\r
-           }\r
-           break;\r
-       case XSLT_FUNC_WHEN: {\r
-               xsltStyleItemWhenPtr item =\r
-                   (xsltStyleItemWhenPtr) comp;\r
-               if (item->comp != NULL)\r
-                   xmlXPathFreeCompExpr(item->comp);\r
-           }\r
-           break;\r
-       case XSLT_FUNC_OTHERWISE:           \r
-       case XSLT_FUNC_FALLBACK:\r
-       case XSLT_FUNC_MESSAGE:\r
-       case XSLT_FUNC_INCLUDE:\r
-       case XSLT_FUNC_ATTRSET:\r
-       \r
-           break;\r
-       default:\r
-           /* TODO: Raise error. */\r
-           break;\r
-    }\r
-#else    \r
-    if (comp->comp != NULL)\r
-       xmlXPathFreeCompExpr(comp->comp);\r
-    if (comp->nsList != NULL)\r
-       xmlFree(comp->nsList);\r
-#endif\r
-\r
-    xmlFree(comp);\r
-}\r
-\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                 XSLT-1.1 extensions                                 *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltDocumentComp:\r
- * @style:  the XSLT stylesheet\r
- * @inst:  the instruction in the stylesheet\r
- * @function:  unused\r
- *\r
- * Pre process an XSLT-1.1 document element\r
- *\r
- * Returns a precompiled data structure for the element\r
- */\r
-xsltElemPreCompPtr\r
-xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst,\r
-                xsltTransformFunction function ATTRIBUTE_UNUSED) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemDocumentPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    const xmlChar *filename = NULL;\r
-\r
-    /*\r
-    * As of 2006-03-30, this function is currently defined in Libxslt\r
-    * to be used for:\r
-    * (in libxslt/extra.c)\r
-    * "output" in XSLT_SAXON_NAMESPACE\r
-    * "write" XSLT_XALAN_NAMESPACE\r
-    * "document" XSLT_XT_NAMESPACE\r
-    * "document" XSLT_NAMESPACE (from the abandoned old working\r
-    *                            draft of XSLT 1.1)\r
-    * (in libexslt/common.c)\r
-    * "document" in EXSLT_COMMON_NAMESPACE\r
-    */\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemDocumentPtr)\r
-       xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);\r
-#endif\r
-    \r
-    if (comp == NULL)\r
-       return (NULL);\r
-    comp->inst = inst;\r
-    comp->ver11 = 0;\r
-\r
-    if (xmlStrEqual(inst->name, (const xmlChar *) "output")) {\r
-#ifdef WITH_XSLT_DEBUG_EXTRA\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-           "Found saxon:output extension\n");\r
-#endif\r
-       /*\r
-       * The element "output" is in the namespace XSLT_SAXON_NAMESPACE\r
-       *   (http://icl.com/saxon)\r
-       * The @file is in no namespace; it is an AVT.\r
-       *   (http://www.computerwizards.com/saxon/doc/extensions.html#saxon:output)\r
-       *\r
-       * TODO: Do we need not to check the namespace here?\r
-       */\r
-       filename = xsltEvalStaticAttrValueTemplate(style, inst,\r
-                        (const xmlChar *)"file",\r
-                        NULL, &comp->has_filename);\r
-    } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) {\r
-#ifdef WITH_XSLT_DEBUG_EXTRA\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-           "Found xalan:write extension\n");\r
-#endif\r
-       /* the filename need to be interpreted */\r
-       /*\r
-       * TODO: Is "filename need to be interpreted" meant to be a todo?\r
-       *   Where will be the filename of xalan:write be processed?\r
-       *\r
-       * TODO: Do we need not to check the namespace here?\r
-       *   The extension ns is "http://xml.apache.org/xalan/redirect".\r
-       *   See http://xml.apache.org/xalan-j/extensionslib.html.\r
-       */\r
-    } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) {\r
-       if (inst->ns != NULL) {\r
-           if (xmlStrEqual(inst->ns->href, XSLT_NAMESPACE)) {\r
-               /*\r
-               * Mark the instruction as being of\r
-               * XSLT version 1.1 (abandoned).\r
-               */\r
-               comp->ver11 = 1;\r
-#ifdef WITH_XSLT_DEBUG_EXTRA\r
-               xsltGenericDebug(xsltGenericDebugContext,\r
-                   "Found xslt11:document construct\n");\r
-#endif                 \r
-           } else {            \r
-               if (xmlStrEqual(inst->ns->href,\r
-                   (const xmlChar *)"http://exslt.org/common")) {\r
-                   /* EXSLT. */\r
-#ifdef WITH_XSLT_DEBUG_EXTRA\r
-                   xsltGenericDebug(xsltGenericDebugContext,\r
-                       "Found exslt:document extension\n");\r
-#endif\r
-               } else if (xmlStrEqual(inst->ns->href, XSLT_XT_NAMESPACE)) {\r
-                   /* James Clark's XT. */\r
-#ifdef WITH_XSLT_DEBUG_EXTRA\r
-                   xsltGenericDebug(xsltGenericDebugContext,\r
-                       "Found xt:document extension\n");\r
-#endif\r
-               }\r
-           }\r
-       }\r
-       /*\r
-       * The element "document" is used in conjunction with the\r
-       * following namespaces:\r
-       *\r
-       * 1) XSLT_NAMESPACE (http://www.w3.org/1999/XSL/Transform version 1.1)\r
-       *    <!ELEMENT xsl:document %template;>\r
-       *    <!ATTLIST xsl:document\r
-       *       href %avt; #REQUIRED\r
-       *    @href is an AVT\r
-       *    IMPORTANT: xsl:document was in the abandoned XSLT 1.1 draft,\r
-       *    it was removed and isn't available in XSLT 1.1 anymore.\r
-       *    In XSLT 2.0 it was renamed to xsl:result-document.\r
-       *\r
-       *   All other attributes are identical to the attributes\r
-       *   on xsl:output\r
-       *\r
-       * 2) EXSLT_COMMON_NAMESPACE (http://exslt.org/common)\r
-       *    <exsl:document\r
-       *       href = { uri-reference }\r
-       *    TODO: is @href is an AVT?\r
-       *\r
-       * 3) XSLT_XT_NAMESPACE (http://www.jclark.com/xt)\r
-       *     Example: <xt:document method="xml" href="myFile.xml">\r
-       *    TODO: is @href is an AVT?\r
-       *               \r
-       * In all cases @href is in no namespace.\r
-       */\r
-       filename = xsltEvalStaticAttrValueTemplate(style, inst,\r
-           (const xmlChar *)"href", NULL, &comp->has_filename);\r
-    }          \r
-    if (!comp->has_filename) {\r
-       goto error;\r
-    }\r
-    comp->filename = filename;\r
-\r
-error:\r
-    return ((xsltElemPreCompPtr) comp);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Most of the XSLT-1.0 transformations                    *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltSortComp:\r
- * @style:  the XSLT stylesheet\r
- * @inst:  the xslt sort node\r
- *\r
- * Process the xslt sort node on the source node\r
- */\r
-static void\r
-xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemSortPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemSortPtr) xsltNewStylePreComp(style, XSLT_FUNC_SORT);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_SORT);\r
-#endif\r
-    \r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    comp->stype = xsltEvalStaticAttrValueTemplate(style, inst,\r
-                        (const xmlChar *)"data-type",\r
-                        NULL, &comp->has_stype);\r
-    if (comp->stype != NULL) {\r
-       if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))\r
-           comp->number = 0;\r
-       else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))\r
-           comp->number = 1;\r
-       else {\r
-           xsltTransformError(NULL, style, inst,\r
-                "xsltSortComp: no support for data-type = %s\n", comp->stype);\r
-           comp->number = 0; /* use default */\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-    }\r
-    comp->order = xsltEvalStaticAttrValueTemplate(style, inst,\r
-                             (const xmlChar *)"order",\r
-                             NULL, &comp->has_order);\r
-    if (comp->order != NULL) {\r
-       if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))\r
-           comp->descending = 0;\r
-       else if (xmlStrEqual(comp->order, (const xmlChar *) "descending"))\r
-           comp->descending = 1;\r
-       else {\r
-           xsltTransformError(NULL, style, inst,\r
-                "xsltSortComp: invalid value %s for order\n", comp->order);\r
-           comp->descending = 0; /* use default */\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-    }\r
-    comp->case_order = xsltEvalStaticAttrValueTemplate(style, inst,\r
-                             (const xmlChar *)"case-order",\r
-                             NULL, &comp->has_use);\r
-    if (comp->case_order != NULL) {\r
-       if (xmlStrEqual(comp->case_order, (const xmlChar *) "upper-first"))\r
-           comp->lower_first = 0;\r
-       else if (xmlStrEqual(comp->case_order, (const xmlChar *) "lower-first"))\r
-           comp->lower_first = 1;\r
-       else {\r
-           xsltTransformError(NULL, style, inst,\r
-                "xsltSortComp: invalid value %s for order\n", comp->order);\r
-           comp->lower_first = 0; /* use default */\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-    }\r
-\r
-    comp->lang = xsltEvalStaticAttrValueTemplate(style, inst,\r
-                                (const xmlChar *)"lang",\r
-                                NULL, &comp->has_lang);\r
-\r
-    comp->select = xsltGetCNsProp(style, inst,(const xmlChar *)"select", XSLT_NAMESPACE);\r
-    if (comp->select == NULL) {\r
-       /*\r
-        * The default value of the select attribute is ., which will\r
-        * cause the string-value of the current node to be used as\r
-        * the sort key.\r
-        */\r
-       comp->select = xmlDictLookup(style->dict, BAD_CAST ".", 1);\r
-    }\r
-    comp->comp = xsltXPathCompile(style, comp->select);\r
-    if (comp->comp == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "xsltSortComp: could not compile select expression '%s'\n",\r
-                        comp->select);\r
-       if (style != NULL) style->errors++;\r
-    }\r
-    if (inst->children != NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-       "xsl:sort : is not empty\n");\r
-       if (style != NULL) style->errors++;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltCopyComp:\r
- * @style:  the XSLT stylesheet\r
- * @inst:  the xslt copy node\r
- *\r
- * Process the xslt copy node on the source node\r
- */\r
-static void\r
-xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemCopyPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemCopyPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPY);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_COPY);\r
-#endif\r
-    \r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-\r
-    comp->use = xsltGetCNsProp(style, inst, (const xmlChar *)"use-attribute-sets",\r
-                                   XSLT_NAMESPACE);\r
-    if (comp->use == NULL)\r
-       comp->has_use = 0;\r
-    else\r
-       comp->has_use = 1;\r
-}\r
-\r
-#ifdef XSLT_REFACTORED\r
-    /* Enable if ever needed for xsl:text. */\r
-#else\r
-/**\r
- * xsltTextComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt text node\r
- *\r
- * TODO: This function is obsolete, since xsl:text won't\r
- *  be compiled, but removed from the tree.\r
- *\r
- * Process the xslt text node on the source node\r
- */\r
-static void\r
-xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemTextPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    const xmlChar *prop;\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemTextPtr) xsltNewStylePreComp(style, XSLT_FUNC_TEXT);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_TEXT);\r
-#endif    \r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-    comp->noescape = 0;\r
-\r
-    prop = xsltGetCNsProp(style, inst,\r
-           (const xmlChar *)"disable-output-escaping",\r
-                       XSLT_NAMESPACE);\r
-    if (prop != NULL) {\r
-       if (xmlStrEqual(prop, (const xmlChar *)"yes")) {\r
-           comp->noescape = 1;\r
-       } else if (!xmlStrEqual(prop,\r
-           (const xmlChar *)"no")){\r
-           xsltTransformError(NULL, style, inst,\r
-               "xsl:text: disable-output-escaping allows only yes or no\n");\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-    }\r
-}\r
-#endif /* else of XSLT_REFACTORED */\r
-\r
-/**\r
- * xsltElementComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt element node\r
- *\r
- * Process the xslt element node on the source node\r
- */\r
-static void\r
-xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemElementPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    /*\r
-    * <xsl:element\r
-    *   name = { qname }\r
-    *   namespace = { uri-reference }\r
-    *   use-attribute-sets = qnames>\r
-    *   <!-- Content: template -->\r
-    * </xsl:element>\r
-    */\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemElementPtr) xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    /*\r
-    * Attribute "name".\r
-    */\r
-    /*\r
-    * TODO: Precompile the AVT. See bug #344894.\r
-    */\r
-    comp->name = xsltEvalStaticAttrValueTemplate(style, inst,\r
-       (const xmlChar *)"name", NULL, &comp->has_name);\r
-    if (! comp->has_name) {\r
-       xsltTransformError(NULL, style, inst,\r
-           "xsl:element: The attribute 'name' is missing.\n");\r
-       style->errors++;\r
-       goto error;\r
-    }\r
-    /*\r
-    * Attribute "namespace".\r
-    */\r
-    /*\r
-    * TODO: Precompile the AVT. See bug #344894.\r
-    */\r
-    comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,\r
-       (const xmlChar *)"namespace", NULL, &comp->has_ns);\r
-    \r
-    if (comp->name != NULL) {  \r
-       if (xmlValidateQName(comp->name, 0)) {\r
-           xsltTransformError(NULL, style, inst,\r
-               "xsl:element: The value '%s' of the attribute 'name' is "\r
-               "not a valid QName.\n", comp->name);\r
-           style->errors++;\r
-       } else {\r
-           const xmlChar *prefix = NULL, *name;\r
-\r
-           name = xsltSplitQName(style->dict, comp->name, &prefix);\r
-           if (comp->has_ns == 0) {        \r
-               xmlNsPtr ns;\r
-\r
-               /*\r
-               * SPEC XSLT 1.0:\r
-               *  "If the namespace attribute is not present, then the QName is\r
-               *  expanded into an expanded-name using the namespace declarations\r
-               *  in effect for the xsl:element element, including any default\r
-               *  namespace declaration.\r
-               */              \r
-               ns = xmlSearchNs(inst->doc, inst, prefix);\r
-               if (ns != NULL) {\r
-                   comp->ns = xmlDictLookup(style->dict, ns->href, -1);\r
-                   comp->has_ns = 1;\r
-#ifdef XSLT_REFACTORED\r
-                   comp->nsPrefix = prefix;\r
-                   comp->name = name;\r
-#endif\r
-               } else if (prefix != NULL) {\r
-                   xsltTransformError(NULL, style, inst,\r
-                       "xsl:element: The prefixed QName '%s' "\r
-                       "has no namespace binding in scope in the "\r
-                       "stylesheet; this is an error, since the namespace was "\r
-                       "not specified by the instruction itself.\n", comp->name);\r
-                   style->errors++;\r
-               }\r
-           }       \r
-           if ((prefix != NULL) &&\r
-               (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)))\r
-           {\r
-               /*\r
-               * Mark is to be skipped.\r
-               */\r
-               comp->has_name = 0;             \r
-           }\r
-       }\r
-    }    \r
-    /*\r
-    * Attribute "use-attribute-sets",\r
-    */\r
-    comp->use = xsltEvalStaticAttrValueTemplate(style, inst,\r
-                      (const xmlChar *)"use-attribute-sets",\r
-                      NULL, &comp->has_use);\r
-\r
-error:    \r
-    return;\r
-}\r
-\r
-/**\r
- * xsltAttributeComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt attribute node\r
- *\r
- * Process the xslt attribute node on the source node\r
- */\r
-static void\r
-xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemAttributePtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    /*\r
-    * <xsl:attribute\r
-    *   name = { qname }\r
-    *   namespace = { uri-reference }>\r
-    *   <!-- Content: template -->\r
-    * </xsl:attribute>\r
-    */\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemAttributePtr) xsltNewStylePreComp(style,\r
-       XSLT_FUNC_ATTRIBUTE);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_ATTRIBUTE);\r
-#endif\r
-    \r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    /*\r
-    * Attribute "name".\r
-    */\r
-    /*\r
-    * TODO: Precompile the AVT. See bug #344894.\r
-    */\r
-    comp->name = xsltEvalStaticAttrValueTemplate(style, inst,\r
-                                (const xmlChar *)"name",\r
-                                NULL, &comp->has_name);\r
-    if (! comp->has_name) {\r
-       xsltTransformError(NULL, style, inst,\r
-           "XSLT-attribute: The attribute 'name' is missing.\n");\r
-       style->errors++;\r
-       return;\r
-    }    \r
-    /*\r
-    * Attribute "namespace".\r
-    */\r
-    /*\r
-    * TODO: Precompile the AVT. See bug #344894.\r
-    */\r
-    comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,\r
-       (const xmlChar *)"namespace",\r
-       NULL, &comp->has_ns);\r
-\r
-    if (comp->name != NULL) {\r
-       if (xmlValidateQName(comp->name, 0)) {\r
-           xsltTransformError(NULL, style, inst,\r
-               "xsl:attribute: The value '%s' of the attribute 'name' is "\r
-               "not a valid QName.\n", comp->name);\r
-           style->errors++;\r
-       } else {\r
-           const xmlChar *prefix = NULL, *name;\r
-\r
-           name = xsltSplitQName(style->dict, comp->name, &prefix);\r
-           if (prefix != NULL) {\r
-               if (comp->has_ns == 0) {\r
-                   xmlNsPtr ns;\r
-\r
-                   /*\r
-                   * SPEC XSLT 1.0:\r
-                   *  "If the namespace attribute is not present, then the\r
-                   *  QName is expanded into an expanded-name using the\r
-                   *  namespace declarations in effect for the xsl:element\r
-                   *  element, including any default namespace declaration.\r
-                   */              \r
-                   ns = xmlSearchNs(inst->doc, inst, prefix);\r
-                   if (ns != NULL) {\r
-                       comp->ns = xmlDictLookup(style->dict, ns->href, -1);\r
-                       comp->has_ns = 1;\r
-#ifdef XSLT_REFACTORED\r
-                       comp->nsPrefix = prefix;\r
-                       comp->name = name;\r
-#endif\r
-                   } else {\r
-                       xsltTransformError(NULL, style, inst,\r
-                           "xsl:attribute: The prefixed QName '%s' "\r
-                           "has no namespace binding in scope in the "\r
-                           "stylesheet; this is an error, since the "\r
-                           "namespace was not specified by the instruction "\r
-                           "itself.\n", comp->name);\r
-                       style->errors++;\r
-                   }\r
-               }\r
-               if (!xmlStrncasecmp(prefix, (xmlChar *) "xmlns", 5)) {\r
-                   /*\r
-                   * SPEC XSLT 1.0:\r
-                   *  "It is an error if the string that results from\r
-                   *  instantiating the attribute value template is not a\r
-                   *  QName or is the string xmlns. An XSLT processor may\r
-                   *  signal the error; if it does not signal the error,\r
-                   *  it must recover by not adding the attribute to the\r
-                   *  result tree."\r
-                   *\r
-                   * Reject a prefix of "xmlns". Mark to be skipped.\r
-                   */\r
-                   comp->has_name = 0;\r
-                   \r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-                   xsltGenericDebug(xsltGenericDebugContext,\r
-                       "xsltAttribute: xmlns prefix forbidden\n");\r
-#endif             \r
-                   return;\r
-               }\r
-               \r
-           }\r
-       }       \r
-    }\r
-}\r
-\r
-/**\r
- * xsltCommentComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt comment node\r
- *\r
- * Process the xslt comment node on the source node\r
- */\r
-static void\r
-xsltCommentComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemCommentPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemCommentPtr) xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-}\r
-\r
-/**\r
- * xsltProcessingInstructionComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt processing-instruction node\r
- *\r
- * Process the xslt processing-instruction node on the source node\r
- */\r
-static void\r
-xsltProcessingInstructionComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemPIPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemPIPtr) xsltNewStylePreComp(style, XSLT_FUNC_PI);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_PI);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    comp->name = xsltEvalStaticAttrValueTemplate(style, inst,\r
-                                (const xmlChar *)"name",\r
-                                XSLT_NAMESPACE, &comp->has_name);\r
-}\r
-\r
-/**\r
- * xsltCopyOfComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt copy-of node\r
- *\r
- * Process the xslt copy-of node on the source node\r
- */\r
-static void\r
-xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemCopyOfPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemCopyOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",\r
-                               XSLT_NAMESPACE);\r
-    if (comp->select == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "xsl:copy-of : select is missing\n");\r
-       if (style != NULL) style->errors++;\r
-       return;\r
-    }\r
-    comp->comp = xsltXPathCompile(style, comp->select);\r
-    if (comp->comp == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "xsl:copy-of : could not compile select expression '%s'\n",\r
-                        comp->select);\r
-       if (style != NULL) style->errors++;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltValueOfComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt value-of node\r
- *\r
- * Process the xslt value-of node on the source node\r
- */\r
-static void\r
-xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemValueOfPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    const xmlChar *prop;\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemValueOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    prop = xsltGetCNsProp(style, inst,\r
-           (const xmlChar *)"disable-output-escaping",\r
-                       XSLT_NAMESPACE);\r
-    if (prop != NULL) {\r
-       if (xmlStrEqual(prop, (const xmlChar *)"yes")) {\r
-           comp->noescape = 1;\r
-       } else if (!xmlStrEqual(prop,\r
-                               (const xmlChar *)"no")){\r
-           xsltTransformError(NULL, style, inst,\r
-"xsl:value-of : disable-output-escaping allows only yes or no\n");\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-    }\r
-    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",\r
-                               XSLT_NAMESPACE);\r
-    if (comp->select == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "xsl:value-of : select is missing\n");\r
-       if (style != NULL) style->errors++;\r
-       return;\r
-    }\r
-    comp->comp = xsltXPathCompile(style, comp->select);\r
-    if (comp->comp == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "xsl:value-of : could not compile select expression '%s'\n",\r
-                        comp->select);\r
-       if (style != NULL) style->errors++;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltWithParamComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt with-param node\r
- *\r
- * Process the xslt with-param node on the source node\r
- * Allowed parents: xsl:call-template, xsl:apply-templates.\r
- * <xsl:with-param\r
- *  name = qname\r
- *  select = expression>\r
- *  <!-- Content: template -->\r
- * </xsl:with-param>\r
- */\r
-static void\r
-xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemWithParamPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    const xmlChar *prop;\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemWithParamPtr) xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    /*\r
-     * The full namespace resolution can be done statically\r
-     */\r
-    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);\r
-    if (prop == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "xsl:with-param : name is missing\n");\r
-       if (style != NULL) style->errors++;\r
-    } else {\r
-        const xmlChar *URI;\r
-\r
-       /*\r
-       * @prop will be in the string dict afterwards, @URI not.\r
-       */\r
-       URI = xsltGetQNameURI2(style, inst, &prop);\r
-       if (prop == NULL) {\r
-           if (style != NULL) style->errors++;\r
-       } else {\r
-           comp->name = prop;\r
-           comp->has_name = 1;\r
-           if (URI != NULL) {\r
-               /*\r
-               * Fixes bug #308441: Put the ns-name in the dict\r
-               * in order to pointer compare names during XPath's\r
-               * variable lookup.\r
-               */\r
-               comp->ns = xmlDictLookup(style->dict, URI, -1);\r
-               comp->has_ns = 1;\r
-           } else {\r
-               comp->has_ns = 0;\r
-           }\r
-       }\r
-    }\r
-\r
-    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",\r
-                               XSLT_NAMESPACE);\r
-    if (comp->select != NULL) {\r
-       comp->comp = xsltXPathCompile(style, comp->select);\r
-       if (comp->comp == NULL) {\r
-           xsltTransformError(NULL, style, inst,\r
-                "xsl:param : could not compile select expression '%s'\n",\r
-                            comp->select);\r
-           if (style != NULL) style->errors++;\r
-       }\r
-       if (inst->children != NULL) {\r
-           xsltTransformError(NULL, style, inst,\r
-           "xsl:param : content should be empty since select is present \n");\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-    }\r
-}\r
-\r
-/**\r
- * xsltNumberComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @cur:   the xslt number node\r
- *\r
- * Process the xslt number node on the source node\r
- */\r
-static void\r
-xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemNumberPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    const xmlChar *prop;\r
-\r
-    if ((style == NULL) || (cur == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemNumberPtr) xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    cur->psvi = comp;\r
-\r
-    if ((style == NULL) || (cur == NULL))\r
-       return;\r
-\r
-    comp->numdata.doc = cur->doc;\r
-    comp->numdata.node = cur;\r
-    comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value",\r
-                                       XSLT_NAMESPACE);\r
-    \r
-    prop = xsltEvalStaticAttrValueTemplate(style, cur,\r
-                        (const xmlChar *)"format",\r
-                        XSLT_NAMESPACE, &comp->numdata.has_format);\r
-    if (comp->numdata.has_format == 0) {\r
-       comp->numdata.format = xmlDictLookup(style->dict, BAD_CAST "" , 0);\r
-    } else {\r
-       comp->numdata.format = prop;\r
-    }\r
-\r
-    comp->numdata.count = xsltGetCNsProp(style, cur, (const xmlChar *)"count",\r
-                                       XSLT_NAMESPACE);\r
-    comp->numdata.from = xsltGetCNsProp(style, cur, (const xmlChar *)"from",\r
-                                       XSLT_NAMESPACE);\r
-    \r
-    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"level", XSLT_NAMESPACE);\r
-    if (prop != NULL) {\r
-       if (xmlStrEqual(prop, BAD_CAST("single")) ||\r
-           xmlStrEqual(prop, BAD_CAST("multiple")) ||\r
-           xmlStrEqual(prop, BAD_CAST("any"))) {\r
-           comp->numdata.level = prop;\r
-       } else {\r
-           xsltTransformError(NULL, style, cur,\r
-                        "xsl:number : invalid value %s for level\n", prop);\r
-           if (style != NULL) style->warnings++;\r
-           xmlFree((void *)(prop));\r
-       }\r
-    }\r
-    \r
-    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"lang", XSLT_NAMESPACE);\r
-    if (prop != NULL) {\r
-       XSLT_TODO; /* xsl:number lang attribute */\r
-       xmlFree((void *)prop);\r
-    }\r
-    \r
-    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE);\r
-    if (prop != NULL) {\r
-       if (xmlStrEqual(prop, BAD_CAST("alphabetic"))) {\r
-           xsltTransformError(NULL, style, cur,\r
-                "xsl:number : letter-value 'alphabetic' not implemented\n");\r
-           if (style != NULL) style->warnings++;\r
-           XSLT_TODO; /* xsl:number letter-value attribute alphabetic */\r
-       } else if (xmlStrEqual(prop, BAD_CAST("traditional"))) {\r
-           xsltTransformError(NULL, style, cur,\r
-                "xsl:number : letter-value 'traditional' not implemented\n");\r
-           if (style != NULL) style->warnings++;\r
-           XSLT_TODO; /* xsl:number letter-value attribute traditional */\r
-       } else {\r
-           xsltTransformError(NULL, style, cur,\r
-                    "xsl:number : invalid value %s for letter-value\n", prop);\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-    }\r
-    \r
-    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-separator",\r
-                       XSLT_NAMESPACE);\r
-    if (prop != NULL) {\r
-        comp->numdata.groupingCharacterLen = xmlStrlen(prop);\r
-       comp->numdata.groupingCharacter =\r
-           xsltGetUTF8Char(prop, &(comp->numdata.groupingCharacterLen));\r
-    }\r
-    \r
-    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE);\r
-    if (prop != NULL) {\r
-       sscanf((char *)prop, "%d", &comp->numdata.digitsPerGroup);\r
-    } else {\r
-       comp->numdata.groupingCharacter = 0;\r
-    }\r
-\r
-    /* Set default values */\r
-    if (comp->numdata.value == NULL) {\r
-       if (comp->numdata.level == NULL) {\r
-           comp->numdata.level = xmlDictLookup(style->dict,\r
-                                               BAD_CAST"single", 6);\r
-       }\r
-    }\r
-    \r
-}\r
-\r
-/**\r
- * xsltApplyImportsComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt apply-imports node\r
- *\r
- * Process the xslt apply-imports node on the source node\r
- */\r
-static void\r
-xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemApplyImportsPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemApplyImportsPtr) xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-}\r
-\r
-/**\r
- * xsltCallTemplateComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt call-template node\r
- *\r
- * Process the xslt call-template node on the source node\r
- */\r
-static void\r
-xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemCallTemplatePtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    const xmlChar *prop;\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemCallTemplatePtr)\r
-       xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    /*\r
-     * The full template resolution can be done statically\r
-     */\r
-    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);\r
-    if (prop == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "xsl:call-template : name is missing\n");\r
-       if (style != NULL) style->errors++;\r
-    } else {\r
-        const xmlChar *URI;\r
-\r
-       URI = xsltGetQNameURI2(style, inst, &prop);\r
-       if (prop == NULL) {\r
-           if (style != NULL) style->errors++;\r
-       } else {\r
-           comp->name = prop;\r
-           comp->has_name = 1;\r
-           if (URI != NULL) {\r
-               comp->ns = xmlDictLookup(style->dict, URI, -1);\r
-               comp->has_ns = 1;\r
-           } else {\r
-               comp->has_ns = 0;\r
-           }\r
-       }\r
-       comp->templ = NULL;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltApplyTemplatesComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the apply-templates node\r
- *\r
- * Process the apply-templates node on the source node\r
- */\r
-static void\r
-xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemApplyTemplatesPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    const xmlChar *prop;\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemApplyTemplatesPtr)\r
-       xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    /*\r
-     * Get mode if any\r
-     */\r
-    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"mode", XSLT_NAMESPACE);\r
-    if (prop != NULL) {\r
-        const xmlChar *URI;\r
-\r
-       URI = xsltGetQNameURI2(style, inst, &prop);\r
-       if (prop == NULL) {\r
-           if (style != NULL) style->errors++;\r
-       } else {\r
-           comp->mode = xmlDictLookup(style->dict, prop, -1);\r
-           if (URI != NULL) {\r
-               comp->modeURI = xmlDictLookup(style->dict, URI, -1);\r
-           } else {\r
-               comp->modeURI = NULL;\r
-           }\r
-       }\r
-    }\r
-    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",\r
-                               XSLT_NAMESPACE);\r
-    if (comp->select != NULL) {\r
-       comp->comp = xsltXPathCompile(style, comp->select);\r
-       if (comp->comp == NULL) {\r
-           xsltTransformError(NULL, style, inst,\r
-     "xsl:apply-templates : could not compile select expression '%s'\n",\r
-                            comp->select);\r
-           if (style != NULL) style->errors++;\r
-       }\r
-    }\r
-\r
-    /* TODO: handle (or skip) the xsl:sort and xsl:with-param */\r
-}\r
-\r
-/**\r
- * xsltChooseComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt choose node\r
- *\r
- * Process the xslt choose node on the source node\r
- */\r
-static void\r
-xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemChoosePtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemChoosePtr)\r
-       xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-}\r
-\r
-/**\r
- * xsltIfComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt if node\r
- *\r
- * Process the xslt if node on the source node\r
- */\r
-static void\r
-xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemIfPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemIfPtr)\r
-       xsltNewStylePreComp(style, XSLT_FUNC_IF);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_IF);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);\r
-    if (comp->test == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "xsl:if : test is not defined\n");\r
-       if (style != NULL) style->errors++;\r
-       return;\r
-    }\r
-    comp->comp = xsltXPathCompile(style, comp->test);\r
-    if (comp->comp == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "xsl:if : could not compile test expression '%s'\n",\r
-                        comp->test);\r
-       if (style != NULL) style->errors++;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltWhenComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt if node\r
- *\r
- * Process the xslt if node on the source node\r
- */\r
-static void\r
-xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemWhenPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemWhenPtr)\r
-       xsltNewStylePreComp(style, XSLT_FUNC_WHEN);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_WHEN);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);\r
-    if (comp->test == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "xsl:when : test is not defined\n");\r
-       if (style != NULL) style->errors++;\r
-       return;\r
-    }\r
-    comp->comp = xsltXPathCompile(style, comp->test);\r
-    if (comp->comp == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "xsl:when : could not compile test expression '%s'\n",\r
-                        comp->test);\r
-       if (style != NULL) style->errors++;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltForEachComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt for-each node\r
- *\r
- * Process the xslt for-each node on the source node\r
- */\r
-static void\r
-xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemForEachPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemForEachPtr)\r
-       xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",\r
-                               XSLT_NAMESPACE);\r
-    if (comp->select == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-               "xsl:for-each : select is missing\n");\r
-       if (style != NULL) style->errors++;\r
-    } else {\r
-       comp->comp = xsltXPathCompile(style, comp->select);\r
-       if (comp->comp == NULL) {\r
-           xsltTransformError(NULL, style, inst,\r
-     "xsl:for-each : could not compile select expression '%s'\n",\r
-                            comp->select);\r
-           if (style != NULL) style->errors++;\r
-       }\r
-    }\r
-    /* TODO: handle and skip the xsl:sort */\r
-}\r
-\r
-/**\r
- * xsltVariableComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt variable node\r
- *\r
- * Process the xslt variable node on the source node\r
- */\r
-static void\r
-xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemVariablePtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    const xmlChar *prop;\r
-    const xmlChar *URI;\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemVariablePtr)\r
-       xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-    /*\r
-     * The full template resolution can be done statically\r
-     */\r
-\r
-    /*\r
-    * Attribute "name".\r
-    */\r
-    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);\r
-    if (prop == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "XSLT-variable: The attribute 'name' is missing.\n");\r
-       style->errors++;\r
-       goto error;\r
-    }    \r
-    if (xmlValidateQName(prop, 0)) {\r
-       xsltTransformError(NULL, style, inst,\r
-           "XSLT-variable: The value '%s' of the attribute 'name' is "\r
-           "not a valid QName.\n", prop);\r
-       style->errors++;\r
-       goto error;\r
-    }\r
-    URI = xsltGetQNameURI2(style, inst, &prop);\r
-    if (prop == NULL) {\r
-       goto error;\r
-    }\r
-    comp->name = prop;\r
-    comp->has_name = 1;\r
-\r
-    if (URI != NULL) {\r
-       comp->ns = xmlDictLookup(style->dict, URI, -1);\r
-       comp->has_ns = 1;\r
-    } else {\r
-       comp->has_ns = 0;\r
-    }\r
-    /*\r
-    * Attribute "select".\r
-    */\r
-    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",\r
-                               XSLT_NAMESPACE);\r
-    if (comp->select != NULL) {\r
-       comp->comp = xsltXPathCompile(style, comp->select);\r
-       if (comp->comp == NULL) {\r
-           xsltTransformError(NULL, style, inst,\r
-               "XSLT-variable: Failed to compile the XPath expression '%s'.\n",\r
-               comp->select);\r
-           style->errors++;\r
-       }\r
-       if (inst->children != NULL) {\r
-           xsltTransformError(NULL, style, inst,\r
-               "XSLT-variable: The must be no child nodes, since the "\r
-               "attribute 'select' was specified.\n");\r
-           style->errors++;\r
-       }\r
-    }\r
-error:\r
-    return;\r
-}\r
-\r
-/**\r
- * xsltParamComp:\r
- * @style: an XSLT compiled stylesheet\r
- * @inst:  the xslt param node\r
- *\r
- * Process the xslt param node on the source node\r
- */\r
-static void\r
-xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemParamPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    const xmlChar *prop;\r
-\r
-    if ((style == NULL) || (inst == NULL))\r
-       return;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleItemParamPtr)\r
-       xsltNewStylePreComp(style, XSLT_FUNC_PARAM);\r
-#else\r
-    comp = xsltNewStylePreComp(style, XSLT_FUNC_PARAM);\r
-#endif\r
-\r
-    if (comp == NULL)\r
-       return;\r
-    inst->psvi = comp;\r
-    comp->inst = inst;\r
-\r
-    /*\r
-     * The full template resolution can be done statically\r
-     */\r
-    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);\r
-    if (prop == NULL) {\r
-       xsltTransformError(NULL, style, inst,\r
-            "xsl:param : name is missing\n");\r
-       if (style != NULL) style->errors++;\r
-    } else {\r
-        const xmlChar *URI;\r
-\r
-       URI = xsltGetQNameURI2(style, inst, &prop);\r
-       if (prop == NULL) {\r
-           if (style != NULL) style->errors++;\r
-       } else {\r
-           comp->name = prop;\r
-           comp->has_name = 1;\r
-           if (URI != NULL) {\r
-               comp->ns = xmlDictLookup(style->dict, URI, -1);\r
-               comp->has_ns = 1;\r
-           } else {\r
-               comp->has_ns = 0;\r
-           }\r
-       }\r
-    }\r
-\r
-    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",\r
-                               XSLT_NAMESPACE);\r
-    if (comp->select != NULL) {\r
-       comp->comp = xsltXPathCompile(style, comp->select);\r
-       if (comp->comp == NULL) {\r
-           xsltTransformError(NULL, style, inst,\r
-                "xsl:param : could not compile select expression '%s'\n",\r
-                            comp->select);\r
-           if (style != NULL) style->errors++;\r
-       }\r
-       if (inst->children != NULL) {\r
-           xsltTransformError(NULL, style, inst,\r
-       "xsl:param : content should be empty since select is present \n");\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-    }\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                 Generic interface                                   *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltFreeStylePreComps:\r
- * @style:  an XSLT transformation context\r
- *\r
- * Free up the memory allocated by all precomputed blocks\r
- */\r
-void\r
-xsltFreeStylePreComps(xsltStylesheetPtr style) {\r
-    xsltElemPreCompPtr cur, next;\r
-\r
-    if (style == NULL)\r
-       return;        \r
-    \r
-    cur = style->preComps;\r
-    while (cur != NULL) {\r
-       next = cur->next;               \r
-       if (cur->type == XSLT_FUNC_EXTENSION)\r
-           cur->free(cur);\r
-       else\r
-           xsltFreeStylePreComp((xsltStylePreCompPtr) cur);\r
-       cur = next;\r
-    }\r
-}\r
-\r
-#ifdef XSLT_REFACTORED\r
-\r
-/**\r
- * xsltStylePreCompute:\r
- * @style:  the XSLT stylesheet\r
- * @node:  the element in the XSLT namespace\r
- *\r
- * Precompute an XSLT element.\r
- * This expects the type of the element to be already\r
- * set in style->compCtxt->inode->type;\r
- */\r
-void\r
-xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr node) {\r
-    /*    \r
-    * The xsltXSLTElemMarker marker was set beforehand by\r
-    *  the parsing mechanism for all elements in the XSLT namespace.\r
-    */\r
-    if (style == NULL) {\r
-       if (node != NULL)\r
-           node->psvi = NULL;\r
-       return;\r
-    }\r
-    if (node == NULL)\r
-       return;\r
-    if (! IS_XSLT_ELEM_FAST(node))\r
-       return;\r
-\r
-    node->psvi = NULL;\r
-    if (XSLT_CCTXT(style)->inode->type != 0) {\r
-       switch (XSLT_CCTXT(style)->inode->type) {\r
-           case XSLT_FUNC_APPLYTEMPLATES:\r
-               xsltApplyTemplatesComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_WITHPARAM:                      \r
-               xsltWithParamComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_VALUEOF:         \r
-               xsltValueOfComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_COPY:            \r
-               xsltCopyComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_COPYOF:\r
-               xsltCopyOfComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_IF:      \r
-               xsltIfComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_CHOOSE:          \r
-               xsltChooseComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_WHEN:            \r
-               xsltWhenComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_OTHERWISE:       \r
-               /* NOP yet */\r
-               return;\r
-           case XSLT_FUNC_FOREACH:         \r
-               xsltForEachComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_APPLYIMPORTS:            \r
-               xsltApplyImportsComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_ATTRIBUTE:       \r
-               xsltAttributeComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_ELEMENT:         \r
-               xsltElementComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_SORT:            \r
-               xsltSortComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_COMMENT:         \r
-               xsltCommentComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_NUMBER:          \r
-               xsltNumberComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_PI:      \r
-               xsltProcessingInstructionComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_CALLTEMPLATE:            \r
-               xsltCallTemplateComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_PARAM:           \r
-               xsltParamComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_VARIABLE:        \r
-               xsltVariableComp(style, node);\r
-               break;\r
-           case XSLT_FUNC_FALLBACK:        \r
-               /* NOP yet */\r
-               return;\r
-           case XSLT_FUNC_DOCUMENT:        \r
-               /* The extra one */\r
-               node->psvi = (void *) xsltDocumentComp(style, node,\r
-                   (xsltTransformFunction) xsltDocumentElem);\r
-               break;\r
-           case XSLT_FUNC_MESSAGE:\r
-               /* NOP yet */\r
-               return;\r
-           default:\r
-               /*\r
-               * NOTE that xsl:text, xsl:template, xsl:stylesheet,\r
-               *  xsl:transform, xsl:import, xsl:include are not expected\r
-               *  to be handed over to this function.\r
-               */\r
-               xsltTransformError(NULL, style, node,\r
-                   "Internal error: (xsltStylePreCompute) cannot handle "\r
-                   "the XSLT element '%s'.\n", node->name);\r
-               style->errors++;\r
-               return;\r
-       }\r
-    } else {\r
-       /*\r
-       * Fallback to string comparison.\r
-       */      \r
-       if (IS_XSLT_NAME(node, "apply-templates")) {\r
-           xsltApplyTemplatesComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "with-param")) {\r
-           xsltWithParamComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "value-of")) {\r
-           xsltValueOfComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "copy")) {\r
-           xsltCopyComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "copy-of")) {\r
-           xsltCopyOfComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "if")) {\r
-           xsltIfComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "choose")) {\r
-           xsltChooseComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "when")) {\r
-           xsltWhenComp(style, node);  \r
-       } else if (IS_XSLT_NAME(node, "otherwise")) {\r
-           /* NOP yet */\r
-           return;\r
-       } else if (IS_XSLT_NAME(node, "for-each")) {\r
-           xsltForEachComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "apply-imports")) {\r
-           xsltApplyImportsComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "attribute")) {\r
-           xsltAttributeComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "element")) {\r
-           xsltElementComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "sort")) {\r
-           xsltSortComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "comment")) {\r
-           xsltCommentComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "number")) {\r
-           xsltNumberComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "processing-instruction")) {\r
-           xsltProcessingInstructionComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "call-template")) {\r
-           xsltCallTemplateComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "param")) {\r
-           xsltParamComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "variable")) {\r
-           xsltVariableComp(style, node);\r
-       } else if (IS_XSLT_NAME(node, "fallback")) {\r
-           /* NOP yet */\r
-           return;\r
-       } else if (IS_XSLT_NAME(node, "document")) {\r
-           /* The extra one */\r
-           node->psvi = (void *) xsltDocumentComp(style, node,\r
-               (xsltTransformFunction) xsltDocumentElem);      \r
-       } else if (IS_XSLT_NAME(node, "output")) {\r
-           /* Top-level */\r
-           return;\r
-       } else if (IS_XSLT_NAME(node, "preserve-space")) {\r
-           /* Top-level */\r
-           return;\r
-       } else if (IS_XSLT_NAME(node, "strip-space")) {\r
-           /* Top-level */\r
-           return;     \r
-       } else if (IS_XSLT_NAME(node, "key")) {\r
-           /* Top-level */\r
-           return;\r
-       } else if (IS_XSLT_NAME(node, "message")) {\r
-           return;\r
-       } else if (IS_XSLT_NAME(node, "attribute-set")) {\r
-           /* Top-level */\r
-           return;\r
-       } else if (IS_XSLT_NAME(node, "namespace-alias")) {\r
-           /* Top-level */\r
-           return;\r
-       } else if (IS_XSLT_NAME(node, "decimal-format")) {\r
-           /* Top-level */\r
-           return;\r
-       } else if (IS_XSLT_NAME(node, "include")) {\r
-           /* Top-level */                 \r
-       } else {\r
-           /*\r
-           * NOTE that xsl:text, xsl:template, xsl:stylesheet,\r
-           *  xsl:transform, xsl:import, xsl:include are not expected\r
-           *  to be handed over to this function.\r
-           */\r
-           xsltTransformError(NULL, style, node,\r
-               "Internal error: (xsltStylePreCompute) cannot handle "\r
-               "the XSLT element '%s'.\n", node->name);\r
-               style->errors++;\r
-           return;\r
-       }       \r
-    }\r
-    /*\r
-    * Assign the current list of in-scope namespaces to the\r
-    * item. This is needed for XPath expressions.\r
-    */\r
-    if (node->psvi != NULL) {\r
-       ((xsltStylePreCompPtr) node->psvi)->inScopeNs =\r
-           XSLT_CCTXT(style)->inode->inScopeNs;\r
-    }\r
-}\r
-\r
-#else\r
-\r
-/**\r
- * xsltStylePreCompute:\r
- * @style:  the XSLT stylesheet\r
- * @inst:  the instruction in the stylesheet\r
- *\r
- * Precompute an XSLT stylesheet element\r
- */\r
-void\r
-xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {\r
-    /*\r
-    * URGENT TODO: Normally inst->psvi Should never be reserved here,\r
-    *   BUT: since if we include the same stylesheet from\r
-    *   multiple imports, then the stylesheet will be parsed\r
-    *   again. We simply must not try to compute the stylesheet again.\r
-    * TODO: Get to the point where we don't need to query the\r
-    *   namespace- and local-name of the node, but can evaluate this\r
-    *   using cctxt->style->inode->category;\r
-    */\r
-    if (inst->psvi != NULL)\r
-       return;\r
-\r
-    if (IS_XSLT_ELEM(inst)) {\r
-       xsltStylePreCompPtr cur;\r
-\r
-       if (IS_XSLT_NAME(inst, "apply-templates")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltApplyTemplatesComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "with-param")) {\r
-           xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",\r
-                                  BAD_CAST "call-template");\r
-           xsltWithParamComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "value-of")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltValueOfComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "copy")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltCopyComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "copy-of")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltCopyOfComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "if")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltIfComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "when")) {\r
-           xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);\r
-           xsltWhenComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "choose")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltChooseComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "for-each")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltForEachComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "apply-imports")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltApplyImportsComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "attribute")) {\r
-           xmlNodePtr parent = inst->parent;\r
-\r
-           if ((parent == NULL) || (parent->ns == NULL) ||\r
-               ((parent->ns != inst->ns) &&\r
-                (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||\r
-               (!xmlStrEqual(parent->name, BAD_CAST "attribute-set"))) {\r
-               xsltCheckInstructionElement(style, inst);\r
-           }\r
-           xsltAttributeComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "element")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltElementComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "text")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltTextComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "sort")) {\r
-           xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",\r
-                                  BAD_CAST "for-each");\r
-           xsltSortComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "comment")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltCommentComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "number")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltNumberComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "processing-instruction")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltProcessingInstructionComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "call-template")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           xsltCallTemplateComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "param")) {          \r
-           if (xsltCheckTopLevelElement(style, inst, 0) == 0)\r
-               xsltCheckInstructionElement(style, inst);\r
-           xsltParamComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "variable")) {\r
-           if (xsltCheckTopLevelElement(style, inst, 0) == 0)\r
-               xsltCheckInstructionElement(style, inst);\r
-           xsltVariableComp(style, inst);\r
-       } else if (IS_XSLT_NAME(inst, "otherwise")) {\r
-           xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);\r
-           xsltCheckInstructionElement(style, inst);\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "template")) {\r
-           xsltCheckTopLevelElement(style, inst, 1);\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "output")) {\r
-           xsltCheckTopLevelElement(style, inst, 1);\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "preserve-space")) {\r
-           xsltCheckTopLevelElement(style, inst, 1);\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "strip-space")) {\r
-           xsltCheckTopLevelElement(style, inst, 1);\r
-           return;\r
-       } else if ((IS_XSLT_NAME(inst, "stylesheet")) ||\r
-                  (IS_XSLT_NAME(inst, "transform"))) {\r
-           xmlNodePtr parent = inst->parent;\r
-\r
-           if ((parent == NULL) || (parent->type != XML_DOCUMENT_NODE)) {\r
-               xsltTransformError(NULL, style, inst,\r
-                   "element %s only allowed only as root element\n",\r
-                                  inst->name);\r
-               style->errors++;\r
-           }\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "key")) {\r
-           xsltCheckTopLevelElement(style, inst, 1);\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "message")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "attribute-set")) {\r
-           xsltCheckTopLevelElement(style, inst, 1);\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "namespace-alias")) {\r
-           xsltCheckTopLevelElement(style, inst, 1);\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "include")) {\r
-           xsltCheckTopLevelElement(style, inst, 1);\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "import")) {\r
-           xsltCheckTopLevelElement(style, inst, 1);\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "decimal-format")) {\r
-           xsltCheckTopLevelElement(style, inst, 1);\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "fallback")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           return;\r
-       } else if (IS_XSLT_NAME(inst, "document")) {\r
-           xsltCheckInstructionElement(style, inst);\r
-           inst->psvi = (void *) xsltDocumentComp(style, inst,\r
-                               (xsltTransformFunction) xsltDocumentElem);\r
-       } else {\r
-           xsltTransformError(NULL, style, inst,\r
-                "xsltStylePreCompute: unknown xsl:%s\n", inst->name);\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-       \r
-       cur = (xsltStylePreCompPtr) inst->psvi;\r
-       /*\r
-       * A ns-list is build for every XSLT item in the\r
-       * node-tree. This is needed for XPath expressions.\r
-       */\r
-       if (cur != NULL) {\r
-           int i = 0;\r
-\r
-           cur->nsList = xmlGetNsList(inst->doc, inst);\r
-            if (cur->nsList != NULL) {\r
-               while (cur->nsList[i] != NULL)\r
-                   i++;\r
-           }\r
-           cur->nsNr = i;\r
-       }\r
-    } else {\r
-       inst->psvi =\r
-           (void *) xsltPreComputeExtModuleElement(style, inst);\r
-\r
-       /*\r
-        * Unknown element, maybe registered at the context\r
-        * level. Mark it for later recognition.\r
-        */\r
-       if (inst->psvi == NULL)\r
-           inst->psvi = (void *) xsltExtMarker;\r
-    }\r
-}\r
-#endif /* XSLT_REFACTORED */\r
+/*
+ * preproc.c: Preprocessing of style operations
+ *
+ * References:
+ *   http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ *   Michael Kay "XSLT Programmer's Reference" pp 637-643
+ *   Writing Multiple Output Files
+ *
+ *   XSLT-1.1 Working Draft
+ *   http://www.w3.org/TR/xslt11#multiple-output
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/valid.h>
+#include <libxml/hash.h>
+#include <libxml/uri.h>
+#include <libxml/encoding.h>
+#include <libxml/xmlerror.h>
+#include "xslt.h"
+#include "xsltutils.h"
+#include "xsltInternals.h"
+#include "transform.h"
+#include "templates.h"
+#include "variables.h"
+#include "numbersInternals.h"
+#include "preproc.h"
+#include "extra.h"
+#include "imports.h"
+#include "extensions.h"
+
+#ifdef WITH_XSLT_DEBUG
+#define WITH_XSLT_DEBUG_PREPROC
+#endif
+
+const xmlChar *xsltExtMarker = (const xmlChar *) "Extension Element";
+
+/************************************************************************
+ *                                                                     *
+ *                     Grammar checks                                  *
+ *                                                                     *
+ ************************************************************************/
+
+#ifdef XSLT_REFACTORED
+    /*
+    * Grammar checks are now performed in xslt.c.
+    */
+#else
+/**
+ * xsltCheckTopLevelElement:
+ * @style: the XSLT stylesheet
+ * @inst: the XSLT instruction
+ * @err: raise an error or not
+ *
+ * Check that the instruction is instanciated as a top level element.
+ *
+ * Returns -1 in case of error, 0 if failed and 1 in case of success
+ */
+static int
+xsltCheckTopLevelElement(xsltStylesheetPtr style, xmlNodePtr inst, int err) {
+    xmlNodePtr parent;
+    if ((style == NULL) || (inst == NULL) || (inst->ns == NULL))
+        return(-1);
+    
+    parent = inst->parent;
+    if (parent == NULL) {
+        if (err) {
+           xsltTransformError(NULL, style, inst,
+                   "internal problem: element has no parent\n");
+           style->errors++;
+       }
+       return(0);
+    }
+    if ((parent->ns == NULL) ||
+        ((parent->ns != inst->ns) &&
+        (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
+       ((!xmlStrEqual(parent->name, BAD_CAST "stylesheet")) &&
+        (!xmlStrEqual(parent->name, BAD_CAST "transform")))) {
+       if (err) {
+           xsltTransformError(NULL, style, inst,
+                   "element %s only allowed as child of stylesheet\n",
+                              inst->name);
+           style->errors++;
+       }
+       return(0);
+    }
+    return(1);
+}
+
+/**
+ * xsltCheckInstructionElement:
+ * @style: the XSLT stylesheet
+ * @inst: the XSLT instruction
+ *
+ * Check that the instruction is instanciated as an instruction element.
+ */
+static void
+xsltCheckInstructionElement(xsltStylesheetPtr style, xmlNodePtr inst) {
+    xmlNodePtr parent;
+    int has_ext;
+
+    if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) ||
+        (style->literal_result))
+        return;
+
+    has_ext = (style->extInfos != NULL);
+    
+    parent = inst->parent;
+    if (parent == NULL) {
+       xsltTransformError(NULL, style, inst,
+               "internal problem: element has no parent\n");
+       style->errors++;
+       return;
+    }
+    while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) {
+        if (((parent->ns == inst->ns) ||
+            ((parent->ns != NULL) &&
+             (xmlStrEqual(parent->ns->href, inst->ns->href)))) &&
+           ((xmlStrEqual(parent->name, BAD_CAST "template")) ||
+            (xmlStrEqual(parent->name, BAD_CAST "param")) ||
+            (xmlStrEqual(parent->name, BAD_CAST "attribute")) ||
+            (xmlStrEqual(parent->name, BAD_CAST "variable")))) {
+           return;
+       }
+
+       /*
+        * if we are within an extension element all bets are off
+        * about the semantic there e.g. xsl:param within func:function
+        */
+       if ((has_ext) && (parent->ns != NULL) &&
+           (xmlHashLookup(style->extInfos, parent->ns->href) != NULL))
+           return;
+       
+        parent = parent->parent;
+    }
+    xsltTransformError(NULL, style, inst,
+           "element %s only allowed within a template, variable or param\n",
+                          inst->name);
+    style->errors++;
+}
+
+/**
+ * xsltCheckParentElement:
+ * @style: the XSLT stylesheet
+ * @inst: the XSLT instruction
+ * @allow1: allowed parent1
+ * @allow2: allowed parent2
+ *
+ * Check that the instruction is instanciated as the childre of one of the
+ * possible parents.
+ */
+static void
+xsltCheckParentElement(xsltStylesheetPtr style, xmlNodePtr inst,
+                       const xmlChar *allow1, const xmlChar *allow2) {
+    xmlNodePtr parent;
+
+    if ((style == NULL) || (inst == NULL) || (inst->ns == NULL) ||
+        (style->literal_result))
+        return;
+
+    parent = inst->parent;
+    if (parent == NULL) {
+       xsltTransformError(NULL, style, inst,
+               "internal problem: element has no parent\n");
+       style->errors++;
+       return;
+    }
+    if (((parent->ns == inst->ns) ||
+        ((parent->ns != NULL) &&
+         (xmlStrEqual(parent->ns->href, inst->ns->href)))) &&
+       ((xmlStrEqual(parent->name, allow1)) ||
+        (xmlStrEqual(parent->name, allow2)))) {
+       return;
+    }
+
+    if (style->extInfos != NULL) {
+       while ((parent != NULL) && (parent->type != XML_DOCUMENT_NODE)) {
+           /*
+            * if we are within an extension element all bets are off
+            * about the semantic there e.g. xsl:param within func:function
+            */
+           if ((parent->ns != NULL) &&
+               (xmlHashLookup(style->extInfos, parent->ns->href) != NULL))
+               return;
+           
+           parent = parent->parent;
+       }
+    }
+    xsltTransformError(NULL, style, inst,
+                      "element %s is not allowed within that context\n",
+                      inst->name);
+    style->errors++;
+}
+#endif
+
+/************************************************************************
+ *                                                                     *
+ *                     handling of precomputed data                    *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltNewStylePreComp:
+ * @style:  the XSLT stylesheet
+ * @type:  the construct type
+ *
+ * Create a new XSLT Style precomputed block
+ *
+ * Returns the newly allocated specialized structure
+ *         or NULL in case of error
+ */
+static xsltStylePreCompPtr
+xsltNewStylePreComp(xsltStylesheetPtr style, xsltStyleType type) {
+    xsltStylePreCompPtr cur;
+#ifdef XSLT_REFACTORED
+    size_t size;
+#endif
+
+    if (style == NULL)
+        return(NULL);
+   
+#ifdef XSLT_REFACTORED
+    /*
+    * URGENT TODO: Use specialized factory functions in order
+    *   to avoid this ugliness.
+    */
+    switch (type) {
+        case XSLT_FUNC_COPY:
+            size = sizeof(xsltStyleItemCopy); break;
+        case XSLT_FUNC_SORT:
+            size = sizeof(xsltStyleItemSort); break;
+        case XSLT_FUNC_TEXT:
+            size = sizeof(xsltStyleItemText); break;
+        case XSLT_FUNC_ELEMENT:
+            size = sizeof(xsltStyleItemElement); break;
+        case XSLT_FUNC_ATTRIBUTE:
+            size = sizeof(xsltStyleItemAttribute); break;
+        case XSLT_FUNC_COMMENT:
+            size = sizeof(xsltStyleItemComment); break;
+        case XSLT_FUNC_PI:
+            size = sizeof(xsltStyleItemPI); break;
+        case XSLT_FUNC_COPYOF:
+            size = sizeof(xsltStyleItemCopyOf); break;
+        case XSLT_FUNC_VALUEOF:
+            size = sizeof(xsltStyleItemValueOf); break;;
+        case XSLT_FUNC_NUMBER:
+            size = sizeof(xsltStyleItemNumber); break;
+        case XSLT_FUNC_APPLYIMPORTS:
+            size = sizeof(xsltStyleItemApplyImports); break;
+        case XSLT_FUNC_CALLTEMPLATE:
+            size = sizeof(xsltStyleItemCallTemplate); break;
+        case XSLT_FUNC_APPLYTEMPLATES:
+            size = sizeof(xsltStyleItemApplyTemplates); break;
+        case XSLT_FUNC_CHOOSE:
+            size = sizeof(xsltStyleItemChoose); break;
+        case XSLT_FUNC_IF:
+            size = sizeof(xsltStyleItemIf); break;
+        case XSLT_FUNC_FOREACH:
+            size = sizeof(xsltStyleItemForEach); break;
+        case XSLT_FUNC_DOCUMENT:
+            size = sizeof(xsltStyleItemDocument); break;
+       case XSLT_FUNC_WITHPARAM:
+           size = sizeof(xsltStyleItemWithParam); break;
+       case XSLT_FUNC_PARAM:
+           size = sizeof(xsltStyleItemParam); break;
+       case XSLT_FUNC_VARIABLE:
+           size = sizeof(xsltStyleItemVariable); break;
+       case XSLT_FUNC_WHEN:
+           size = sizeof(xsltStyleItemWhen); break;
+       case XSLT_FUNC_OTHERWISE:
+           size = sizeof(xsltStyleItemOtherwise); break;
+       default:        
+           xsltTransformError(NULL, style, NULL,
+                   "xsltNewStylePreComp : invalid type %d\n", type);
+           style->errors++;
+           return(NULL);
+    }
+    /*
+    * Create the structure.
+    */
+    cur = (xsltStylePreCompPtr) xmlMalloc(size);
+    if (cur == NULL) {
+       xsltTransformError(NULL, style, NULL,
+               "xsltNewStylePreComp : malloc failed\n");
+       style->errors++;
+       return(NULL);
+    }
+    memset(cur, 0, size);
+
+#else /* XSLT_REFACTORED */
+    /*
+    * Old behaviour.
+    */
+    cur = (xsltStylePreCompPtr) xmlMalloc(sizeof(xsltStylePreComp));
+    if (cur == NULL) {
+       xsltTransformError(NULL, style, NULL,
+               "xsltNewStylePreComp : malloc failed\n");
+       style->errors++;
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltStylePreComp));
+#endif /* XSLT_REFACTORED */
+
+    /*
+    * URGENT TODO: Better to move this to spezialized factory functions.
+    */
+    cur->type = type;
+    switch (cur->type) {
+        case XSLT_FUNC_COPY:
+            cur->func = (xsltTransformFunction) xsltCopy;break;
+        case XSLT_FUNC_SORT:
+            cur->func = (xsltTransformFunction) xsltSort;break;
+        case XSLT_FUNC_TEXT:
+            cur->func = (xsltTransformFunction) xsltText;break;
+        case XSLT_FUNC_ELEMENT:
+            cur->func = (xsltTransformFunction) xsltElement;break;
+        case XSLT_FUNC_ATTRIBUTE:
+            cur->func = (xsltTransformFunction) xsltAttribute;break;
+        case XSLT_FUNC_COMMENT:
+            cur->func = (xsltTransformFunction) xsltComment;break;
+        case XSLT_FUNC_PI:
+            cur->func = (xsltTransformFunction) xsltProcessingInstruction;
+           break;
+        case XSLT_FUNC_COPYOF:
+            cur->func = (xsltTransformFunction) xsltCopyOf;break;
+        case XSLT_FUNC_VALUEOF:
+            cur->func = (xsltTransformFunction) xsltValueOf;break;
+        case XSLT_FUNC_NUMBER:
+            cur->func = (xsltTransformFunction) xsltNumber;break;
+        case XSLT_FUNC_APPLYIMPORTS:
+            cur->func = (xsltTransformFunction) xsltApplyImports;break;
+        case XSLT_FUNC_CALLTEMPLATE:
+            cur->func = (xsltTransformFunction) xsltCallTemplate;break;
+        case XSLT_FUNC_APPLYTEMPLATES:
+            cur->func = (xsltTransformFunction) xsltApplyTemplates;break;
+        case XSLT_FUNC_CHOOSE:
+            cur->func = (xsltTransformFunction) xsltChoose;break;
+        case XSLT_FUNC_IF:
+            cur->func = (xsltTransformFunction) xsltIf;break;
+        case XSLT_FUNC_FOREACH:
+            cur->func = (xsltTransformFunction) xsltForEach;break;
+        case XSLT_FUNC_DOCUMENT:
+            cur->func = (xsltTransformFunction) xsltDocumentElem;break;
+       case XSLT_FUNC_WITHPARAM:
+       case XSLT_FUNC_PARAM:       
+       case XSLT_FUNC_VARIABLE:            
+       case XSLT_FUNC_WHEN:
+           break;
+       default:
+       if (cur->func == NULL) {
+           xsltTransformError(NULL, style, NULL,
+                   "xsltNewStylePreComp : no function for type %d\n", type);
+           style->errors++;
+       }
+    }
+    cur->next = style->preComps;
+    style->preComps = (xsltElemPreCompPtr) cur;
+
+    return(cur);
+}
+
+/**
+ * xsltFreeStylePreComp:
+ * @comp:  an XSLT Style precomputed block
+ *
+ * Free up the memory allocated by @comp
+ */
+static void
+xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
+    if (comp == NULL)
+       return;
+#ifdef XSLT_REFACTORED
+    /*
+    * URGENT TODO: Implement destructors.
+    */
+    switch (comp->type) {
+       case XSLT_FUNC_LITERAL_RESULT_ELEMENT:
+           break;
+       case XSLT_FUNC_COPY:
+            break;
+        case XSLT_FUNC_SORT: {
+               xsltStyleItemSortPtr item = (xsltStyleItemSortPtr) comp;
+               if (item->comp != NULL)
+                   xmlXPathFreeCompExpr(item->comp);
+           }
+            break;
+        case XSLT_FUNC_TEXT:
+            break;
+        case XSLT_FUNC_ELEMENT:
+            break;
+        case XSLT_FUNC_ATTRIBUTE:
+            break;
+        case XSLT_FUNC_COMMENT:
+            break;
+        case XSLT_FUNC_PI:
+           break;
+        case XSLT_FUNC_COPYOF: {
+               xsltStyleItemCopyOfPtr item = (xsltStyleItemCopyOfPtr) comp;
+               if (item->comp != NULL)
+                   xmlXPathFreeCompExpr(item->comp);
+           }
+            break;
+        case XSLT_FUNC_VALUEOF: {
+               xsltStyleItemValueOfPtr item = (xsltStyleItemValueOfPtr) comp;
+               if (item->comp != NULL)
+                   xmlXPathFreeCompExpr(item->comp);
+           }
+            break;
+        case XSLT_FUNC_NUMBER:
+            break;
+        case XSLT_FUNC_APPLYIMPORTS:
+            break;
+        case XSLT_FUNC_CALLTEMPLATE:
+            break;
+        case XSLT_FUNC_APPLYTEMPLATES: {
+               xsltStyleItemApplyTemplatesPtr item =
+                   (xsltStyleItemApplyTemplatesPtr) comp;
+               if (item->comp != NULL)
+                   xmlXPathFreeCompExpr(item->comp);
+           }
+            break;
+        case XSLT_FUNC_CHOOSE:
+            break;
+        case XSLT_FUNC_IF: {
+               xsltStyleItemIfPtr item = (xsltStyleItemIfPtr) comp;
+               if (item->comp != NULL)
+                   xmlXPathFreeCompExpr(item->comp);
+           }
+            break;
+        case XSLT_FUNC_FOREACH: {
+               xsltStyleItemForEachPtr item =
+                   (xsltStyleItemForEachPtr) comp;
+               if (item->comp != NULL)
+                   xmlXPathFreeCompExpr(item->comp);
+           }
+            break;
+        case XSLT_FUNC_DOCUMENT:
+            break;
+       case XSLT_FUNC_WITHPARAM: {
+               xsltStyleItemWithParamPtr item =
+                   (xsltStyleItemWithParamPtr) comp;
+               if (item->comp != NULL)
+                   xmlXPathFreeCompExpr(item->comp);
+           }
+           break;
+       case XSLT_FUNC_PARAM: {
+               xsltStyleItemParamPtr item =
+                   (xsltStyleItemParamPtr) comp;
+               if (item->comp != NULL)
+                   xmlXPathFreeCompExpr(item->comp);
+           }
+           break;
+       case XSLT_FUNC_VARIABLE: {
+               xsltStyleItemVariablePtr item =
+                   (xsltStyleItemVariablePtr) comp;
+               if (item->comp != NULL)
+                   xmlXPathFreeCompExpr(item->comp);
+           }
+           break;
+       case XSLT_FUNC_WHEN: {
+               xsltStyleItemWhenPtr item =
+                   (xsltStyleItemWhenPtr) comp;
+               if (item->comp != NULL)
+                   xmlXPathFreeCompExpr(item->comp);
+           }
+           break;
+       case XSLT_FUNC_OTHERWISE:           
+       case XSLT_FUNC_FALLBACK:
+       case XSLT_FUNC_MESSAGE:
+       case XSLT_FUNC_INCLUDE:
+       case XSLT_FUNC_ATTRSET:
+       
+           break;
+       default:
+           /* TODO: Raise error. */
+           break;
+    }
+#else    
+    if (comp->comp != NULL)
+       xmlXPathFreeCompExpr(comp->comp);
+    if (comp->nsList != NULL)
+       xmlFree(comp->nsList);
+#endif
+
+    xmlFree(comp);
+}
+
+
+/************************************************************************
+ *                                                                     *
+ *                 XSLT-1.1 extensions                                 *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltDocumentComp:
+ * @style:  the XSLT stylesheet
+ * @inst:  the instruction in the stylesheet
+ * @function:  unused
+ *
+ * Pre process an XSLT-1.1 document element
+ *
+ * Returns a precompiled data structure for the element
+ */
+xsltElemPreCompPtr
+xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst,
+                xsltTransformFunction function ATTRIBUTE_UNUSED) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemDocumentPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    const xmlChar *filename = NULL;
+
+    /*
+    * As of 2006-03-30, this function is currently defined in Libxslt
+    * to be used for:
+    * (in libxslt/extra.c)
+    * "output" in XSLT_SAXON_NAMESPACE
+    * "write" XSLT_XALAN_NAMESPACE
+    * "document" XSLT_XT_NAMESPACE
+    * "document" XSLT_NAMESPACE (from the abandoned old working
+    *                            draft of XSLT 1.1)
+    * (in libexslt/common.c)
+    * "document" in EXSLT_COMMON_NAMESPACE
+    */
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemDocumentPtr)
+       xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_DOCUMENT);
+#endif
+    
+    if (comp == NULL)
+       return (NULL);
+    comp->inst = inst;
+    comp->ver11 = 0;
+
+    if (xmlStrEqual(inst->name, (const xmlChar *) "output")) {
+#ifdef WITH_XSLT_DEBUG_EXTRA
+       xsltGenericDebug(xsltGenericDebugContext,
+           "Found saxon:output extension\n");
+#endif
+       /*
+       * The element "output" is in the namespace XSLT_SAXON_NAMESPACE
+       *   (http://icl.com/saxon)
+       * The @file is in no namespace; it is an AVT.
+       *   (http://www.computerwizards.com/saxon/doc/extensions.html#saxon:output)
+       *
+       * TODO: Do we need not to check the namespace here?
+       */
+       filename = xsltEvalStaticAttrValueTemplate(style, inst,
+                        (const xmlChar *)"file",
+                        NULL, &comp->has_filename);
+    } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) {
+#ifdef WITH_XSLT_DEBUG_EXTRA
+       xsltGenericDebug(xsltGenericDebugContext,
+           "Found xalan:write extension\n");
+#endif
+       /* the filename need to be interpreted */
+       /*
+       * TODO: Is "filename need to be interpreted" meant to be a todo?
+       *   Where will be the filename of xalan:write be processed?
+       *
+       * TODO: Do we need not to check the namespace here?
+       *   The extension ns is "http://xml.apache.org/xalan/redirect".
+       *   See http://xml.apache.org/xalan-j/extensionslib.html.
+       */
+    } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) {
+       if (inst->ns != NULL) {
+           if (xmlStrEqual(inst->ns->href, XSLT_NAMESPACE)) {
+               /*
+               * Mark the instruction as being of
+               * XSLT version 1.1 (abandoned).
+               */
+               comp->ver11 = 1;
+#ifdef WITH_XSLT_DEBUG_EXTRA
+               xsltGenericDebug(xsltGenericDebugContext,
+                   "Found xslt11:document construct\n");
+#endif                 
+           } else {            
+               if (xmlStrEqual(inst->ns->href,
+                   (const xmlChar *)"http://exslt.org/common")) {
+                   /* EXSLT. */
+#ifdef WITH_XSLT_DEBUG_EXTRA
+                   xsltGenericDebug(xsltGenericDebugContext,
+                       "Found exslt:document extension\n");
+#endif
+               } else if (xmlStrEqual(inst->ns->href, XSLT_XT_NAMESPACE)) {
+                   /* James Clark's XT. */
+#ifdef WITH_XSLT_DEBUG_EXTRA
+                   xsltGenericDebug(xsltGenericDebugContext,
+                       "Found xt:document extension\n");
+#endif
+               }
+           }
+       }
+       /*
+       * The element "document" is used in conjunction with the
+       * following namespaces:
+       *
+       * 1) XSLT_NAMESPACE (http://www.w3.org/1999/XSL/Transform version 1.1)
+       *    <!ELEMENT xsl:document %template;>
+       *    <!ATTLIST xsl:document
+       *       href %avt; #REQUIRED
+       *    @href is an AVT
+       *    IMPORTANT: xsl:document was in the abandoned XSLT 1.1 draft,
+       *    it was removed and isn't available in XSLT 1.1 anymore.
+       *    In XSLT 2.0 it was renamed to xsl:result-document.
+       *
+       *   All other attributes are identical to the attributes
+       *   on xsl:output
+       *
+       * 2) EXSLT_COMMON_NAMESPACE (http://exslt.org/common)
+       *    <exsl:document
+       *       href = { uri-reference }
+       *    TODO: is @href is an AVT?
+       *
+       * 3) XSLT_XT_NAMESPACE (http://www.jclark.com/xt)
+       *     Example: <xt:document method="xml" href="myFile.xml">
+       *    TODO: is @href is an AVT?
+       *               
+       * In all cases @href is in no namespace.
+       */
+       filename = xsltEvalStaticAttrValueTemplate(style, inst,
+           (const xmlChar *)"href", NULL, &comp->has_filename);
+    }          
+    if (!comp->has_filename) {
+       goto error;
+    }
+    comp->filename = filename;
+
+error:
+    return ((xsltElemPreCompPtr) comp);
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Most of the XSLT-1.0 transformations                    *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltSortComp:
+ * @style:  the XSLT stylesheet
+ * @inst:  the xslt sort node
+ *
+ * Process the xslt sort node on the source node
+ */
+static void
+xsltSortComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemSortPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemSortPtr) xsltNewStylePreComp(style, XSLT_FUNC_SORT);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_SORT);
+#endif
+    
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    comp->stype = xsltEvalStaticAttrValueTemplate(style, inst,
+                        (const xmlChar *)"data-type",
+                        NULL, &comp->has_stype);
+    if (comp->stype != NULL) {
+       if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
+           comp->number = 0;
+       else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
+           comp->number = 1;
+       else {
+           xsltTransformError(NULL, style, inst,
+                "xsltSortComp: no support for data-type = %s\n", comp->stype);
+           comp->number = 0; /* use default */
+           if (style != NULL) style->warnings++;
+       }
+    }
+    comp->order = xsltEvalStaticAttrValueTemplate(style, inst,
+                             (const xmlChar *)"order",
+                             NULL, &comp->has_order);
+    if (comp->order != NULL) {
+       if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
+           comp->descending = 0;
+       else if (xmlStrEqual(comp->order, (const xmlChar *) "descending"))
+           comp->descending = 1;
+       else {
+           xsltTransformError(NULL, style, inst,
+                "xsltSortComp: invalid value %s for order\n", comp->order);
+           comp->descending = 0; /* use default */
+           if (style != NULL) style->warnings++;
+       }
+    }
+    comp->case_order = xsltEvalStaticAttrValueTemplate(style, inst,
+                             (const xmlChar *)"case-order",
+                             NULL, &comp->has_use);
+    if (comp->case_order != NULL) {
+       if (xmlStrEqual(comp->case_order, (const xmlChar *) "upper-first"))
+           comp->lower_first = 0;
+       else if (xmlStrEqual(comp->case_order, (const xmlChar *) "lower-first"))
+           comp->lower_first = 1;
+       else {
+           xsltTransformError(NULL, style, inst,
+                "xsltSortComp: invalid value %s for order\n", comp->order);
+           comp->lower_first = 0; /* use default */
+           if (style != NULL) style->warnings++;
+       }
+    }
+
+    comp->lang = xsltEvalStaticAttrValueTemplate(style, inst,
+                                (const xmlChar *)"lang",
+                                NULL, &comp->has_lang);
+
+    comp->select = xsltGetCNsProp(style, inst,(const xmlChar *)"select", XSLT_NAMESPACE);
+    if (comp->select == NULL) {
+       /*
+        * The default value of the select attribute is ., which will
+        * cause the string-value of the current node to be used as
+        * the sort key.
+        */
+       comp->select = xmlDictLookup(style->dict, BAD_CAST ".", 1);
+    }
+    comp->comp = xsltXPathCompile(style, comp->select);
+    if (comp->comp == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "xsltSortComp: could not compile select expression '%s'\n",
+                        comp->select);
+       if (style != NULL) style->errors++;
+    }
+    if (inst->children != NULL) {
+       xsltTransformError(NULL, style, inst,
+       "xsl:sort : is not empty\n");
+       if (style != NULL) style->errors++;
+    }
+}
+
+/**
+ * xsltCopyComp:
+ * @style:  the XSLT stylesheet
+ * @inst:  the xslt copy node
+ *
+ * Process the xslt copy node on the source node
+ */
+static void
+xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemCopyPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemCopyPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPY);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_COPY);
+#endif
+    
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+
+    comp->use = xsltGetCNsProp(style, inst, (const xmlChar *)"use-attribute-sets",
+                                   XSLT_NAMESPACE);
+    if (comp->use == NULL)
+       comp->has_use = 0;
+    else
+       comp->has_use = 1;
+}
+
+#ifdef XSLT_REFACTORED
+    /* Enable if ever needed for xsl:text. */
+#else
+/**
+ * xsltTextComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt text node
+ *
+ * TODO: This function is obsolete, since xsl:text won't
+ *  be compiled, but removed from the tree.
+ *
+ * Process the xslt text node on the source node
+ */
+static void
+xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemTextPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    const xmlChar *prop;
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemTextPtr) xsltNewStylePreComp(style, XSLT_FUNC_TEXT);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_TEXT);
+#endif    
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+    comp->noescape = 0;
+
+    prop = xsltGetCNsProp(style, inst,
+           (const xmlChar *)"disable-output-escaping",
+                       XSLT_NAMESPACE);
+    if (prop != NULL) {
+       if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
+           comp->noescape = 1;
+       } else if (!xmlStrEqual(prop,
+           (const xmlChar *)"no")){
+           xsltTransformError(NULL, style, inst,
+               "xsl:text: disable-output-escaping allows only yes or no\n");
+           if (style != NULL) style->warnings++;
+       }
+    }
+}
+#endif /* else of XSLT_REFACTORED */
+
+/**
+ * xsltElementComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt element node
+ *
+ * Process the xslt element node on the source node
+ */
+static void
+xsltElementComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemElementPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    /*
+    * <xsl:element
+    *   name = { qname }
+    *   namespace = { uri-reference }
+    *   use-attribute-sets = qnames>
+    *   <!-- Content: template -->
+    * </xsl:element>
+    */
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemElementPtr) xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_ELEMENT);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    /*
+    * Attribute "name".
+    */
+    /*
+    * TODO: Precompile the AVT. See bug #344894.
+    */
+    comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
+       (const xmlChar *)"name", NULL, &comp->has_name);
+    if (! comp->has_name) {
+       xsltTransformError(NULL, style, inst,
+           "xsl:element: The attribute 'name' is missing.\n");
+       style->errors++;
+       goto error;
+    }
+    /*
+    * Attribute "namespace".
+    */
+    /*
+    * TODO: Precompile the AVT. See bug #344894.
+    */
+    comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
+       (const xmlChar *)"namespace", NULL, &comp->has_ns);
+    
+    if (comp->name != NULL) {  
+       if (xmlValidateQName(comp->name, 0)) {
+           xsltTransformError(NULL, style, inst,
+               "xsl:element: The value '%s' of the attribute 'name' is "
+               "not a valid QName.\n", comp->name);
+           style->errors++;
+       } else {
+           const xmlChar *prefix = NULL, *name;
+
+           name = xsltSplitQName(style->dict, comp->name, &prefix);
+           if (comp->has_ns == 0) {        
+               xmlNsPtr ns;
+
+               /*
+               * SPEC XSLT 1.0:
+               *  "If the namespace attribute is not present, then the QName is
+               *  expanded into an expanded-name using the namespace declarations
+               *  in effect for the xsl:element element, including any default
+               *  namespace declaration.
+               */              
+               ns = xmlSearchNs(inst->doc, inst, prefix);
+               if (ns != NULL) {
+                   comp->ns = xmlDictLookup(style->dict, ns->href, -1);
+                   comp->has_ns = 1;
+#ifdef XSLT_REFACTORED
+                   comp->nsPrefix = prefix;
+                   comp->name = name;
+#endif
+               } else if (prefix != NULL) {
+                   xsltTransformError(NULL, style, inst,
+                       "xsl:element: The prefixed QName '%s' "
+                       "has no namespace binding in scope in the "
+                       "stylesheet; this is an error, since the namespace was "
+                       "not specified by the instruction itself.\n", comp->name);
+                   style->errors++;
+               }
+           }       
+           if ((prefix != NULL) &&
+               (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)))
+           {
+               /*
+               * Mark is to be skipped.
+               */
+               comp->has_name = 0;             
+           }
+       }
+    }    
+    /*
+    * Attribute "use-attribute-sets",
+    */
+    comp->use = xsltEvalStaticAttrValueTemplate(style, inst,
+                      (const xmlChar *)"use-attribute-sets",
+                      NULL, &comp->has_use);
+
+error:    
+    return;
+}
+
+/**
+ * xsltAttributeComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt attribute node
+ *
+ * Process the xslt attribute node on the source node
+ */
+static void
+xsltAttributeComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemAttributePtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    /*
+    * <xsl:attribute
+    *   name = { qname }
+    *   namespace = { uri-reference }>
+    *   <!-- Content: template -->
+    * </xsl:attribute>
+    */
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemAttributePtr) xsltNewStylePreComp(style,
+       XSLT_FUNC_ATTRIBUTE);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_ATTRIBUTE);
+#endif
+    
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    /*
+    * Attribute "name".
+    */
+    /*
+    * TODO: Precompile the AVT. See bug #344894.
+    */
+    comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
+                                (const xmlChar *)"name",
+                                NULL, &comp->has_name);
+    if (! comp->has_name) {
+       xsltTransformError(NULL, style, inst,
+           "XSLT-attribute: The attribute 'name' is missing.\n");
+       style->errors++;
+       return;
+    }    
+    /*
+    * Attribute "namespace".
+    */
+    /*
+    * TODO: Precompile the AVT. See bug #344894.
+    */
+    comp->ns = xsltEvalStaticAttrValueTemplate(style, inst,
+       (const xmlChar *)"namespace",
+       NULL, &comp->has_ns);
+
+    if (comp->name != NULL) {
+       if (xmlValidateQName(comp->name, 0)) {
+           xsltTransformError(NULL, style, inst,
+               "xsl:attribute: The value '%s' of the attribute 'name' is "
+               "not a valid QName.\n", comp->name);
+           style->errors++;
+       } else {
+           const xmlChar *prefix = NULL, *name;
+
+           name = xsltSplitQName(style->dict, comp->name, &prefix);
+           if (prefix != NULL) {
+               if (comp->has_ns == 0) {
+                   xmlNsPtr ns;
+
+                   /*
+                   * SPEC XSLT 1.0:
+                   *  "If the namespace attribute is not present, then the
+                   *  QName is expanded into an expanded-name using the
+                   *  namespace declarations in effect for the xsl:element
+                   *  element, including any default namespace declaration.
+                   */              
+                   ns = xmlSearchNs(inst->doc, inst, prefix);
+                   if (ns != NULL) {
+                       comp->ns = xmlDictLookup(style->dict, ns->href, -1);
+                       comp->has_ns = 1;
+#ifdef XSLT_REFACTORED
+                       comp->nsPrefix = prefix;
+                       comp->name = name;
+#endif
+                   } else {
+                       xsltTransformError(NULL, style, inst,
+                           "xsl:attribute: The prefixed QName '%s' "
+                           "has no namespace binding in scope in the "
+                           "stylesheet; this is an error, since the "
+                           "namespace was not specified by the instruction "
+                           "itself.\n", comp->name);
+                       style->errors++;
+                   }
+               }
+               if (!xmlStrncasecmp(prefix, (xmlChar *) "xmlns", 5)) {
+                   /*
+                   * SPEC XSLT 1.0:
+                   *  "It is an error if the string that results from
+                   *  instantiating the attribute value template is not a
+                   *  QName or is the string xmlns. An XSLT processor may
+                   *  signal the error; if it does not signal the error,
+                   *  it must recover by not adding the attribute to the
+                   *  result tree."
+                   *
+                   * Reject a prefix of "xmlns". Mark to be skipped.
+                   */
+                   comp->has_name = 0;
+                   
+#ifdef WITH_XSLT_DEBUG_PARSING
+                   xsltGenericDebug(xsltGenericDebugContext,
+                       "xsltAttribute: xmlns prefix forbidden\n");
+#endif             
+                   return;
+               }
+               
+           }
+       }       
+    }
+}
+
+/**
+ * xsltCommentComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt comment node
+ *
+ * Process the xslt comment node on the source node
+ */
+static void
+xsltCommentComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemCommentPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemCommentPtr) xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_COMMENT);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+}
+
+/**
+ * xsltProcessingInstructionComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt processing-instruction node
+ *
+ * Process the xslt processing-instruction node on the source node
+ */
+static void
+xsltProcessingInstructionComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemPIPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemPIPtr) xsltNewStylePreComp(style, XSLT_FUNC_PI);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_PI);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    comp->name = xsltEvalStaticAttrValueTemplate(style, inst,
+                                (const xmlChar *)"name",
+                                XSLT_NAMESPACE, &comp->has_name);
+}
+
+/**
+ * xsltCopyOfComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt copy-of node
+ *
+ * Process the xslt copy-of node on the source node
+ */
+static void
+xsltCopyOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemCopyOfPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemCopyOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_COPYOF);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
+                               XSLT_NAMESPACE);
+    if (comp->select == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "xsl:copy-of : select is missing\n");
+       if (style != NULL) style->errors++;
+       return;
+    }
+    comp->comp = xsltXPathCompile(style, comp->select);
+    if (comp->comp == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "xsl:copy-of : could not compile select expression '%s'\n",
+                        comp->select);
+       if (style != NULL) style->errors++;
+    }
+}
+
+/**
+ * xsltValueOfComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt value-of node
+ *
+ * Process the xslt value-of node on the source node
+ */
+static void
+xsltValueOfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemValueOfPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    const xmlChar *prop;
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemValueOfPtr) xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_VALUEOF);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    prop = xsltGetCNsProp(style, inst,
+           (const xmlChar *)"disable-output-escaping",
+                       XSLT_NAMESPACE);
+    if (prop != NULL) {
+       if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
+           comp->noescape = 1;
+       } else if (!xmlStrEqual(prop,
+                               (const xmlChar *)"no")){
+           xsltTransformError(NULL, style, inst,
+"xsl:value-of : disable-output-escaping allows only yes or no\n");
+           if (style != NULL) style->warnings++;
+       }
+    }
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
+                               XSLT_NAMESPACE);
+    if (comp->select == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "xsl:value-of : select is missing\n");
+       if (style != NULL) style->errors++;
+       return;
+    }
+    comp->comp = xsltXPathCompile(style, comp->select);
+    if (comp->comp == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "xsl:value-of : could not compile select expression '%s'\n",
+                        comp->select);
+       if (style != NULL) style->errors++;
+    }
+}
+
+/**
+ * xsltWithParamComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt with-param node
+ *
+ * Process the xslt with-param node on the source node
+ * Allowed parents: xsl:call-template, xsl:apply-templates.
+ * <xsl:with-param
+ *  name = qname
+ *  select = expression>
+ *  <!-- Content: template -->
+ * </xsl:with-param>
+ */
+static void
+xsltWithParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemWithParamPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    const xmlChar *prop;
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemWithParamPtr) xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_WITHPARAM);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    /*
+     * The full namespace resolution can be done statically
+     */
+    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);
+    if (prop == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "xsl:with-param : name is missing\n");
+       if (style != NULL) style->errors++;
+    } else {
+        const xmlChar *URI;
+
+       /*
+       * @prop will be in the string dict afterwards, @URI not.
+       */
+       URI = xsltGetQNameURI2(style, inst, &prop);
+       if (prop == NULL) {
+           if (style != NULL) style->errors++;
+       } else {
+           comp->name = prop;
+           comp->has_name = 1;
+           if (URI != NULL) {
+               /*
+               * Fixes bug #308441: Put the ns-name in the dict
+               * in order to pointer compare names during XPath's
+               * variable lookup.
+               */
+               comp->ns = xmlDictLookup(style->dict, URI, -1);
+               comp->has_ns = 1;
+           } else {
+               comp->has_ns = 0;
+           }
+       }
+    }
+
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
+                               XSLT_NAMESPACE);
+    if (comp->select != NULL) {
+       comp->comp = xsltXPathCompile(style, comp->select);
+       if (comp->comp == NULL) {
+           xsltTransformError(NULL, style, inst,
+                "xsl:param : could not compile select expression '%s'\n",
+                            comp->select);
+           if (style != NULL) style->errors++;
+       }
+       if (inst->children != NULL) {
+           xsltTransformError(NULL, style, inst,
+           "xsl:param : content should be empty since select is present \n");
+           if (style != NULL) style->warnings++;
+       }
+    }
+}
+
+/**
+ * xsltNumberComp:
+ * @style: an XSLT compiled stylesheet
+ * @cur:   the xslt number node
+ *
+ * Process the xslt number node on the source node
+ */
+static void
+xsltNumberComp(xsltStylesheetPtr style, xmlNodePtr cur) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemNumberPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    const xmlChar *prop;
+
+    if ((style == NULL) || (cur == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemNumberPtr) xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_NUMBER);
+#endif
+
+    if (comp == NULL)
+       return;
+    cur->psvi = comp;
+
+    if ((style == NULL) || (cur == NULL))
+       return;
+
+    comp->numdata.doc = cur->doc;
+    comp->numdata.node = cur;
+    comp->numdata.value = xsltGetCNsProp(style, cur, (const xmlChar *)"value",
+                                       XSLT_NAMESPACE);
+    
+    prop = xsltEvalStaticAttrValueTemplate(style, cur,
+                        (const xmlChar *)"format",
+                        XSLT_NAMESPACE, &comp->numdata.has_format);
+    if (comp->numdata.has_format == 0) {
+       comp->numdata.format = xmlDictLookup(style->dict, BAD_CAST "" , 0);
+    } else {
+       comp->numdata.format = prop;
+    }
+
+    comp->numdata.count = xsltGetCNsProp(style, cur, (const xmlChar *)"count",
+                                       XSLT_NAMESPACE);
+    comp->numdata.from = xsltGetCNsProp(style, cur, (const xmlChar *)"from",
+                                       XSLT_NAMESPACE);
+    
+    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"level", XSLT_NAMESPACE);
+    if (prop != NULL) {
+       if (xmlStrEqual(prop, BAD_CAST("single")) ||
+           xmlStrEqual(prop, BAD_CAST("multiple")) ||
+           xmlStrEqual(prop, BAD_CAST("any"))) {
+           comp->numdata.level = prop;
+       } else {
+           xsltTransformError(NULL, style, cur,
+                        "xsl:number : invalid value %s for level\n", prop);
+           if (style != NULL) style->warnings++;
+           xmlFree((void *)(prop));
+       }
+    }
+    
+    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"lang", XSLT_NAMESPACE);
+    if (prop != NULL) {
+       XSLT_TODO; /* xsl:number lang attribute */
+       xmlFree((void *)prop);
+    }
+    
+    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"letter-value", XSLT_NAMESPACE);
+    if (prop != NULL) {
+       if (xmlStrEqual(prop, BAD_CAST("alphabetic"))) {
+           xsltTransformError(NULL, style, cur,
+                "xsl:number : letter-value 'alphabetic' not implemented\n");
+           if (style != NULL) style->warnings++;
+           XSLT_TODO; /* xsl:number letter-value attribute alphabetic */
+       } else if (xmlStrEqual(prop, BAD_CAST("traditional"))) {
+           xsltTransformError(NULL, style, cur,
+                "xsl:number : letter-value 'traditional' not implemented\n");
+           if (style != NULL) style->warnings++;
+           XSLT_TODO; /* xsl:number letter-value attribute traditional */
+       } else {
+           xsltTransformError(NULL, style, cur,
+                    "xsl:number : invalid value %s for letter-value\n", prop);
+           if (style != NULL) style->warnings++;
+       }
+    }
+    
+    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-separator",
+                       XSLT_NAMESPACE);
+    if (prop != NULL) {
+        comp->numdata.groupingCharacterLen = xmlStrlen(prop);
+       comp->numdata.groupingCharacter =
+           xsltGetUTF8Char(prop, &(comp->numdata.groupingCharacterLen));
+    }
+    
+    prop = xsltGetCNsProp(style, cur, (const xmlChar *)"grouping-size", XSLT_NAMESPACE);
+    if (prop != NULL) {
+       sscanf((char *)prop, "%d", &comp->numdata.digitsPerGroup);
+    } else {
+       comp->numdata.groupingCharacter = 0;
+    }
+
+    /* Set default values */
+    if (comp->numdata.value == NULL) {
+       if (comp->numdata.level == NULL) {
+           comp->numdata.level = xmlDictLookup(style->dict,
+                                               BAD_CAST"single", 6);
+       }
+    }
+    
+}
+
+/**
+ * xsltApplyImportsComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt apply-imports node
+ *
+ * Process the xslt apply-imports node on the source node
+ */
+static void
+xsltApplyImportsComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemApplyImportsPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemApplyImportsPtr) xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYIMPORTS);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+}
+
+/**
+ * xsltCallTemplateComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt call-template node
+ *
+ * Process the xslt call-template node on the source node
+ */
+static void
+xsltCallTemplateComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemCallTemplatePtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    const xmlChar *prop;
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemCallTemplatePtr)
+       xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_CALLTEMPLATE);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    /*
+     * The full template resolution can be done statically
+     */
+    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);
+    if (prop == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "xsl:call-template : name is missing\n");
+       if (style != NULL) style->errors++;
+    } else {
+        const xmlChar *URI;
+
+       URI = xsltGetQNameURI2(style, inst, &prop);
+       if (prop == NULL) {
+           if (style != NULL) style->errors++;
+       } else {
+           comp->name = prop;
+           comp->has_name = 1;
+           if (URI != NULL) {
+               comp->ns = xmlDictLookup(style->dict, URI, -1);
+               comp->has_ns = 1;
+           } else {
+               comp->has_ns = 0;
+           }
+       }
+       comp->templ = NULL;
+    }
+}
+
+/**
+ * xsltApplyTemplatesComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the apply-templates node
+ *
+ * Process the apply-templates node on the source node
+ */
+static void
+xsltApplyTemplatesComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemApplyTemplatesPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    const xmlChar *prop;
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemApplyTemplatesPtr)
+       xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_APPLYTEMPLATES);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    /*
+     * Get mode if any
+     */
+    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"mode", XSLT_NAMESPACE);
+    if (prop != NULL) {
+        const xmlChar *URI;
+
+       URI = xsltGetQNameURI2(style, inst, &prop);
+       if (prop == NULL) {
+           if (style != NULL) style->errors++;
+       } else {
+           comp->mode = xmlDictLookup(style->dict, prop, -1);
+           if (URI != NULL) {
+               comp->modeURI = xmlDictLookup(style->dict, URI, -1);
+           } else {
+               comp->modeURI = NULL;
+           }
+       }
+    }
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
+                               XSLT_NAMESPACE);
+    if (comp->select != NULL) {
+       comp->comp = xsltXPathCompile(style, comp->select);
+       if (comp->comp == NULL) {
+           xsltTransformError(NULL, style, inst,
+     "xsl:apply-templates : could not compile select expression '%s'\n",
+                            comp->select);
+           if (style != NULL) style->errors++;
+       }
+    }
+
+    /* TODO: handle (or skip) the xsl:sort and xsl:with-param */
+}
+
+/**
+ * xsltChooseComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt choose node
+ *
+ * Process the xslt choose node on the source node
+ */
+static void
+xsltChooseComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemChoosePtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemChoosePtr)
+       xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_CHOOSE);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+}
+
+/**
+ * xsltIfComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt if node
+ *
+ * Process the xslt if node on the source node
+ */
+static void
+xsltIfComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemIfPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemIfPtr)
+       xsltNewStylePreComp(style, XSLT_FUNC_IF);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_IF);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
+    if (comp->test == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "xsl:if : test is not defined\n");
+       if (style != NULL) style->errors++;
+       return;
+    }
+    comp->comp = xsltXPathCompile(style, comp->test);
+    if (comp->comp == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "xsl:if : could not compile test expression '%s'\n",
+                        comp->test);
+       if (style != NULL) style->errors++;
+    }
+}
+
+/**
+ * xsltWhenComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt if node
+ *
+ * Process the xslt if node on the source node
+ */
+static void
+xsltWhenComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemWhenPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemWhenPtr)
+       xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_WHEN);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    comp->test = xsltGetCNsProp(style, inst, (const xmlChar *)"test", XSLT_NAMESPACE);
+    if (comp->test == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "xsl:when : test is not defined\n");
+       if (style != NULL) style->errors++;
+       return;
+    }
+    comp->comp = xsltXPathCompile(style, comp->test);
+    if (comp->comp == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "xsl:when : could not compile test expression '%s'\n",
+                        comp->test);
+       if (style != NULL) style->errors++;
+    }
+}
+
+/**
+ * xsltForEachComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt for-each node
+ *
+ * Process the xslt for-each node on the source node
+ */
+static void
+xsltForEachComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemForEachPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemForEachPtr)
+       xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_FOREACH);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
+                               XSLT_NAMESPACE);
+    if (comp->select == NULL) {
+       xsltTransformError(NULL, style, inst,
+               "xsl:for-each : select is missing\n");
+       if (style != NULL) style->errors++;
+    } else {
+       comp->comp = xsltXPathCompile(style, comp->select);
+       if (comp->comp == NULL) {
+           xsltTransformError(NULL, style, inst,
+     "xsl:for-each : could not compile select expression '%s'\n",
+                            comp->select);
+           if (style != NULL) style->errors++;
+       }
+    }
+    /* TODO: handle and skip the xsl:sort */
+}
+
+/**
+ * xsltVariableComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt variable node
+ *
+ * Process the xslt variable node on the source node
+ */
+static void
+xsltVariableComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemVariablePtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    const xmlChar *prop;
+    const xmlChar *URI;
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemVariablePtr)
+       xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_VARIABLE);
+#endif
+
+    if (comp == NULL)
+       return;
+
+    inst->psvi = comp;
+    comp->inst = inst;
+    /*
+     * The full template resolution can be done statically
+     */
+
+    /*
+    * Attribute "name".
+    */
+    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);
+    if (prop == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "XSLT-variable: The attribute 'name' is missing.\n");
+       style->errors++;
+       goto error;
+    }    
+    if (xmlValidateQName(prop, 0)) {
+       xsltTransformError(NULL, style, inst,
+           "XSLT-variable: The value '%s' of the attribute 'name' is "
+           "not a valid QName.\n", prop);
+       style->errors++;
+       goto error;
+    }
+    URI = xsltGetQNameURI2(style, inst, &prop);
+    if (prop == NULL) {
+       goto error;
+    }
+    comp->name = prop;
+    comp->has_name = 1;
+
+    if (URI != NULL) {
+       comp->ns = xmlDictLookup(style->dict, URI, -1);
+       comp->has_ns = 1;
+    } else {
+       comp->has_ns = 0;
+    }
+    /*
+    * Attribute "select".
+    */
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
+                               XSLT_NAMESPACE);
+    if (comp->select != NULL) {
+       comp->comp = xsltXPathCompile(style, comp->select);
+       if (comp->comp == NULL) {
+           xsltTransformError(NULL, style, inst,
+               "XSLT-variable: Failed to compile the XPath expression '%s'.\n",
+               comp->select);
+           style->errors++;
+       }
+       if (inst->children != NULL) {
+           xsltTransformError(NULL, style, inst,
+               "XSLT-variable: The must be no child nodes, since the "
+               "attribute 'select' was specified.\n");
+           style->errors++;
+       }
+    }
+error:
+    return;
+}
+
+/**
+ * xsltParamComp:
+ * @style: an XSLT compiled stylesheet
+ * @inst:  the xslt param node
+ *
+ * Process the xslt param node on the source node
+ */
+static void
+xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemParamPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    const xmlChar *prop;
+
+    if ((style == NULL) || (inst == NULL))
+       return;
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleItemParamPtr)
+       xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
+#else
+    comp = xsltNewStylePreComp(style, XSLT_FUNC_PARAM);
+#endif
+
+    if (comp == NULL)
+       return;
+    inst->psvi = comp;
+    comp->inst = inst;
+
+    /*
+     * The full template resolution can be done statically
+     */
+    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);
+    if (prop == NULL) {
+       xsltTransformError(NULL, style, inst,
+            "xsl:param : name is missing\n");
+       if (style != NULL) style->errors++;
+    } else {
+        const xmlChar *URI;
+
+       URI = xsltGetQNameURI2(style, inst, &prop);
+       if (prop == NULL) {
+           if (style != NULL) style->errors++;
+       } else {
+           comp->name = prop;
+           comp->has_name = 1;
+           if (URI != NULL) {
+               comp->ns = xmlDictLookup(style->dict, URI, -1);
+               comp->has_ns = 1;
+           } else {
+               comp->has_ns = 0;
+           }
+       }
+    }
+
+    comp->select = xsltGetCNsProp(style, inst, (const xmlChar *)"select",
+                               XSLT_NAMESPACE);
+    if (comp->select != NULL) {
+       comp->comp = xsltXPathCompile(style, comp->select);
+       if (comp->comp == NULL) {
+           xsltTransformError(NULL, style, inst,
+                "xsl:param : could not compile select expression '%s'\n",
+                            comp->select);
+           if (style != NULL) style->errors++;
+       }
+       if (inst->children != NULL) {
+           xsltTransformError(NULL, style, inst,
+       "xsl:param : content should be empty since select is present \n");
+           if (style != NULL) style->warnings++;
+       }
+    }
+}
+
+/************************************************************************
+ *                                                                     *
+ *                 Generic interface                                   *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltFreeStylePreComps:
+ * @style:  an XSLT transformation context
+ *
+ * Free up the memory allocated by all precomputed blocks
+ */
+void
+xsltFreeStylePreComps(xsltStylesheetPtr style) {
+    xsltElemPreCompPtr cur, next;
+
+    if (style == NULL)
+       return;        
+    
+    cur = style->preComps;
+    while (cur != NULL) {
+       next = cur->next;               
+       if (cur->type == XSLT_FUNC_EXTENSION)
+           cur->free(cur);
+       else
+           xsltFreeStylePreComp((xsltStylePreCompPtr) cur);
+       cur = next;
+    }
+}
+
+#ifdef XSLT_REFACTORED
+
+/**
+ * xsltStylePreCompute:
+ * @style:  the XSLT stylesheet
+ * @node:  the element in the XSLT namespace
+ *
+ * Precompute an XSLT element.
+ * This expects the type of the element to be already
+ * set in style->compCtxt->inode->type;
+ */
+void
+xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr node) {
+    /*    
+    * The xsltXSLTElemMarker marker was set beforehand by
+    *  the parsing mechanism for all elements in the XSLT namespace.
+    */
+    if (style == NULL) {
+       if (node != NULL)
+           node->psvi = NULL;
+       return;
+    }
+    if (node == NULL)
+       return;
+    if (! IS_XSLT_ELEM_FAST(node))
+       return;
+
+    node->psvi = NULL;
+    if (XSLT_CCTXT(style)->inode->type != 0) {
+       switch (XSLT_CCTXT(style)->inode->type) {
+           case XSLT_FUNC_APPLYTEMPLATES:
+               xsltApplyTemplatesComp(style, node);
+               break;
+           case XSLT_FUNC_WITHPARAM:                      
+               xsltWithParamComp(style, node);
+               break;
+           case XSLT_FUNC_VALUEOF:         
+               xsltValueOfComp(style, node);
+               break;
+           case XSLT_FUNC_COPY:            
+               xsltCopyComp(style, node);
+               break;
+           case XSLT_FUNC_COPYOF:
+               xsltCopyOfComp(style, node);
+               break;
+           case XSLT_FUNC_IF:      
+               xsltIfComp(style, node);
+               break;
+           case XSLT_FUNC_CHOOSE:          
+               xsltChooseComp(style, node);
+               break;
+           case XSLT_FUNC_WHEN:            
+               xsltWhenComp(style, node);
+               break;
+           case XSLT_FUNC_OTHERWISE:       
+               /* NOP yet */
+               return;
+           case XSLT_FUNC_FOREACH:         
+               xsltForEachComp(style, node);
+               break;
+           case XSLT_FUNC_APPLYIMPORTS:            
+               xsltApplyImportsComp(style, node);
+               break;
+           case XSLT_FUNC_ATTRIBUTE:       
+               xsltAttributeComp(style, node);
+               break;
+           case XSLT_FUNC_ELEMENT:         
+               xsltElementComp(style, node);
+               break;
+           case XSLT_FUNC_SORT:            
+               xsltSortComp(style, node);
+               break;
+           case XSLT_FUNC_COMMENT:         
+               xsltCommentComp(style, node);
+               break;
+           case XSLT_FUNC_NUMBER:          
+               xsltNumberComp(style, node);
+               break;
+           case XSLT_FUNC_PI:      
+               xsltProcessingInstructionComp(style, node);
+               break;
+           case XSLT_FUNC_CALLTEMPLATE:            
+               xsltCallTemplateComp(style, node);
+               break;
+           case XSLT_FUNC_PARAM:           
+               xsltParamComp(style, node);
+               break;
+           case XSLT_FUNC_VARIABLE:        
+               xsltVariableComp(style, node);
+               break;
+           case XSLT_FUNC_FALLBACK:        
+               /* NOP yet */
+               return;
+           case XSLT_FUNC_DOCUMENT:        
+               /* The extra one */
+               node->psvi = (void *) xsltDocumentComp(style, node,
+                   (xsltTransformFunction) xsltDocumentElem);
+               break;
+           case XSLT_FUNC_MESSAGE:
+               /* NOP yet */
+               return;
+           default:
+               /*
+               * NOTE that xsl:text, xsl:template, xsl:stylesheet,
+               *  xsl:transform, xsl:import, xsl:include are not expected
+               *  to be handed over to this function.
+               */
+               xsltTransformError(NULL, style, node,
+                   "Internal error: (xsltStylePreCompute) cannot handle "
+                   "the XSLT element '%s'.\n", node->name);
+               style->errors++;
+               return;
+       }
+    } else {
+       /*
+       * Fallback to string comparison.
+       */      
+       if (IS_XSLT_NAME(node, "apply-templates")) {
+           xsltApplyTemplatesComp(style, node);
+       } else if (IS_XSLT_NAME(node, "with-param")) {
+           xsltWithParamComp(style, node);
+       } else if (IS_XSLT_NAME(node, "value-of")) {
+           xsltValueOfComp(style, node);
+       } else if (IS_XSLT_NAME(node, "copy")) {
+           xsltCopyComp(style, node);
+       } else if (IS_XSLT_NAME(node, "copy-of")) {
+           xsltCopyOfComp(style, node);
+       } else if (IS_XSLT_NAME(node, "if")) {
+           xsltIfComp(style, node);
+       } else if (IS_XSLT_NAME(node, "choose")) {
+           xsltChooseComp(style, node);
+       } else if (IS_XSLT_NAME(node, "when")) {
+           xsltWhenComp(style, node);  
+       } else if (IS_XSLT_NAME(node, "otherwise")) {
+           /* NOP yet */
+           return;
+       } else if (IS_XSLT_NAME(node, "for-each")) {
+           xsltForEachComp(style, node);
+       } else if (IS_XSLT_NAME(node, "apply-imports")) {
+           xsltApplyImportsComp(style, node);
+       } else if (IS_XSLT_NAME(node, "attribute")) {
+           xsltAttributeComp(style, node);
+       } else if (IS_XSLT_NAME(node, "element")) {
+           xsltElementComp(style, node);
+       } else if (IS_XSLT_NAME(node, "sort")) {
+           xsltSortComp(style, node);
+       } else if (IS_XSLT_NAME(node, "comment")) {
+           xsltCommentComp(style, node);
+       } else if (IS_XSLT_NAME(node, "number")) {
+           xsltNumberComp(style, node);
+       } else if (IS_XSLT_NAME(node, "processing-instruction")) {
+           xsltProcessingInstructionComp(style, node);
+       } else if (IS_XSLT_NAME(node, "call-template")) {
+           xsltCallTemplateComp(style, node);
+       } else if (IS_XSLT_NAME(node, "param")) {
+           xsltParamComp(style, node);
+       } else if (IS_XSLT_NAME(node, "variable")) {
+           xsltVariableComp(style, node);
+       } else if (IS_XSLT_NAME(node, "fallback")) {
+           /* NOP yet */
+           return;
+       } else if (IS_XSLT_NAME(node, "document")) {
+           /* The extra one */
+           node->psvi = (void *) xsltDocumentComp(style, node,
+               (xsltTransformFunction) xsltDocumentElem);      
+       } else if (IS_XSLT_NAME(node, "output")) {
+           /* Top-level */
+           return;
+       } else if (IS_XSLT_NAME(node, "preserve-space")) {
+           /* Top-level */
+           return;
+       } else if (IS_XSLT_NAME(node, "strip-space")) {
+           /* Top-level */
+           return;     
+       } else if (IS_XSLT_NAME(node, "key")) {
+           /* Top-level */
+           return;
+       } else if (IS_XSLT_NAME(node, "message")) {
+           return;
+       } else if (IS_XSLT_NAME(node, "attribute-set")) {
+           /* Top-level */
+           return;
+       } else if (IS_XSLT_NAME(node, "namespace-alias")) {
+           /* Top-level */
+           return;
+       } else if (IS_XSLT_NAME(node, "decimal-format")) {
+           /* Top-level */
+           return;
+       } else if (IS_XSLT_NAME(node, "include")) {
+           /* Top-level */                 
+       } else {
+           /*
+           * NOTE that xsl:text, xsl:template, xsl:stylesheet,
+           *  xsl:transform, xsl:import, xsl:include are not expected
+           *  to be handed over to this function.
+           */
+           xsltTransformError(NULL, style, node,
+               "Internal error: (xsltStylePreCompute) cannot handle "
+               "the XSLT element '%s'.\n", node->name);
+               style->errors++;
+           return;
+       }       
+    }
+    /*
+    * Assign the current list of in-scope namespaces to the
+    * item. This is needed for XPath expressions.
+    */
+    if (node->psvi != NULL) {
+       ((xsltStylePreCompPtr) node->psvi)->inScopeNs =
+           XSLT_CCTXT(style)->inode->inScopeNs;
+    }
+}
+
+#else
+
+/**
+ * xsltStylePreCompute:
+ * @style:  the XSLT stylesheet
+ * @inst:  the instruction in the stylesheet
+ *
+ * Precompute an XSLT stylesheet element
+ */
+void
+xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
+    /*
+    * URGENT TODO: Normally inst->psvi Should never be reserved here,
+    *   BUT: since if we include the same stylesheet from
+    *   multiple imports, then the stylesheet will be parsed
+    *   again. We simply must not try to compute the stylesheet again.
+    * TODO: Get to the point where we don't need to query the
+    *   namespace- and local-name of the node, but can evaluate this
+    *   using cctxt->style->inode->category;
+    */
+    if (inst->psvi != NULL)
+       return;
+
+    if (IS_XSLT_ELEM(inst)) {
+       xsltStylePreCompPtr cur;
+
+       if (IS_XSLT_NAME(inst, "apply-templates")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltApplyTemplatesComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "with-param")) {
+           xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
+                                  BAD_CAST "call-template");
+           xsltWithParamComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "value-of")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltValueOfComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "copy")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltCopyComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "copy-of")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltCopyOfComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "if")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltIfComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "when")) {
+           xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
+           xsltWhenComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "choose")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltChooseComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "for-each")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltForEachComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "apply-imports")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltApplyImportsComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "attribute")) {
+           xmlNodePtr parent = inst->parent;
+
+           if ((parent == NULL) || (parent->ns == NULL) ||
+               ((parent->ns != inst->ns) &&
+                (!xmlStrEqual(parent->ns->href, inst->ns->href))) ||
+               (!xmlStrEqual(parent->name, BAD_CAST "attribute-set"))) {
+               xsltCheckInstructionElement(style, inst);
+           }
+           xsltAttributeComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "element")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltElementComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "text")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltTextComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "sort")) {
+           xsltCheckParentElement(style, inst, BAD_CAST "apply-templates",
+                                  BAD_CAST "for-each");
+           xsltSortComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "comment")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltCommentComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "number")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltNumberComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "processing-instruction")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltProcessingInstructionComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "call-template")) {
+           xsltCheckInstructionElement(style, inst);
+           xsltCallTemplateComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "param")) {          
+           if (xsltCheckTopLevelElement(style, inst, 0) == 0)
+               xsltCheckInstructionElement(style, inst);
+           xsltParamComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "variable")) {
+           if (xsltCheckTopLevelElement(style, inst, 0) == 0)
+               xsltCheckInstructionElement(style, inst);
+           xsltVariableComp(style, inst);
+       } else if (IS_XSLT_NAME(inst, "otherwise")) {
+           xsltCheckParentElement(style, inst, BAD_CAST "choose", NULL);
+           xsltCheckInstructionElement(style, inst);
+           return;
+       } else if (IS_XSLT_NAME(inst, "template")) {
+           xsltCheckTopLevelElement(style, inst, 1);
+           return;
+       } else if (IS_XSLT_NAME(inst, "output")) {
+           xsltCheckTopLevelElement(style, inst, 1);
+           return;
+       } else if (IS_XSLT_NAME(inst, "preserve-space")) {
+           xsltCheckTopLevelElement(style, inst, 1);
+           return;
+       } else if (IS_XSLT_NAME(inst, "strip-space")) {
+           xsltCheckTopLevelElement(style, inst, 1);
+           return;
+       } else if ((IS_XSLT_NAME(inst, "stylesheet")) ||
+                  (IS_XSLT_NAME(inst, "transform"))) {
+           xmlNodePtr parent = inst->parent;
+
+           if ((parent == NULL) || (parent->type != XML_DOCUMENT_NODE)) {
+               xsltTransformError(NULL, style, inst,
+                   "element %s only allowed only as root element\n",
+                                  inst->name);
+               style->errors++;
+           }
+           return;
+       } else if (IS_XSLT_NAME(inst, "key")) {
+           xsltCheckTopLevelElement(style, inst, 1);
+           return;
+       } else if (IS_XSLT_NAME(inst, "message")) {
+           xsltCheckInstructionElement(style, inst);
+           return;
+       } else if (IS_XSLT_NAME(inst, "attribute-set")) {
+           xsltCheckTopLevelElement(style, inst, 1);
+           return;
+       } else if (IS_XSLT_NAME(inst, "namespace-alias")) {
+           xsltCheckTopLevelElement(style, inst, 1);
+           return;
+       } else if (IS_XSLT_NAME(inst, "include")) {
+           xsltCheckTopLevelElement(style, inst, 1);
+           return;
+       } else if (IS_XSLT_NAME(inst, "import")) {
+           xsltCheckTopLevelElement(style, inst, 1);
+           return;
+       } else if (IS_XSLT_NAME(inst, "decimal-format")) {
+           xsltCheckTopLevelElement(style, inst, 1);
+           return;
+       } else if (IS_XSLT_NAME(inst, "fallback")) {
+           xsltCheckInstructionElement(style, inst);
+           return;
+       } else if (IS_XSLT_NAME(inst, "document")) {
+           xsltCheckInstructionElement(style, inst);
+           inst->psvi = (void *) xsltDocumentComp(style, inst,
+                               (xsltTransformFunction) xsltDocumentElem);
+       } else {
+           xsltTransformError(NULL, style, inst,
+                "xsltStylePreCompute: unknown xsl:%s\n", inst->name);
+           if (style != NULL) style->warnings++;
+       }
+       
+       cur = (xsltStylePreCompPtr) inst->psvi;
+       /*
+       * A ns-list is build for every XSLT item in the
+       * node-tree. This is needed for XPath expressions.
+       */
+       if (cur != NULL) {
+           int i = 0;
+
+           cur->nsList = xmlGetNsList(inst->doc, inst);
+            if (cur->nsList != NULL) {
+               while (cur->nsList[i] != NULL)
+                   i++;
+           }
+           cur->nsNr = i;
+       }
+    } else {
+       inst->psvi =
+           (void *) xsltPreComputeExtModuleElement(style, inst);
+
+       /*
+        * Unknown element, maybe registered at the context
+        * level. Mark it for later recognition.
+        */
+       if (inst->psvi == NULL)
+           inst->psvi = (void *) xsltExtMarker;
+    }
+}
+#endif /* XSLT_REFACTORED */
index 1d82852..da18210 100644 (file)
-/*\r
- * templates.c: Implementation of the template processing\r
- *\r
- * Reference:\r
- *   http://www.w3.org/TR/1999/REC-xslt-19991116\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * daniel@veillard.com\r
- */\r
-\r
-#define IN_LIBXSLT\r
-#include "libxslt.h"\r
-\r
-#include <string.h>\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/globals.h>\r
-#include <libxml/xmlerror.h>\r
-#include <libxml/tree.h>\r
-#include <libxml/xpathInternals.h>\r
-#include <libxml/parserInternals.h>\r
-#include "xslt.h"\r
-#include "xsltInternals.h"\r
-#include "xsltutils.h"\r
-#include "variables.h"\r
-#include "functions.h"\r
-#include "templates.h"\r
-#include "transform.h"\r
-#include "namespaces.h"\r
-#include "attributes.h"\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
-#define WITH_XSLT_DEBUG_TEMPLATES\r
-#endif\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Module interfaces                               *\r
- *                                                                     *\r
- ************************************************************************/\r
\r
-/**\r
- * xsltEvalXPathPredicate:\r
- * @ctxt:  the XSLT transformation context\r
- * @comp:  the XPath compiled expression\r
- * @nsList:  the namespaces in scope\r
- * @nsNr:  the number of namespaces in scope\r
- *\r
- * Process the expression using XPath and evaluate the result as\r
- * an XPath predicate\r
- *\r
- * Returns 1 is the predicate was true, 0 otherwise\r
- */\r
-int\r
-xsltEvalXPathPredicate(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,\r
-                      xmlNsPtr *nsList, int nsNr) {\r
-    int ret;\r
-    xmlXPathObjectPtr res;\r
-    int oldNsNr;\r
-    xmlNsPtr *oldNamespaces;\r
-    xmlNodePtr oldInst;\r
-    int oldProximityPosition, oldContextSize;\r
-\r
-    oldContextSize = ctxt->xpathCtxt->contextSize;\r
-    oldProximityPosition = ctxt->xpathCtxt->proximityPosition;\r
-    oldNsNr = ctxt->xpathCtxt->nsNr;\r
-    oldNamespaces = ctxt->xpathCtxt->namespaces;\r
-    oldInst = ctxt->inst;\r
-\r
-    ctxt->xpathCtxt->node = ctxt->node;\r
-    ctxt->xpathCtxt->namespaces = nsList;\r
-    ctxt->xpathCtxt->nsNr = nsNr;\r
-\r
-    res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);\r
-\r
-    if (res != NULL) {\r
-       ret = xmlXPathEvalPredicate(ctxt->xpathCtxt, res);\r
-       xmlXPathFreeObject(res);\r
-#ifdef WITH_XSLT_DEBUG_TEMPLATES\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltEvalXPathPredicate: returns %d\n", ret));\r
-#endif\r
-    } else {\r
-#ifdef WITH_XSLT_DEBUG_TEMPLATES\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltEvalXPathPredicate: failed\n"));\r
-#endif\r
-       ctxt->state = XSLT_STATE_STOPPED;\r
-       ret = 0;\r
-    }\r
-    ctxt->xpathCtxt->nsNr = oldNsNr;\r
-\r
-    ctxt->xpathCtxt->namespaces = oldNamespaces;\r
-    ctxt->inst = oldInst;\r
-    ctxt->xpathCtxt->contextSize = oldContextSize;\r
-    ctxt->xpathCtxt->proximityPosition = oldProximityPosition;\r
-\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltEvalXPathStringNs:\r
- * @ctxt:  the XSLT transformation context\r
- * @comp:  the compiled XPath expression\r
- * @nsNr:  the number of namespaces in the list\r
- * @nsList:  the list of in-scope namespaces to use\r
- *\r
- * Process the expression using XPath, allowing to pass a namespace mapping\r
- * context and get a string\r
- *\r
- * Returns the computed string value or NULL, must be deallocated by the\r
- *    caller.\r
- */\r
-xmlChar *\r
-xsltEvalXPathStringNs(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,\r
-                     int nsNr, xmlNsPtr *nsList) {\r
-    xmlChar *ret = NULL;\r
-    xmlXPathObjectPtr res;\r
-    xmlNodePtr oldInst;\r
-    xmlNodePtr oldNode;\r
-    int        oldPos, oldSize;\r
-    int oldNsNr;\r
-    xmlNsPtr *oldNamespaces;\r
-\r
-    oldInst = ctxt->inst;\r
-    oldNode = ctxt->node;\r
-    oldPos = ctxt->xpathCtxt->proximityPosition;\r
-    oldSize = ctxt->xpathCtxt->contextSize;\r
-    oldNsNr = ctxt->xpathCtxt->nsNr;\r
-    oldNamespaces = ctxt->xpathCtxt->namespaces;\r
-\r
-    ctxt->xpathCtxt->node = ctxt->node;\r
-    /* TODO: do we need to propagate the namespaces here ? */\r
-    ctxt->xpathCtxt->namespaces = nsList;\r
-    ctxt->xpathCtxt->nsNr = nsNr;\r
-    res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);\r
-    if (res != NULL) {\r
-       if (res->type != XPATH_STRING)\r
-           res = xmlXPathConvertString(res);\r
-       if (res->type == XPATH_STRING) {\r
-            ret = res->stringval;\r
-           res->stringval = NULL;\r
-       } else {\r
-           xsltTransformError(ctxt, NULL, NULL,\r
-                "xpath : string() function didn't return a String\n");\r
-       }\r
-       xmlXPathFreeObject(res);\r
-    } else {\r
-       ctxt->state = XSLT_STATE_STOPPED;\r
-    }\r
-#ifdef WITH_XSLT_DEBUG_TEMPLATES\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,\r
-        "xsltEvalXPathString: returns %s\n", ret));\r
-#endif\r
-    ctxt->inst = oldInst;\r
-    ctxt->node = oldNode;\r
-    ctxt->xpathCtxt->contextSize = oldSize;\r
-    ctxt->xpathCtxt->proximityPosition = oldPos;\r
-    ctxt->xpathCtxt->nsNr = oldNsNr;\r
-    ctxt->xpathCtxt->namespaces = oldNamespaces;\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltEvalXPathString:\r
- * @ctxt:  the XSLT transformation context\r
- * @comp:  the compiled XPath expression\r
- *\r
- * Process the expression using XPath and get a string\r
- *\r
- * Returns the computed string value or NULL, must be deallocated by the\r
- *    caller.\r
- */\r
-xmlChar *\r
-xsltEvalXPathString(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp) {\r
-    return(xsltEvalXPathStringNs(ctxt, comp, 0, NULL));\r
-}\r
-\r
-/**\r
- * xsltEvalTemplateString:\r
- * @ctxt:  the XSLT transformation context\r
- * @contextNode:  the current node in the source tree\r
- * @inst:  the XSLT instruction (xsl:comment, xsl:processing-instruction)\r
- *\r
- * Processes the sequence constructor of the given instruction on\r
- * @contextNode and converts the resulting tree to a string.\r
- * This is needed by e.g. xsl:comment and xsl:processing-instruction.\r
- *\r
- * Returns the computed string value or NULL; it's up to the caller to\r
- *         free the result.\r
- */\r
-xmlChar *\r
-xsltEvalTemplateString(xsltTransformContextPtr ctxt,\r
-                      xmlNodePtr contextNode,\r
-                      xmlNodePtr inst)\r
-{\r
-    xmlNodePtr oldInsert, insert = NULL;\r
-    xmlChar *ret;\r
-\r
-    if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))\r
-       return(NULL);\r
-\r
-    if (inst->children == NULL)\r
-       return(NULL);\r
-\r
-    /*\r
-    * This creates a temporary element-node to add the resulting\r
-    * text content to.\r
-    * OPTIMIZE TODO: Keep such an element-node in the transformation\r
-    *  context to avoid creating it every time.\r
-    */\r
-    insert = xmlNewDocNode(ctxt->output, NULL,\r
-                          (const xmlChar *)"fake", NULL);\r
-    if (insert == NULL) {\r
-       xsltTransformError(ctxt, NULL, contextNode,\r
-               "Failed to create temporary node\n");\r
-       return(NULL);\r
-    }\r
-    oldInsert = ctxt->insert;\r
-    ctxt->insert = insert;\r
-    /*\r
-    * OPTIMIZE TODO: if inst->children consists only of text-nodes.\r
-    */\r
-    xsltApplyOneTemplate(ctxt, contextNode, inst->children, NULL, NULL);\r
-\r
-    ctxt->insert = oldInsert;\r
-\r
-    ret = xmlNodeGetContent(insert);\r
-    if (insert != NULL)\r
-       xmlFreeNode(insert);\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltAttrTemplateValueProcessNode:\r
- * @ctxt:  the XSLT transformation context\r
- * @str:  the attribute template node value\r
- * @inst:  the instruction (or LRE) in the stylesheet holding the\r
- *         attribute with an AVT\r
- *\r
- * Process the given string, allowing to pass a namespace mapping\r
- * context and return the new string value.\r
- *\r
- * Called by:\r
- *  - xsltAttrTemplateValueProcess() (templates.c)\r
- *  - xsltEvalAttrValueTemplate() (templates.c)\r
- *\r
- * QUESTION: Why is this function public? It is not used outside\r
- *  of templates.c.\r
- *\r
- * Returns the computed string value or NULL, must be deallocated by the\r
- *    caller.\r
- */\r
-xmlChar *\r
-xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt,\r
-         const xmlChar *str, xmlNodePtr inst)\r
-{\r
-    xmlChar *ret = NULL;\r
-    const xmlChar *cur;\r
-    xmlChar *expr, *val;\r
-    xmlNsPtr *nsList = NULL;\r
-    int nsNr = 0;\r
-\r
-    if (str == NULL) return(NULL);\r
-    if (*str == 0)\r
-       return(xmlStrndup((xmlChar *)"", 0));\r
-\r
-    cur = str;\r
-    while (*cur != 0) {\r
-       if (*cur == '{') {\r
-           if (*(cur+1) == '{') {      /* escaped '{' */\r
-               cur++;\r
-               ret = xmlStrncat(ret, str, cur - str);\r
-               cur++;\r
-               str = cur;\r
-               continue;\r
-           }\r
-           ret = xmlStrncat(ret, str, cur - str);\r
-           str = cur;\r
-           cur++;\r
-           while ((*cur != 0) && (*cur != '}')) cur++;\r
-           if (*cur == 0) {\r
-               xsltTransformError(ctxt, NULL, inst,\r
-                       "xsltAttrTemplateValueProcessNode: unmatched '{'\n");\r
-               ret = xmlStrncat(ret, str, cur - str);\r
-               return(ret);\r
-           }\r
-           str++;\r
-           expr = xmlStrndup(str, cur - str);\r
-           if (expr == NULL)\r
-               return(ret);\r
-           else if (*expr == '{') {\r
-               ret = xmlStrcat(ret, expr);\r
-               xmlFree(expr);\r
-           } else {\r
-               xmlXPathCompExprPtr comp;\r
-               /*\r
-                * TODO: keep precompiled form around\r
-                */\r
-               if ((nsList == NULL) && (inst != NULL)) {\r
-                   int i = 0;\r
-\r
-                   nsList = xmlGetNsList(inst->doc, inst);\r
-                   if (nsList != NULL) {\r
-                       while (nsList[i] != NULL)\r
-                           i++;\r
-                       nsNr = i;\r
-                   }\r
-               }\r
-               comp = xmlXPathCompile(expr);\r
-                val = xsltEvalXPathStringNs(ctxt, comp, nsNr, nsList);\r
-               xmlXPathFreeCompExpr(comp);\r
-               xmlFree(expr);\r
-               if (val != NULL) {\r
-                   ret = xmlStrcat(ret, val);\r
-                   xmlFree(val);\r
-               }\r
-           }\r
-           cur++;\r
-           str = cur;\r
-       } else if (*cur == '}') {\r
-           cur++;\r
-           if (*cur == '}') {  /* escaped '}' */\r
-               ret = xmlStrncat(ret, str, cur - str);\r
-               cur++;\r
-               str = cur;\r
-               continue;\r
-           } else {\r
-               xsltTransformError(ctxt, NULL, inst,\r
-                    "xsltAttrTemplateValueProcessNode: unmatched '}'\n");\r
-           }\r
-       } else\r
-           cur++;\r
-    }\r
-    if (cur != str) {\r
-       ret = xmlStrncat(ret, str, cur - str);\r
-    }\r
-\r
-    if (nsList != NULL)\r
-       xmlFree(nsList);\r
-\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltAttrTemplateValueProcess:\r
- * @ctxt:  the XSLT transformation context\r
- * @str:  the attribute template node value\r
- *\r
- * Process the given node and return the new string value.\r
- *\r
- * Returns the computed string value or NULL, must be deallocated by the\r
- *    caller.\r
- */\r
-xmlChar *\r
-xsltAttrTemplateValueProcess(xsltTransformContextPtr ctxt, const xmlChar *str) {\r
-    return(xsltAttrTemplateValueProcessNode(ctxt, str, NULL));\r
-}\r
-\r
-/**\r
- * xsltEvalAttrValueTemplate:\r
- * @ctxt:  the XSLT transformation context\r
- * @inst:  the instruction (or LRE) in the stylesheet holding the\r
- *         attribute with an AVT\r
- * @name:  the attribute QName\r
- * @ns:  the attribute namespace URI\r
- *\r
- * Evaluate a attribute value template, i.e. the attribute value can\r
- * contain expressions contained in curly braces ({}) and those are\r
- * substituted by they computed value.\r
- *\r
- * Returns the computed string value or NULL, must be deallocated by the\r
- *    caller.\r
- */\r
-xmlChar *\r
-xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr inst,\r
-                         const xmlChar *name, const xmlChar *ns)\r
-{\r
-    xmlChar *ret;\r
-    xmlChar *expr;\r
-\r
-    if ((ctxt == NULL) || (inst == NULL) || (name == NULL))\r
-       return(NULL);\r
-\r
-    expr = xsltGetNsProp(inst, name, ns);\r
-    if (expr == NULL)\r
-       return(NULL);\r
-\r
-    /*\r
-     * TODO: though now {} is detected ahead, it would still be good to\r
-     *       optimize both functions to keep the splitted value if the\r
-     *       attribute content and the XPath precompiled expressions around\r
-     */\r
-\r
-    ret = xsltAttrTemplateValueProcessNode(ctxt, expr, inst);\r
-#ifdef WITH_XSLT_DEBUG_TEMPLATES\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,\r
-        "xsltEvalAttrValueTemplate: %s returns %s\n", expr, ret));\r
-#endif\r
-    if (expr != NULL)\r
-       xmlFree(expr);\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltEvalStaticAttrValueTemplate:\r
- * @style:  the XSLT stylesheet\r
- * @inst:  the instruction (or LRE) in the stylesheet holding the\r
- *         attribute with an AVT\r
- * @name:  the attribute Name\r
- * @ns:  the attribute namespace URI\r
- * @found:  indicator whether the attribute is present\r
- *\r
- * Check if an attribute value template has a static value, i.e. the\r
- * attribute value does not contain expressions contained in curly braces ({})\r
- *\r
- * Returns the static string value or NULL, must be deallocated by the\r
- *    caller.\r
- */\r
-const xmlChar *\r
-xsltEvalStaticAttrValueTemplate(xsltStylesheetPtr style, xmlNodePtr inst,\r
-                       const xmlChar *name, const xmlChar *ns, int *found) {\r
-    const xmlChar *ret;\r
-    xmlChar *expr;\r
-\r
-    if ((style == NULL) || (inst == NULL) || (name == NULL))\r
-       return(NULL);\r
-\r
-    expr = xsltGetNsProp(inst, name, ns);\r
-    if (expr == NULL) {\r
-       *found = 0;\r
-       return(NULL);\r
-    }\r
-    *found = 1;\r
-\r
-    ret = xmlStrchr(expr, '{');\r
-    if (ret != NULL) {\r
-       xmlFree(expr);\r
-       return(NULL);\r
-    }\r
-    ret = xmlDictLookup(style->dict, expr, -1);\r
-    xmlFree(expr);\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltAttrTemplateProcess:\r
- * @ctxt:  the XSLT transformation context\r
- * @target:  the element where the attribute will be grafted\r
- * @attr:  the attribute node of a literal result element\r
- *\r
- * Process one attribute of a Literal Result Element (in the stylesheet).\r
- * Evaluates Attribute Value Templates and copies the attribute over to\r
- * the result element.\r
- * This does *not* process attribute sets (xsl:use-attribute-set).\r
- * \r
- *\r
- * Returns the generated attribute node.\r
- */\r
-xmlAttrPtr\r
-xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,\r
-                       xmlAttrPtr attr)\r
-{\r
-    const xmlChar *value;\r
-    xmlAttrPtr ret;\r
-\r
-    if ((ctxt == NULL) || (attr == NULL) || (target == NULL))\r
-       return(NULL);\r
-    \r
-    if (attr->type != XML_ATTRIBUTE_NODE)\r
-       return(NULL);\r
-\r
-    /*\r
-    * Skip all XSLT attributes.\r
-    */\r
-#ifdef XSLT_REFACTORED    \r
-    if (attr->psvi == xsltXSLTAttrMarker)\r
-       return(NULL);\r
-#else\r
-    if ((attr->ns != NULL) && xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))\r
-       return(NULL);\r
-#endif\r
-    /*\r
-    * Get the value.\r
-    */\r
-    if (attr->children != NULL) {\r
-       if ((attr->children->type != XML_TEXT_NODE) ||\r
-           (attr->children->next != NULL))\r
-       {\r
-           xsltTransformError(ctxt, NULL, attr->parent,\r
-               "Internal error: The children of an attribute node of a "\r
-               "literal result element are not in the expected form.\n");\r
-           return(NULL);\r
-       }\r
-       value = attr->children->content;\r
-       if (value == NULL)\r
-           value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);\r
-    } else\r
-       value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);\r
-    /*\r
-    * Overwrite duplicates.\r
-    */\r
-    ret = target->properties;\r
-    while (ret != NULL) {\r
-        if (((attr->ns != NULL) == (ret->ns != NULL)) &&\r
-           xmlStrEqual(ret->name, attr->name) &&\r
-           ((attr->ns == NULL) || xmlStrEqual(ret->ns->href, attr->ns->href)))\r
-       {\r
-           break;\r
-       }\r
-        ret = ret->next;\r
-    }\r
-    if (ret != NULL) { \r
-        /* free the existing value */\r
-       xmlFreeNodeList(ret->children);\r
-       ret->children = ret->last = NULL;\r
-       /*\r
-       * Adjust ns-prefix if needed.\r
-       */\r
-       if ((ret->ns != NULL) &&\r
-           (! xmlStrEqual(ret->ns->prefix, attr->ns->prefix)))\r
-       {\r
-           ret->ns = xsltGetNamespace(ctxt, attr->parent, attr->ns, target);\r
-       }\r
-    } else {\r
-        /* create a new attribute */\r
-       if (attr->ns != NULL)\r
-           ret = xmlNewNsProp(target,\r
-               xsltGetNamespace(ctxt, attr->parent, attr->ns, target),\r
-                   attr->name, NULL);\r
-       else\r
-           ret = xmlNewNsProp(target, NULL, attr->name, NULL); \r
-    }\r
-    /*\r
-    * Set the value.\r
-    */\r
-    if (ret != NULL) {\r
-        xmlNodePtr text;\r
-\r
-        text = xmlNewText(NULL);\r
-       if (text != NULL) {\r
-           ret->last = ret->children = text;\r
-           text->parent = (xmlNodePtr) ret;\r
-           text->doc = ret->doc;\r
-\r
-           if (attr->psvi != NULL) {\r
-               /*\r
-               * Evaluate the Attribute Value Template.\r
-               */\r
-               xmlChar *val;\r
-               val = xsltEvalAVT(ctxt, attr->psvi, attr->parent);\r
-               if (val == NULL) {\r
-                   /*\r
-                   * TODO: Damn, we need an easy mechanism to report\r
-                   * qualified names!\r
-                   */\r
-                   if (attr->ns) {\r
-                       xsltTransformError(ctxt, NULL, attr->parent,\r
-                           "Internal error: Failed to evaluate the AVT "\r
-                           "of attribute '{%s}%s'.\n",\r
-                           attr->ns->href, attr->name);\r
-                   } else {\r
-                       xsltTransformError(ctxt, NULL, attr->parent,\r
-                           "Internal error: Failed to evaluate the AVT "\r
-                           "of attribute '%s'.\n",\r
-                           attr->name);\r
-                   }\r
-                   text->content = xmlStrdup(BAD_CAST "");\r
-               } else {\r
-                   text->content = val;\r
-               }\r
-           } else if ((ctxt->internalized) && (target != NULL) &&\r
-                      (target->doc != NULL) &&\r
-                      (target->doc->dict == ctxt->dict)) {\r
-               text->content = (xmlChar *) value;\r
-           } else {\r
-               text->content = xmlStrdup(value);\r
-           }\r
-       }\r
-    } else {\r
-       if (attr->ns) {\r
-           xsltTransformError(ctxt, NULL, attr->parent,\r
-               "Internal error: Failed to create attribute '{%s}%s'.\n",\r
-               attr->ns->href, attr->name);\r
-       } else {\r
-           xsltTransformError(ctxt, NULL, attr->parent,\r
-               "Internal error: Failed to create attribute '%s'.\n",\r
-               attr->name);\r
-       }\r
-    }\r
-    return(ret);\r
-}\r
-\r
-\r
-/**\r
- * xsltAttrListTemplateProcess:\r
- * @ctxt:  the XSLT transformation context\r
- * @target:  the element where the attributes will be grafted\r
- * @cur:  the first attribute\r
- *\r
- * Processes all attributes of a Literal Result Element.\r
- * Attribute references are applied via xsl:use-attribute-set\r
- * attributes.\r
- * Copies all non XSLT-attributes over to the @target element\r
- * and evaluates Attribute Value Templates.\r
- *\r
- * Called by xsltApplySequenceConstructor() (transform.c).\r
- *\r
- * Returns a new list of attribute nodes, or NULL in case of error.\r
- *         (Don't assign the result to @target->properties; if\r
- *         the result is NULL, you'll get memory leaks, since the\r
- *         attributes will be disattached.)\r
- */\r
-xmlAttrPtr\r
-xsltAttrListTemplateProcess(xsltTransformContextPtr ctxt, \r
-                           xmlNodePtr target, xmlAttrPtr attrs)\r
-{\r
-    xmlAttrPtr attr, copy, last;\r
-    xmlNodePtr oldInsert, text;\r
-    xmlNsPtr origNs = NULL, copyNs = NULL;\r
-    const xmlChar *value;\r
-    xmlChar *valueAVT;\r
-\r
-    if ((ctxt == NULL) || (target == NULL) || (attrs == NULL))\r
-       return(NULL);\r
-\r
-    oldInsert = ctxt->insert;\r
-    ctxt->insert = target;        \r
-\r
-    /*\r
-    * Instantiate LRE-attributes.\r
-    */\r
-    if (target->properties) {\r
-       last = target->properties;\r
-       while (last->next != NULL)\r
-           last = last->next;\r
-    } else {\r
-       last = NULL;\r
-    }    \r
-    attr = attrs;\r
-    do {\r
-       /*\r
-       * Skip XSLT attributes.\r
-       */\r
-#ifdef XSLT_REFACTORED\r
-       if (attr->psvi == xsltXSLTAttrMarker) {\r
-           goto next_attribute;\r
-       }\r
-#else\r
-       if ((attr->ns != NULL) &&\r
-           xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))\r
-       {\r
-           goto next_attribute;\r
-       }\r
-#endif\r
-       /*\r
-       * Get the value.\r
-       */\r
-       if (attr->children != NULL) {\r
-           if ((attr->children->type != XML_TEXT_NODE) ||\r
-               (attr->children->next != NULL))\r
-           {\r
-               xsltTransformError(ctxt, NULL, attr->parent,\r
-                   "Internal error: The children of an attribute node of a "\r
-                   "literal result element are not in the expected form.\n");\r
-               goto error;\r
-           }\r
-           value = attr->children->content;\r
-           if (value == NULL)\r
-               value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);\r
-       } else\r
-           value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);\r
-\r
-       /*\r
-       * Create a new attribute.\r
-       */\r
-       copy = xmlNewDocProp(target->doc, attr->name, NULL);\r
-       if (copy == NULL) {\r
-           if (attr->ns) {\r
-               xsltTransformError(ctxt, NULL, attr->parent,\r
-                   "Internal error: Failed to create attribute '{%s}%s'.\n",\r
-                   attr->ns->href, attr->name);\r
-           } else {\r
-               xsltTransformError(ctxt, NULL, attr->parent,\r
-                   "Internal error: Failed to create attribute '%s'.\n",\r
-                   attr->name);\r
-           }\r
-           goto error;\r
-       }\r
-       /*\r
-       * Attach it to the target element.\r
-       */\r
-       copy->parent = target;\r
-       if (last == NULL) {\r
-           target->properties = copy;\r
-           last = copy;\r
-       } else {\r
-           last->next = copy;\r
-           copy->prev = last;\r
-           last = copy;\r
-       }\r
-       /*\r
-       * Set the namespace. Avoid lookups of same namespaces.\r
-       */\r
-       if (attr->ns != origNs) {\r
-           origNs = attr->ns;\r
-           if (attr->ns != NULL) {\r
-#ifdef XSLT_REFACTORED\r
-               copyNs = xsltGetSpecialNamespace(ctxt, attr->parent,\r
-                   attr->ns->href, attr->ns->prefix, target);\r
-#else\r
-               copyNs = xsltGetNamespace(ctxt, attr->parent,\r
-                   attr->ns, target);\r
-#endif\r
-               if (copyNs == NULL)\r
-                   goto error;\r
-           } else\r
-               copyNs = NULL;\r
-       }\r
-       copy->ns = copyNs;\r
-       \r
-       /*\r
-       * Set the value.\r
-       */          \r
-       text = xmlNewText(NULL);\r
-       if (text != NULL) {\r
-           copy->last = copy->children = text;\r
-           text->parent = (xmlNodePtr) copy;\r
-           text->doc = copy->doc;\r
-           \r
-           if (attr->psvi != NULL) {\r
-               /*\r
-               * Evaluate the Attribute Value Template.\r
-               */              \r
-               valueAVT = xsltEvalAVT(ctxt, attr->psvi, attr->parent);\r
-               if (valueAVT == NULL) {\r
-                   /*\r
-                   * TODO: Damn, we need an easy mechanism to report\r
-                   * qualified names!\r
-                   */\r
-                   if (attr->ns) {\r
-                       xsltTransformError(ctxt, NULL, attr->parent,\r
-                           "Internal error: Failed to evaluate the AVT "\r
-                           "of attribute '{%s}%s'.\n",\r
-                           attr->ns->href, attr->name);                            \r
-                   } else {\r
-                       xsltTransformError(ctxt, NULL, attr->parent,\r
-                           "Internal error: Failed to evaluate the AVT "\r
-                           "of attribute '%s'.\n",\r
-                           attr->name);\r
-                   }\r
-                   text->content = xmlStrdup(BAD_CAST "");\r
-                   goto error;\r
-               } else {\r
-                   text->content = valueAVT;\r
-               }\r
-           } else if ((ctxt->internalized) &&\r
-               (target->doc != NULL) &&\r
-               (target->doc->dict == ctxt->dict))\r
-           {\r
-               text->content = (xmlChar *) value;\r
-           } else {\r
-               text->content = xmlStrdup(value);\r
-           }\r
-       }\r
-\r
-next_attribute:\r
-       attr = attr->next;\r
-    } while (attr != NULL);\r
-\r
-    /*\r
-    * Apply attribute-sets.\r
-    * The creation of such attributes will not overwrite any existing\r
-    * attribute.\r
-    */\r
-    attr = attrs;\r
-    do {\r
-#ifdef XSLT_REFACTORED\r
-       if ((attr->psvi == xsltXSLTAttrMarker) &&\r
-           xmlStrEqual(attr->name, (const xmlChar *)"use-attribute-sets"))\r
-       {\r
-           xsltApplyAttributeSet(ctxt, ctxt->node, (xmlNodePtr) attr, NULL);\r
-       }\r
-#else\r
-       if ((attr->ns != NULL) &&\r
-           xmlStrEqual(attr->name, (const xmlChar *)"use-attribute-sets") &&\r
-           xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))\r
-       {\r
-           xsltApplyAttributeSet(ctxt, ctxt->node, (xmlNodePtr) attr, NULL);\r
-       }\r
-#endif\r
-       attr = attr->next;\r
-    } while (attr != NULL);\r
-\r
-    ctxt->insert = oldInsert;\r
-    return(target->properties);\r
-\r
-error:\r
-    ctxt->insert = oldInsert;\r
-    return(NULL);\r
-}\r
-\r
-\r
-/**\r
- * xsltTemplateProcess:\r
- * @ctxt:  the XSLT transformation context\r
- * @node:  the attribute template node\r
- *\r
- * Obsolete. Does always return NULL. Don't use it.\r
- */\r
-xmlNodePtr *\r
-xsltTemplateProcess(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, xmlNodePtr node) {\r
-    if (node == NULL)\r
-       return(NULL);\r
-    \r
-    return(0);\r
-}\r
-\r
-\r
+/*
+ * templates.c: Implementation of the template processing
+ *
+ * Reference:
+ *   http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/globals.h>
+#include <libxml/xmlerror.h>
+#include <libxml/tree.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/parserInternals.h>
+#include "xslt.h"
+#include "xsltInternals.h"
+#include "xsltutils.h"
+#include "variables.h"
+#include "functions.h"
+#include "templates.h"
+#include "transform.h"
+#include "namespaces.h"
+#include "attributes.h"
+
+#ifdef WITH_XSLT_DEBUG
+#define WITH_XSLT_DEBUG_TEMPLATES
+#endif
+
+/************************************************************************
+ *                                                                     *
+ *                     Module interfaces                               *
+ *                                                                     *
+ ************************************************************************/
+/**
+ * xsltEvalXPathPredicate:
+ * @ctxt:  the XSLT transformation context
+ * @comp:  the XPath compiled expression
+ * @nsList:  the namespaces in scope
+ * @nsNr:  the number of namespaces in scope
+ *
+ * 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, xmlXPathCompExprPtr comp,
+                      xmlNsPtr *nsList, int nsNr) {
+    int ret;
+    xmlXPathObjectPtr res;
+    int oldNsNr;
+    xmlNsPtr *oldNamespaces;
+    xmlNodePtr oldInst;
+    int oldProximityPosition, oldContextSize;
+
+    oldContextSize = ctxt->xpathCtxt->contextSize;
+    oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
+    oldNsNr = ctxt->xpathCtxt->nsNr;
+    oldNamespaces = ctxt->xpathCtxt->namespaces;
+    oldInst = ctxt->inst;
+
+    ctxt->xpathCtxt->node = ctxt->node;
+    ctxt->xpathCtxt->namespaces = nsList;
+    ctxt->xpathCtxt->nsNr = nsNr;
+
+    res = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
+
+    if (res != NULL) {
+       ret = xmlXPathEvalPredicate(ctxt->xpathCtxt, res);
+       xmlXPathFreeObject(res);
+#ifdef WITH_XSLT_DEBUG_TEMPLATES
+       XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltEvalXPathPredicate: returns %d\n", ret));
+#endif
+    } else {
+#ifdef WITH_XSLT_DEBUG_TEMPLATES
+       XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltEvalXPathPredicate: failed\n"));
+#endif
+       ctxt->state = XSLT_STATE_STOPPED;
+       ret = 0;
+    }
+    ctxt->xpathCtxt->nsNr = oldNsNr;
+
+    ctxt->xpathCtxt->namespaces = oldNamespaces;
+    ctxt->inst = oldInst;
+    ctxt->xpathCtxt->contextSize = oldContextSize;
+    ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
+
+    return(ret);
+}
+
+/**
+ * xsltEvalXPathStringNs:
+ * @ctxt:  the XSLT transformation context
+ * @comp:  the compiled XPath expression
+ * @nsNr:  the number of namespaces in the list
+ * @nsList:  the list of in-scope namespaces to use
+ *
+ * Process the expression using XPath, allowing to pass a namespace mapping
+ * context and get a string
+ *
+ * Returns the computed string value or NULL, must be deallocated by the
+ *    caller.
+ */
+xmlChar *
+xsltEvalXPathStringNs(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp,
+                     int nsNr, xmlNsPtr *nsList) {
+    xmlChar *ret = NULL;
+    xmlXPathObjectPtr res;
+    xmlNodePtr oldInst;
+    xmlNodePtr oldNode;
+    int        oldPos, oldSize;
+    int oldNsNr;
+    xmlNsPtr *oldNamespaces;
+
+    oldInst = ctxt->inst;
+    oldNode = ctxt->node;
+    oldPos = ctxt->xpathCtxt->proximityPosition;
+    oldSize = ctxt->xpathCtxt->contextSize;
+    oldNsNr = ctxt->xpathCtxt->nsNr;
+    oldNamespaces = ctxt->xpathCtxt->namespaces;
+
+    ctxt->xpathCtxt->node = ctxt->node;
+    /* TODO: do we need to propagate the namespaces here ? */
+    ctxt->xpathCtxt->namespaces = nsList;
+    ctxt->xpathCtxt->nsNr = nsNr;
+    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;
+       } else {
+           xsltTransformError(ctxt, NULL, NULL,
+                "xpath : string() function didn't return a String\n");
+       }
+       xmlXPathFreeObject(res);
+    } else {
+       ctxt->state = XSLT_STATE_STOPPED;
+    }
+#ifdef WITH_XSLT_DEBUG_TEMPLATES
+    XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
+        "xsltEvalXPathString: returns %s\n", ret));
+#endif
+    ctxt->inst = oldInst;
+    ctxt->node = oldNode;
+    ctxt->xpathCtxt->contextSize = oldSize;
+    ctxt->xpathCtxt->proximityPosition = oldPos;
+    ctxt->xpathCtxt->nsNr = oldNsNr;
+    ctxt->xpathCtxt->namespaces = oldNamespaces;
+    return(ret);
+}
+
+/**
+ * xsltEvalXPathString:
+ * @ctxt:  the XSLT transformation context
+ * @comp:  the compiled XPath expression
+ *
+ * Process the expression using XPath and get a string
+ *
+ * Returns the computed string value or NULL, must be deallocated by the
+ *    caller.
+ */
+xmlChar *
+xsltEvalXPathString(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp) {
+    return(xsltEvalXPathStringNs(ctxt, comp, 0, NULL));
+}
+
+/**
+ * xsltEvalTemplateString:
+ * @ctxt:  the XSLT transformation context
+ * @contextNode:  the current node in the source tree
+ * @inst:  the XSLT instruction (xsl:comment, xsl:processing-instruction)
+ *
+ * Processes the sequence constructor of the given instruction on
+ * @contextNode and converts the resulting tree to a string.
+ * This is needed by e.g. xsl:comment and xsl:processing-instruction.
+ *
+ * Returns the computed string value or NULL; it's up to the caller to
+ *         free the result.
+ */
+xmlChar *
+xsltEvalTemplateString(xsltTransformContextPtr ctxt,
+                      xmlNodePtr contextNode,
+                      xmlNodePtr inst)
+{
+    xmlNodePtr oldInsert, insert = NULL;
+    xmlChar *ret;
+
+    if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))
+       return(NULL);
+
+    if (inst->children == NULL)
+       return(NULL);
+
+    /*
+    * This creates a temporary element-node to add the resulting
+    * text content to.
+    * OPTIMIZE TODO: Keep such an element-node in the transformation
+    *  context to avoid creating it every time.
+    */
+    insert = xmlNewDocNode(ctxt->output, NULL,
+                          (const xmlChar *)"fake", NULL);
+    if (insert == NULL) {
+       xsltTransformError(ctxt, NULL, contextNode,
+               "Failed to create temporary node\n");
+       return(NULL);
+    }
+    oldInsert = ctxt->insert;
+    ctxt->insert = insert;
+    /*
+    * OPTIMIZE TODO: if inst->children consists only of text-nodes.
+    */
+    xsltApplyOneTemplate(ctxt, contextNode, inst->children, NULL, NULL);
+
+    ctxt->insert = oldInsert;
+
+    ret = xmlNodeGetContent(insert);
+    if (insert != NULL)
+       xmlFreeNode(insert);
+    return(ret);
+}
+
+/**
+ * xsltAttrTemplateValueProcessNode:
+ * @ctxt:  the XSLT transformation context
+ * @str:  the attribute template node value
+ * @inst:  the instruction (or LRE) in the stylesheet holding the
+ *         attribute with an AVT
+ *
+ * Process the given string, allowing to pass a namespace mapping
+ * context and return the new string value.
+ *
+ * Called by:
+ *  - xsltAttrTemplateValueProcess() (templates.c)
+ *  - xsltEvalAttrValueTemplate() (templates.c)
+ *
+ * QUESTION: Why is this function public? It is not used outside
+ *  of templates.c.
+ *
+ * Returns the computed string value or NULL, must be deallocated by the
+ *    caller.
+ */
+xmlChar *
+xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt,
+         const xmlChar *str, xmlNodePtr inst)
+{
+    xmlChar *ret = NULL;
+    const xmlChar *cur;
+    xmlChar *expr, *val;
+    xmlNsPtr *nsList = NULL;
+    int nsNr = 0;
+
+    if (str == NULL) return(NULL);
+    if (*str == 0)
+       return(xmlStrndup((xmlChar *)"", 0));
+
+    cur = str;
+    while (*cur != 0) {
+       if (*cur == '{') {
+           if (*(cur+1) == '{') {      /* escaped '{' */
+               cur++;
+               ret = xmlStrncat(ret, str, cur - str);
+               cur++;
+               str = cur;
+               continue;
+           }
+           ret = xmlStrncat(ret, str, cur - str);
+           str = cur;
+           cur++;
+           while ((*cur != 0) && (*cur != '}')) cur++;
+           if (*cur == 0) {
+               xsltTransformError(ctxt, NULL, inst,
+                       "xsltAttrTemplateValueProcessNode: unmatched '{'\n");
+               ret = xmlStrncat(ret, str, cur - str);
+               return(ret);
+           }
+           str++;
+           expr = xmlStrndup(str, cur - str);
+           if (expr == NULL)
+               return(ret);
+           else if (*expr == '{') {
+               ret = xmlStrcat(ret, expr);
+               xmlFree(expr);
+           } else {
+               xmlXPathCompExprPtr comp;
+               /*
+                * TODO: keep precompiled form around
+                */
+               if ((nsList == NULL) && (inst != NULL)) {
+                   int i = 0;
+
+                   nsList = xmlGetNsList(inst->doc, inst);
+                   if (nsList != NULL) {
+                       while (nsList[i] != NULL)
+                           i++;
+                       nsNr = i;
+                   }
+               }
+               comp = xmlXPathCompile(expr);
+                val = xsltEvalXPathStringNs(ctxt, comp, nsNr, nsList);
+               xmlXPathFreeCompExpr(comp);
+               xmlFree(expr);
+               if (val != NULL) {
+                   ret = xmlStrcat(ret, val);
+                   xmlFree(val);
+               }
+           }
+           cur++;
+           str = cur;
+       } else if (*cur == '}') {
+           cur++;
+           if (*cur == '}') {  /* escaped '}' */
+               ret = xmlStrncat(ret, str, cur - str);
+               cur++;
+               str = cur;
+               continue;
+           } else {
+               xsltTransformError(ctxt, NULL, inst,
+                    "xsltAttrTemplateValueProcessNode: unmatched '}'\n");
+           }
+       } else
+           cur++;
+    }
+    if (cur != str) {
+       ret = xmlStrncat(ret, str, cur - str);
+    }
+
+    if (nsList != NULL)
+       xmlFree(nsList);
+
+    return(ret);
+}
+
+/**
+ * xsltAttrTemplateValueProcess:
+ * @ctxt:  the XSLT transformation context
+ * @str:  the attribute template node value
+ *
+ * Process the given node and return the new string value.
+ *
+ * Returns the computed string value or NULL, must be deallocated by the
+ *    caller.
+ */
+xmlChar *
+xsltAttrTemplateValueProcess(xsltTransformContextPtr ctxt, const xmlChar *str) {
+    return(xsltAttrTemplateValueProcessNode(ctxt, str, NULL));
+}
+
+/**
+ * xsltEvalAttrValueTemplate:
+ * @ctxt:  the XSLT transformation context
+ * @inst:  the instruction (or LRE) in the stylesheet holding the
+ *         attribute with an AVT
+ * @name:  the attribute QName
+ * @ns:  the attribute namespace URI
+ *
+ * Evaluate a attribute value template, i.e. the attribute value can
+ * contain expressions contained in curly braces ({}) and those are
+ * substituted by they computed value.
+ *
+ * Returns the computed string value or NULL, must be deallocated by the
+ *    caller.
+ */
+xmlChar *
+xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr inst,
+                         const xmlChar *name, const xmlChar *ns)
+{
+    xmlChar *ret;
+    xmlChar *expr;
+
+    if ((ctxt == NULL) || (inst == NULL) || (name == NULL))
+       return(NULL);
+
+    expr = xsltGetNsProp(inst, name, ns);
+    if (expr == NULL)
+       return(NULL);
+
+    /*
+     * 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 = xsltAttrTemplateValueProcessNode(ctxt, expr, inst);
+#ifdef WITH_XSLT_DEBUG_TEMPLATES
+    XSLT_TRACE(ctxt,XSLT_TRACE_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
+        "xsltEvalAttrValueTemplate: %s returns %s\n", expr, ret));
+#endif
+    if (expr != NULL)
+       xmlFree(expr);
+    return(ret);
+}
+
+/**
+ * xsltEvalStaticAttrValueTemplate:
+ * @style:  the XSLT stylesheet
+ * @inst:  the instruction (or LRE) in the stylesheet holding the
+ *         attribute with an AVT
+ * @name:  the attribute Name
+ * @ns:  the attribute namespace URI
+ * @found:  indicator whether the attribute is present
+ *
+ * Check if an attribute value template has a static value, i.e. the
+ * attribute value does not contain expressions contained in curly braces ({})
+ *
+ * Returns the static string value or NULL, must be deallocated by the
+ *    caller.
+ */
+const xmlChar *
+xsltEvalStaticAttrValueTemplate(xsltStylesheetPtr style, xmlNodePtr inst,
+                       const xmlChar *name, const xmlChar *ns, int *found) {
+    const xmlChar *ret;
+    xmlChar *expr;
+
+    if ((style == NULL) || (inst == NULL) || (name == NULL))
+       return(NULL);
+
+    expr = xsltGetNsProp(inst, name, ns);
+    if (expr == NULL) {
+       *found = 0;
+       return(NULL);
+    }
+    *found = 1;
+
+    ret = xmlStrchr(expr, '{');
+    if (ret != NULL) {
+       xmlFree(expr);
+       return(NULL);
+    }
+    ret = xmlDictLookup(style->dict, expr, -1);
+    xmlFree(expr);
+    return(ret);
+}
+
+/**
+ * xsltAttrTemplateProcess:
+ * @ctxt:  the XSLT transformation context
+ * @target:  the element where the attribute will be grafted
+ * @attr:  the attribute node of a literal result element
+ *
+ * Process one attribute of a Literal Result Element (in the stylesheet).
+ * Evaluates Attribute Value Templates and copies the attribute over to
+ * the result element.
+ * This does *not* process attribute sets (xsl:use-attribute-set).
+ * 
+ *
+ * Returns the generated attribute node.
+ */
+xmlAttrPtr
+xsltAttrTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target,
+                       xmlAttrPtr attr)
+{
+    const xmlChar *value;
+    xmlAttrPtr ret;
+
+    if ((ctxt == NULL) || (attr == NULL) || (target == NULL))
+       return(NULL);
+    
+    if (attr->type != XML_ATTRIBUTE_NODE)
+       return(NULL);
+
+    /*
+    * Skip all XSLT attributes.
+    */
+#ifdef XSLT_REFACTORED    
+    if (attr->psvi == xsltXSLTAttrMarker)
+       return(NULL);
+#else
+    if ((attr->ns != NULL) && xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))
+       return(NULL);
+#endif
+    /*
+    * Get the value.
+    */
+    if (attr->children != NULL) {
+       if ((attr->children->type != XML_TEXT_NODE) ||
+           (attr->children->next != NULL))
+       {
+           xsltTransformError(ctxt, NULL, attr->parent,
+               "Internal error: The children of an attribute node of a "
+               "literal result element are not in the expected form.\n");
+           return(NULL);
+       }
+       value = attr->children->content;
+       if (value == NULL)
+           value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
+    } else
+       value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
+    /*
+    * Overwrite duplicates.
+    */
+    ret = target->properties;
+    while (ret != NULL) {
+        if (((attr->ns != NULL) == (ret->ns != NULL)) &&
+           xmlStrEqual(ret->name, attr->name) &&
+           ((attr->ns == NULL) || xmlStrEqual(ret->ns->href, attr->ns->href)))
+       {
+           break;
+       }
+        ret = ret->next;
+    }
+    if (ret != NULL) { 
+        /* free the existing value */
+       xmlFreeNodeList(ret->children);
+       ret->children = ret->last = NULL;
+       /*
+       * Adjust ns-prefix if needed.
+       */
+       if ((ret->ns != NULL) &&
+           (! xmlStrEqual(ret->ns->prefix, attr->ns->prefix)))
+       {
+           ret->ns = xsltGetNamespace(ctxt, attr->parent, attr->ns, target);
+       }
+    } else {
+        /* create a new attribute */
+       if (attr->ns != NULL)
+           ret = xmlNewNsProp(target,
+               xsltGetNamespace(ctxt, attr->parent, attr->ns, target),
+                   attr->name, NULL);
+       else
+           ret = xmlNewNsProp(target, NULL, attr->name, NULL); 
+    }
+    /*
+    * Set the value.
+    */
+    if (ret != NULL) {
+        xmlNodePtr text;
+
+        text = xmlNewText(NULL);
+       if (text != NULL) {
+           ret->last = ret->children = text;
+           text->parent = (xmlNodePtr) ret;
+           text->doc = ret->doc;
+
+           if (attr->psvi != NULL) {
+               /*
+               * Evaluate the Attribute Value Template.
+               */
+               xmlChar *val;
+               val = xsltEvalAVT(ctxt, attr->psvi, attr->parent);
+               if (val == NULL) {
+                   /*
+                   * TODO: Damn, we need an easy mechanism to report
+                   * qualified names!
+                   */
+                   if (attr->ns) {
+                       xsltTransformError(ctxt, NULL, attr->parent,
+                           "Internal error: Failed to evaluate the AVT "
+                           "of attribute '{%s}%s'.\n",
+                           attr->ns->href, attr->name);
+                   } else {
+                       xsltTransformError(ctxt, NULL, attr->parent,
+                           "Internal error: Failed to evaluate the AVT "
+                           "of attribute '%s'.\n",
+                           attr->name);
+                   }
+                   text->content = xmlStrdup(BAD_CAST "");
+               } else {
+                   text->content = val;
+               }
+           } else if ((ctxt->internalized) && (target != NULL) &&
+                      (target->doc != NULL) &&
+                      (target->doc->dict == ctxt->dict)) {
+               text->content = (xmlChar *) value;
+           } else {
+               text->content = xmlStrdup(value);
+           }
+       }
+    } else {
+       if (attr->ns) {
+           xsltTransformError(ctxt, NULL, attr->parent,
+               "Internal error: Failed to create attribute '{%s}%s'.\n",
+               attr->ns->href, attr->name);
+       } else {
+           xsltTransformError(ctxt, NULL, attr->parent,
+               "Internal error: Failed to create attribute '%s'.\n",
+               attr->name);
+       }
+    }
+    return(ret);
+}
+
+
+/**
+ * xsltAttrListTemplateProcess:
+ * @ctxt:  the XSLT transformation context
+ * @target:  the element where the attributes will be grafted
+ * @cur:  the first attribute
+ *
+ * Processes all attributes of a Literal Result Element.
+ * Attribute references are applied via xsl:use-attribute-set
+ * attributes.
+ * Copies all non XSLT-attributes over to the @target element
+ * and evaluates Attribute Value Templates.
+ *
+ * Called by xsltApplySequenceConstructor() (transform.c).
+ *
+ * Returns a new list of attribute nodes, or NULL in case of error.
+ *         (Don't assign the result to @target->properties; if
+ *         the result is NULL, you'll get memory leaks, since the
+ *         attributes will be disattached.)
+ */
+xmlAttrPtr
+xsltAttrListTemplateProcess(xsltTransformContextPtr ctxt, 
+                           xmlNodePtr target, xmlAttrPtr attrs)
+{
+    xmlAttrPtr attr, copy, last;
+    xmlNodePtr oldInsert, text;
+    xmlNsPtr origNs = NULL, copyNs = NULL;
+    const xmlChar *value;
+    xmlChar *valueAVT;
+
+    if ((ctxt == NULL) || (target == NULL) || (attrs == NULL))
+       return(NULL);
+
+    oldInsert = ctxt->insert;
+    ctxt->insert = target;        
+
+    /*
+    * Instantiate LRE-attributes.
+    */
+    if (target->properties) {
+       last = target->properties;
+       while (last->next != NULL)
+           last = last->next;
+    } else {
+       last = NULL;
+    }    
+    attr = attrs;
+    do {
+       /*
+       * Skip XSLT attributes.
+       */
+#ifdef XSLT_REFACTORED
+       if (attr->psvi == xsltXSLTAttrMarker) {
+           goto next_attribute;
+       }
+#else
+       if ((attr->ns != NULL) &&
+           xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))
+       {
+           goto next_attribute;
+       }
+#endif
+       /*
+       * Get the value.
+       */
+       if (attr->children != NULL) {
+           if ((attr->children->type != XML_TEXT_NODE) ||
+               (attr->children->next != NULL))
+           {
+               xsltTransformError(ctxt, NULL, attr->parent,
+                   "Internal error: The children of an attribute node of a "
+                   "literal result element are not in the expected form.\n");
+               goto error;
+           }
+           value = attr->children->content;
+           if (value == NULL)
+               value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
+       } else
+           value = xmlDictLookup(ctxt->dict, BAD_CAST "", 0);
+
+       /*
+       * Create a new attribute.
+       */
+       copy = xmlNewDocProp(target->doc, attr->name, NULL);
+       if (copy == NULL) {
+           if (attr->ns) {
+               xsltTransformError(ctxt, NULL, attr->parent,
+                   "Internal error: Failed to create attribute '{%s}%s'.\n",
+                   attr->ns->href, attr->name);
+           } else {
+               xsltTransformError(ctxt, NULL, attr->parent,
+                   "Internal error: Failed to create attribute '%s'.\n",
+                   attr->name);
+           }
+           goto error;
+       }
+       /*
+       * Attach it to the target element.
+       */
+       copy->parent = target;
+       if (last == NULL) {
+           target->properties = copy;
+           last = copy;
+       } else {
+           last->next = copy;
+           copy->prev = last;
+           last = copy;
+       }
+       /*
+       * Set the namespace. Avoid lookups of same namespaces.
+       */
+       if (attr->ns != origNs) {
+           origNs = attr->ns;
+           if (attr->ns != NULL) {
+#ifdef XSLT_REFACTORED
+               copyNs = xsltGetSpecialNamespace(ctxt, attr->parent,
+                   attr->ns->href, attr->ns->prefix, target);
+#else
+               copyNs = xsltGetNamespace(ctxt, attr->parent,
+                   attr->ns, target);
+#endif
+               if (copyNs == NULL)
+                   goto error;
+           } else
+               copyNs = NULL;
+       }
+       copy->ns = copyNs;
+       
+       /*
+       * Set the value.
+       */          
+       text = xmlNewText(NULL);
+       if (text != NULL) {
+           copy->last = copy->children = text;
+           text->parent = (xmlNodePtr) copy;
+           text->doc = copy->doc;
+           
+           if (attr->psvi != NULL) {
+               /*
+               * Evaluate the Attribute Value Template.
+               */              
+               valueAVT = xsltEvalAVT(ctxt, attr->psvi, attr->parent);
+               if (valueAVT == NULL) {
+                   /*
+                   * TODO: Damn, we need an easy mechanism to report
+                   * qualified names!
+                   */
+                   if (attr->ns) {
+                       xsltTransformError(ctxt, NULL, attr->parent,
+                           "Internal error: Failed to evaluate the AVT "
+                           "of attribute '{%s}%s'.\n",
+                           attr->ns->href, attr->name);                            
+                   } else {
+                       xsltTransformError(ctxt, NULL, attr->parent,
+                           "Internal error: Failed to evaluate the AVT "
+                           "of attribute '%s'.\n",
+                           attr->name);
+                   }
+                   text->content = xmlStrdup(BAD_CAST "");
+                   goto error;
+               } else {
+                   text->content = valueAVT;
+               }
+           } else if ((ctxt->internalized) &&
+               (target->doc != NULL) &&
+               (target->doc->dict == ctxt->dict))
+           {
+               text->content = (xmlChar *) value;
+           } else {
+               text->content = xmlStrdup(value);
+           }
+       }
+
+next_attribute:
+       attr = attr->next;
+    } while (attr != NULL);
+
+    /*
+    * Apply attribute-sets.
+    * The creation of such attributes will not overwrite any existing
+    * attribute.
+    */
+    attr = attrs;
+    do {
+#ifdef XSLT_REFACTORED
+       if ((attr->psvi == xsltXSLTAttrMarker) &&
+           xmlStrEqual(attr->name, (const xmlChar *)"use-attribute-sets"))
+       {
+           xsltApplyAttributeSet(ctxt, ctxt->node, (xmlNodePtr) attr, NULL);
+       }
+#else
+       if ((attr->ns != NULL) &&
+           xmlStrEqual(attr->name, (const xmlChar *)"use-attribute-sets") &&
+           xmlStrEqual(attr->ns->href, XSLT_NAMESPACE))
+       {
+           xsltApplyAttributeSet(ctxt, ctxt->node, (xmlNodePtr) attr, NULL);
+       }
+#endif
+       attr = attr->next;
+    } while (attr != NULL);
+
+    ctxt->insert = oldInsert;
+    return(target->properties);
+
+error:
+    ctxt->insert = oldInsert;
+    return(NULL);
+}
+
+
+/**
+ * xsltTemplateProcess:
+ * @ctxt:  the XSLT transformation context
+ * @node:  the attribute template node
+ *
+ * Obsolete. Does always return NULL. Don't use it.
+ */
+xmlNodePtr *
+xsltTemplateProcess(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, xmlNodePtr node) {
+    if (node == NULL)
+       return(NULL);
+    
+    return(0);
+}
+
+
index 54907e1..18adfdb 100644 (file)
@@ -1,77 +1,77 @@
-/*\r
- * Summary: interface for the template processing\r
- * Description: This set of routine encapsulates XPath calls\r
- *              and Attribute Value Templates evaluation.\r
- *\r
- * Copy: See Copyright for the status of this software.\r
- *\r
- * Author: Daniel Veillard\r
- */\r
-\r
-#ifndef __XML_XSLT_TEMPLATES_H__\r
-#define __XML_XSLT_TEMPLATES_H__\r
-\r
-#include <libxml/xpath.h>\r
-#include <libxml/xpathInternals.h>\r
-#include "xsltexports.h"\r
-#include "xsltInternals.h"\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-XSLTPUBFUN int XSLTCALL                \r
-               xsltEvalXPathPredicate          (xsltTransformContextPtr ctxt,\r
-                                                xmlXPathCompExprPtr comp,\r
-                                                xmlNsPtr *nsList,\r
-                                                int nsNr);\r
-XSLTPUBFUN xmlChar * XSLTCALL  \r
-               xsltEvalTemplateString          (xsltTransformContextPtr ctxt,\r
-                                                xmlNodePtr contextNode,\r
-                                                xmlNodePtr inst);\r
-XSLTPUBFUN xmlChar * XSLTCALL  \r
-               xsltEvalAttrValueTemplate       (xsltTransformContextPtr ctxt,\r
-                                                xmlNodePtr node,\r
-                                                const xmlChar *name,\r
-                                                const xmlChar *ns);\r
-XSLTPUBFUN const xmlChar * XSLTCALL    \r
-               xsltEvalStaticAttrValueTemplate (xsltStylesheetPtr style,\r
-                                                xmlNodePtr node,\r
-                                                const xmlChar *name,\r
-                                                const xmlChar *ns,\r
-                                                int *found);\r
-\r
-/* TODO: this is obviously broken ... the namespaces should be passed too ! */\r
-XSLTPUBFUN xmlChar * XSLTCALL  \r
-               xsltEvalXPathString             (xsltTransformContextPtr ctxt,\r
-                                                xmlXPathCompExprPtr comp);\r
-XSLTPUBFUN xmlChar * XSLTCALL  \r
-               xsltEvalXPathStringNs           (xsltTransformContextPtr ctxt,\r
-                                                xmlXPathCompExprPtr comp,\r
-                                                int nsNr,\r
-                                                xmlNsPtr *nsList);\r
-\r
-XSLTPUBFUN xmlNodePtr * XSLTCALL       \r
-               xsltTemplateProcess             (xsltTransformContextPtr ctxt,\r
-                                                xmlNodePtr node);\r
-XSLTPUBFUN xmlAttrPtr XSLTCALL \r
-               xsltAttrListTemplateProcess     (xsltTransformContextPtr ctxt,\r
-                                                xmlNodePtr target,\r
-                                                xmlAttrPtr cur);\r
-XSLTPUBFUN xmlAttrPtr XSLTCALL \r
-               xsltAttrTemplateProcess         (xsltTransformContextPtr ctxt,\r
-                                                xmlNodePtr target,\r
-                                                xmlAttrPtr attr);\r
-XSLTPUBFUN xmlChar * XSLTCALL  \r
-               xsltAttrTemplateValueProcess    (xsltTransformContextPtr ctxt,\r
-                                                const xmlChar* attr);\r
-XSLTPUBFUN xmlChar * XSLTCALL  \r
-               xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt,\r
-                                                const xmlChar* str,\r
-                                                xmlNodePtr node);\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-\r
-#endif /* __XML_XSLT_TEMPLATES_H__ */\r
-\r
+/*
+ * Summary: interface for the template processing
+ * Description: This set of routine encapsulates XPath calls
+ *              and Attribute Value Templates evaluation.
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Daniel Veillard
+ */
+
+#ifndef __XML_XSLT_TEMPLATES_H__
+#define __XML_XSLT_TEMPLATES_H__
+
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include "xsltexports.h"
+#include "xsltInternals.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+XSLTPUBFUN int XSLTCALL                
+               xsltEvalXPathPredicate          (xsltTransformContextPtr ctxt,
+                                                xmlXPathCompExprPtr comp,
+                                                xmlNsPtr *nsList,
+                                                int nsNr);
+XSLTPUBFUN xmlChar * XSLTCALL  
+               xsltEvalTemplateString          (xsltTransformContextPtr ctxt,
+                                                xmlNodePtr contextNode,
+                                                xmlNodePtr inst);
+XSLTPUBFUN xmlChar * XSLTCALL  
+               xsltEvalAttrValueTemplate       (xsltTransformContextPtr ctxt,
+                                                xmlNodePtr node,
+                                                const xmlChar *name,
+                                                const xmlChar *ns);
+XSLTPUBFUN const xmlChar * XSLTCALL    
+               xsltEvalStaticAttrValueTemplate (xsltStylesheetPtr style,
+                                                xmlNodePtr node,
+                                                const xmlChar *name,
+                                                const xmlChar *ns,
+                                                int *found);
+
+/* TODO: this is obviously broken ... the namespaces should be passed too ! */
+XSLTPUBFUN xmlChar * XSLTCALL  
+               xsltEvalXPathString             (xsltTransformContextPtr ctxt,
+                                                xmlXPathCompExprPtr comp);
+XSLTPUBFUN xmlChar * XSLTCALL  
+               xsltEvalXPathStringNs           (xsltTransformContextPtr ctxt,
+                                                xmlXPathCompExprPtr comp,
+                                                int nsNr,
+                                                xmlNsPtr *nsList);
+
+XSLTPUBFUN xmlNodePtr * XSLTCALL       
+               xsltTemplateProcess             (xsltTransformContextPtr ctxt,
+                                                xmlNodePtr node);
+XSLTPUBFUN xmlAttrPtr XSLTCALL 
+               xsltAttrListTemplateProcess     (xsltTransformContextPtr ctxt,
+                                                xmlNodePtr target,
+                                                xmlAttrPtr cur);
+XSLTPUBFUN xmlAttrPtr XSLTCALL 
+               xsltAttrTemplateProcess         (xsltTransformContextPtr ctxt,
+                                                xmlNodePtr target,
+                                                xmlAttrPtr attr);
+XSLTPUBFUN xmlChar * XSLTCALL  
+               xsltAttrTemplateValueProcess    (xsltTransformContextPtr ctxt,
+                                                const xmlChar* attr);
+XSLTPUBFUN xmlChar * XSLTCALL  
+               xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt,
+                                                const xmlChar* str,
+                                                xmlNodePtr node);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __XML_XSLT_TEMPLATES_H__ */
+
index ed1bfc0..e9eda83 100644 (file)
-/*\r
- * transform.c: Implementation of the XSL Transformation 1.0 engine\r
- *              transform part, i.e. applying a Stylesheet to a document\r
- *\r
- * References:\r
- *   http://www.w3.org/TR/1999/REC-xslt-19991116\r
- *\r
- *   Michael Kay "XSLT Programmer's Reference" pp 637-643\r
- *   Writing Multiple Output Files\r
- *\r
- *   XSLT-1.1 Working Draft\r
- *   http://www.w3.org/TR/xslt11#multiple-output\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * daniel@veillard.com\r
- */\r
-\r
-#define IN_LIBXSLT\r
-#include "libxslt.h"\r
-\r
-#include <string.h>\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/parser.h>\r
-#include <libxml/tree.h>\r
-#include <libxml/valid.h>\r
-#include <libxml/hash.h>\r
-#include <libxml/encoding.h>\r
-#include <libxml/xmlerror.h>\r
-#include <libxml/xpath.h>\r
-#include <libxml/parserInternals.h>\r
-#include <libxml/xpathInternals.h>\r
-#include <libxml/HTMLtree.h>\r
-#include <libxml/debugXML.h>\r
-#include <libxml/uri.h>\r
-#include "xslt.h"\r
-#include "xsltInternals.h"\r
-#include "xsltutils.h"\r
-#include "pattern.h"\r
-#include "transform.h"\r
-#include "variables.h"\r
-#include "numbersInternals.h"\r
-#include "namespaces.h"\r
-#include "attributes.h"\r
-#include "templates.h"\r
-#include "imports.h"\r
-#include "keys.h"\r
-#include "documents.h"\r
-#include "extensions.h"\r
-#include "extra.h"\r
-#include "preproc.h"\r
-#include "security.h"\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
-#define WITH_XSLT_DEBUG_EXTRA\r
-#define WITH_XSLT_DEBUG_PROCESS\r
-#endif\r
-\r
-#define XSLT_GENERATE_HTML_DOCTYPE\r
-#ifdef XSLT_GENERATE_HTML_DOCTYPE\r
-static int xsltGetHTMLIDs(const xmlChar *version, const xmlChar **publicID,\r
-                         const xmlChar **systemID);\r
-#endif\r
-\r
-int xsltMaxDepth = 3000;\r
-\r
-/*\r
- * Useful macros\r
- */\r
-\r
-#ifndef FALSE\r
-# define FALSE (0 == 1)\r
-# define TRUE (!FALSE)\r
-#endif\r
-\r
-#define IS_BLANK_NODE(n)                                               \\r
-    (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))\r
-\r
-\r
-/*\r
-* Forward declarations\r
-*/\r
-\r
-static xmlNsPtr\r
-xsltCopyNamespaceListInternal(xmlNodePtr node, xmlNsPtr cur);\r
-\r
-static xmlNodePtr\r
-xsltCopyTreeInternal(xsltTransformContextPtr ctxt,\r
-                    xmlNodePtr invocNode,\r
-                    xmlNodePtr node,\r
-                    xmlNodePtr insert, int isLRE, int topElemVisited);\r
-\r
-static void\r
-xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,\r
-                            xmlNodePtr contextNode, xmlNodePtr list,\r
-                            xsltTemplatePtr templ);\r
-\r
-static void\r
-xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,\r
-                     xmlNodePtr contextNode,\r
-                     xmlNodePtr list,\r
-                     xsltTemplatePtr templ,\r
-                     xsltStackElemPtr withParams);\r
-\r
-/**\r
- * templPush:\r
- * @ctxt: the transformation context\r
- * @value:  the template to push on the stack\r
- *\r
- * Push a template on the stack\r
- *\r
- * Returns the new index in the stack or 0 in case of error\r
- */\r
-static int\r
-templPush(xsltTransformContextPtr ctxt, xsltTemplatePtr value)\r
-{\r
-    if (ctxt->templMax == 0) {\r
-        ctxt->templMax = 4;\r
-        ctxt->templTab =\r
-            (xsltTemplatePtr *) xmlMalloc(ctxt->templMax *\r
-                                          sizeof(ctxt->templTab[0]));\r
-        if (ctxt->templTab == NULL) {\r
-            xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");\r
-            return (0);\r
-        }\r
-    }\r
-    if (ctxt->templNr >= ctxt->templMax) {\r
-        ctxt->templMax *= 2;\r
-        ctxt->templTab =\r
-            (xsltTemplatePtr *) xmlRealloc(ctxt->templTab,\r
-                                           ctxt->templMax *\r
-                                           sizeof(ctxt->templTab[0]));\r
-        if (ctxt->templTab == NULL) {\r
-            xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");\r
-            return (0);\r
-        }\r
-    }\r
-    ctxt->templTab[ctxt->templNr] = value;\r
-    ctxt->templ = value;\r
-    return (ctxt->templNr++);\r
-}\r
-/**\r
- * templPop:\r
- * @ctxt: the transformation context\r
- *\r
- * Pop a template value from the stack\r
- *\r
- * Returns the stored template value\r
- */\r
-static xsltTemplatePtr\r
-templPop(xsltTransformContextPtr ctxt)\r
-{\r
-    xsltTemplatePtr ret;\r
-\r
-    if (ctxt->templNr <= 0)\r
-        return (0);\r
-    ctxt->templNr--;\r
-    if (ctxt->templNr > 0)\r
-        ctxt->templ = ctxt->templTab[ctxt->templNr - 1];\r
-    else\r
-        ctxt->templ = (xsltTemplatePtr) 0;\r
-    ret = ctxt->templTab[ctxt->templNr];\r
-    ctxt->templTab[ctxt->templNr] = 0;\r
-    return (ret);\r
-}\r
-\r
-/**\r
- * xsltVariablePop:\r
- * @ctxt: the transformation context\r
- * @depth:  the depth in the xsl:template's tree\r
- *\r
- * Pops all variable values at the given @depth from the stack.\r
- *\r
- * Returns the stored variable value\r
- */\r
-static void\r
-xsltLocalVariablePop(xsltTransformContextPtr ctxt, int limitNr, int level)\r
-{\r
-    xsltStackElemPtr variable;\r
-\r
-    if (ctxt->varsNr <= 0)\r
-        return;\r
-\r
-    do {\r
-       if (ctxt->varsNr <= limitNr)\r
-           break;\r
-       variable = ctxt->varsTab[ctxt->varsNr - 1];\r
-       if (variable->level <= level)\r
-           break;      \r
-       if (variable->level >= 0)\r
-           xsltFreeStackElemList(variable);\r
-       ctxt->varsNr--;\r
-    } while (ctxt->varsNr != 0);\r
-    if (ctxt->varsNr > 0)\r
-        ctxt->vars = ctxt->varsTab[ctxt->varsNr - 1];\r
-    else\r
-        ctxt->vars = NULL;\r
-}\r
-\r
-/**\r
- * xsltTemplateParamsCleanup:\r
- *\r
- * Removes xsl:param and xsl:with-param items from the\r
- * variable-stack. Only xsl:with-param items are not freed. \r
- */\r
-static void\r
-xsltTemplateParamsCleanup(xsltTransformContextPtr ctxt)\r
-{\r
-    xsltStackElemPtr param;    \r
-\r
-    for (; ctxt->varsNr > ctxt->varsBase; ctxt->varsNr--) {\r
-       param = ctxt->varsTab[ctxt->varsNr -1];\r
-       /*\r
-       * Free xsl:param items.\r
-       * xsl:with-param items will have a level of -1 or -2.\r
-       */\r
-       if (param->level >= 0) {            \r
-           xsltFreeStackElemList(param);\r
-       }           \r
-    }    \r
-    if (ctxt->varsNr > 0)\r
-        ctxt->vars = ctxt->varsTab[ctxt->varsNr - 1];\r
-    else\r
-        ctxt->vars = NULL;\r
-}\r
-\r
-/**\r
- * profPush:\r
- * @ctxt: the transformation context\r
- * @value:  the profiling value to push on the stack\r
- *\r
- * Push a profiling value on the stack\r
- *\r
- * Returns the new index in the stack or 0 in case of error\r
- */\r
-static int\r
-profPush(xsltTransformContextPtr ctxt, long value)\r
-{\r
-    if (ctxt->profMax == 0) {\r
-        ctxt->profMax = 4;\r
-        ctxt->profTab =\r
-            (long *) xmlMalloc(ctxt->profMax * sizeof(ctxt->profTab[0]));\r
-        if (ctxt->profTab == NULL) {\r
-            xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");\r
-            return (0);\r
-        }\r
-    }\r
-    if (ctxt->profNr >= ctxt->profMax) {\r
-        ctxt->profMax *= 2;\r
-        ctxt->profTab =\r
-            (long *) xmlRealloc(ctxt->profTab,\r
-                                ctxt->profMax * sizeof(ctxt->profTab[0]));\r
-        if (ctxt->profTab == NULL) {\r
-            xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");\r
-            return (0);\r
-        }\r
-    }\r
-    ctxt->profTab[ctxt->profNr] = value;\r
-    ctxt->prof = value;\r
-    return (ctxt->profNr++);\r
-}\r
-/**\r
- * profPop:\r
- * @ctxt: the transformation context\r
- *\r
- * Pop a profiling value from the stack\r
- *\r
- * Returns the stored profiling value\r
- */\r
-static long\r
-profPop(xsltTransformContextPtr ctxt)\r
-{\r
-    long ret;\r
-\r
-    if (ctxt->profNr <= 0)\r
-        return (0);\r
-    ctxt->profNr--;\r
-    if (ctxt->profNr > 0)\r
-        ctxt->prof = ctxt->profTab[ctxt->profNr - 1];\r
-    else\r
-        ctxt->prof = (long) 0;\r
-    ret = ctxt->profTab[ctxt->profNr];\r
-    ctxt->profTab[ctxt->profNr] = 0;\r
-    return (ret);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     XInclude default settings                       *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-static int xsltDoXIncludeDefault = 0;\r
-\r
-/**\r
- * xsltSetXIncludeDefault:\r
- * @xinclude: whether to do XInclude processing\r
- *\r
- * Set whether XInclude should be processed on document being loaded by default\r
- */\r
-void\r
-xsltSetXIncludeDefault(int xinclude) {\r
-    xsltDoXIncludeDefault = (xinclude != 0);\r
-}\r
-\r
-/**\r
- * xsltGetXIncludeDefault:\r
- *\r
- * Provides the default state for XInclude processing\r
- *\r
- * Returns 0 if there is no processing 1 otherwise\r
- */\r
-int\r
-xsltGetXIncludeDefault(void) {\r
-    return(xsltDoXIncludeDefault);\r
-}\r
-\r
-unsigned long xsltDefaultTrace = (unsigned long) XSLT_TRACE_ALL;\r
-\r
-/**\r
- * xsltDebugSetDefaultTrace:\r
- * @val: tracing level mask\r
- *\r
- * Set the default debug tracing level mask\r
- */\r
-void xsltDebugSetDefaultTrace(xsltDebugTraceCodes val) {\r
-       xsltDefaultTrace = val;\r
-}\r
-\r
-/**\r
- * xsltDebugGetDefaultTrace:\r
- *\r
- * Get the current default debug tracing level mask\r
- *\r
- * Returns the current default debug tracing level mask\r
- */\r
-xsltDebugTraceCodes xsltDebugGetDefaultTrace() {\r
-       return xsltDefaultTrace;\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Handling of Transformation Contexts             *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-static xsltTransformCachePtr\r
-xsltTransformCacheCreate(void)\r
-{\r
-    xsltTransformCachePtr ret;\r
-    \r
-    ret = (xsltTransformCachePtr) xmlMalloc(sizeof(xsltTransformCache));\r
-    if (ret == NULL) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-           "xsltTransformCacheCreate : malloc failed\n");\r
-       return(NULL);\r
-    }\r
-    memset(ret, 0, sizeof(xsltTransformCache));\r
-    return(ret);\r
-}\r
-\r
-static void\r
-xsltTransformCacheFree(xsltTransformCachePtr cache)\r
-{    \r
-    if (cache == NULL)\r
-       return;    \r
-    /*\r
-    * Free tree fragments.\r
-    */\r
-    if (cache->RVT) {\r
-       xmlDocPtr tmp, cur = cache->RVT;\r
-       while (cur) {\r
-           tmp = cur;\r
-           cur = (xmlDocPtr) cur->next;\r
-           if (tmp->_private != NULL) {\r
-               /*\r
-               * Tree the document info.\r
-               */\r
-               xsltFreeDocumentKeys((xsltDocumentPtr) tmp->_private);\r
-               xmlFree(tmp->_private);\r
-           }\r
-           xmlFreeDoc(tmp);\r
-       }\r
-    }\r
-    /*\r
-    * Free vars/params.\r
-    */\r
-    if (cache->stackItems) {\r
-       xsltStackElemPtr tmp, cur = cache->stackItems;\r
-       while (cur) {\r
-           tmp = cur;\r
-           cur = cur->next;\r
-           /*\r
-           * REVISIT TODO: Should be call a destruction-function\r
-           * instead?\r
-           */\r
-           xmlFree(tmp);\r
-       }\r
-    }\r
-    xmlFree(cache);\r
-}\r
-\r
-/**\r
- * xsltNewTransformContext:\r
- * @style:  a parsed XSLT stylesheet\r
- * @doc:  the input document\r
- *\r
- * Create a new XSLT TransformContext\r
- *\r
- * Returns the newly allocated xsltTransformContextPtr or NULL in case of error\r
- */\r
-xsltTransformContextPtr\r
-xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) {\r
-    xsltTransformContextPtr cur;\r
-    xsltDocumentPtr docu;\r
-    int i;\r
-\r
-    cur = (xsltTransformContextPtr) xmlMalloc(sizeof(xsltTransformContext));\r
-    if (cur == NULL) {\r
-       xsltTransformError(NULL, NULL, (xmlNodePtr)doc,\r
-               "xsltNewTransformContext : malloc failed\n");\r
-       return(NULL);\r
-    }\r
-    memset(cur, 0, sizeof(xsltTransformContext));\r
-\r
-    cur->cache = xsltTransformCacheCreate();\r
-    if (cur->cache == NULL)\r
-       goto internal_err;\r
-    /*\r
-     * setup of the dictionnary must be done early as some of the\r
-     * processing later like key handling may need it.\r
-     */\r
-    cur->dict = xmlDictCreateSub(style->dict);\r
-    cur->internalized = ((style->internalized) && (cur->dict != NULL));\r
-#ifdef WITH_XSLT_DEBUG\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-            "Creating sub-dictionary from stylesheet for transformation\n");\r
-#endif\r
-\r
-    /*\r
-     * initialize the template stack\r
-     */\r
-    cur->templTab = (xsltTemplatePtr *)\r
-               xmlMalloc(10 * sizeof(xsltTemplatePtr));\r
-    if (cur->templTab == NULL) {\r
-       xsltTransformError(NULL, NULL, (xmlNodePtr) doc,\r
-               "xsltNewTransformContext: out of memory\n");\r
-       goto internal_err;\r
-    }\r
-    cur->templNr = 0;\r
-    cur->templMax = 5;\r
-    cur->templ = NULL;\r
-\r
-    /*\r
-     * initialize the variables stack\r
-     */\r
-    cur->varsTab = (xsltStackElemPtr *)\r
-               xmlMalloc(10 * sizeof(xsltStackElemPtr));\r
-    if (cur->varsTab == NULL) {\r
-        xmlGenericError(xmlGenericErrorContext,\r
-               "xsltNewTransformContext: out of memory\n");\r
-       goto internal_err;\r
-    }\r
-    cur->varsNr = 0;\r
-    cur->varsMax = 10;\r
-    cur->vars = NULL;\r
-    cur->varsBase = 0;\r
-\r
-    /*\r
-     * the profiling stack is not initialized by default\r
-     */\r
-    cur->profTab = NULL;\r
-    cur->profNr = 0;\r
-    cur->profMax = 0;\r
-    cur->prof = 0;\r
-\r
-    cur->style = style;\r
-    xmlXPathInit();\r
-    cur->xpathCtxt = xmlXPathNewContext(doc);\r
-    if (cur->xpathCtxt == NULL) {\r
-       xsltTransformError(NULL, NULL, (xmlNodePtr) doc,\r
-               "xsltNewTransformContext : xmlXPathNewContext failed\n");\r
-       goto internal_err;\r
-    }\r
-    /*\r
-    * Create an XPath cache.\r
-    */\r
-    if (xmlXPathContextSetCache(cur->xpathCtxt, 1, -1, 0) == -1)\r
-       goto internal_err;\r
-    /*\r
-     * Initialize the extras array\r
-     */\r
-    if (style->extrasNr != 0) {\r
-       cur->extrasMax = style->extrasNr + 20;\r
-       cur->extras = (xsltRuntimeExtraPtr) \r
-           xmlMalloc(cur->extrasMax * sizeof(xsltRuntimeExtra));\r
-       if (cur->extras == NULL) {\r
-           xmlGenericError(xmlGenericErrorContext,\r
-                   "xsltNewTransformContext: out of memory\n");\r
-           goto internal_err;\r
-       }\r
-       cur->extrasNr = style->extrasNr;\r
-       for (i = 0;i < cur->extrasMax;i++) {\r
-           cur->extras[i].info = NULL;\r
-           cur->extras[i].deallocate = NULL;\r
-           cur->extras[i].val.ptr = NULL;\r
-       }\r
-    } else {\r
-       cur->extras = NULL;\r
-       cur->extrasNr = 0;\r
-       cur->extrasMax = 0;\r
-    }\r
-\r
-    XSLT_REGISTER_VARIABLE_LOOKUP(cur);\r
-    XSLT_REGISTER_FUNCTION_LOOKUP(cur);\r
-    cur->xpathCtxt->nsHash = style->nsHash;\r
-    /*\r
-     * Initialize the registered external modules\r
-     */\r
-    xsltInitCtxtExts(cur);\r
-    /*\r
-     * Setup document element ordering for later efficiencies\r
-     * (bug 133289)\r
-     */\r
-    if (xslDebugStatus == XSLT_DEBUG_NONE)\r
-        xmlXPathOrderDocElems(doc);\r
-    /*\r
-     * Must set parserOptions before calling xsltNewDocument\r
-     * (bug 164530)\r
-     */\r
-    cur->parserOptions = XSLT_PARSE_OPTIONS;\r
-    docu = xsltNewDocument(cur, doc);\r
-    if (docu == NULL) {\r
-       xsltTransformError(cur, NULL, (xmlNodePtr)doc,\r
-               "xsltNewTransformContext : xsltNewDocument failed\n");\r
-       goto internal_err;\r
-    }\r
-    docu->main = 1;\r
-    cur->document = docu;    \r
-    cur->inst = NULL;\r
-    cur->outputFile = NULL;\r
-    cur->sec = xsltGetDefaultSecurityPrefs();\r
-    cur->debugStatus = xslDebugStatus;\r
-    cur->traceCode = (unsigned long*) &xsltDefaultTrace;\r
-    cur->xinclude = xsltGetXIncludeDefault();\r
-\r
-    return(cur);\r
-\r
-internal_err:\r
-    if (cur != NULL)\r
-       xsltFreeTransformContext(cur);\r
-    return(NULL);\r
-}\r
-\r
-/**\r
- * xsltFreeTransformContext:\r
- * @ctxt:  an XSLT parser context\r
- *\r
- * Free up the memory allocated by @ctxt\r
- */\r
-void\r
-xsltFreeTransformContext(xsltTransformContextPtr ctxt) {\r
-    if (ctxt == NULL)\r
-       return;\r
-\r
-    /*\r
-     * Shutdown the extension modules associated to the stylesheet\r
-     * used if needed.\r
-     */\r
-    xsltShutdownCtxtExts(ctxt);\r
-\r
-    if (ctxt->xpathCtxt != NULL) {\r
-       ctxt->xpathCtxt->nsHash = NULL;\r
-       xmlXPathFreeContext(ctxt->xpathCtxt);\r
-    }\r
-    if (ctxt->templTab != NULL)\r
-       xmlFree(ctxt->templTab);\r
-    if (ctxt->varsTab != NULL)\r
-       xmlFree(ctxt->varsTab);\r
-    if (ctxt->profTab != NULL)\r
-       xmlFree(ctxt->profTab);\r
-    if ((ctxt->extrasNr > 0) && (ctxt->extras != NULL)) {\r
-       int i;\r
-\r
-       for (i = 0;i < ctxt->extrasNr;i++) {\r
-           if ((ctxt->extras[i].deallocate != NULL) &&\r
-               (ctxt->extras[i].info != NULL))\r
-               ctxt->extras[i].deallocate(ctxt->extras[i].info);\r
-       }\r
-       xmlFree(ctxt->extras);\r
-    }\r
-    xsltFreeGlobalVariables(ctxt);\r
-    xsltFreeDocuments(ctxt);\r
-    xsltFreeCtxtExts(ctxt);\r
-    xsltFreeRVTs(ctxt);\r
-    xsltTransformCacheFree(ctxt->cache);\r
-    xmlDictFree(ctxt->dict);\r
-#ifdef WITH_XSLT_DEBUG\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-                     "freeing transformation dictionnary\n");\r
-#endif\r
-    memset(ctxt, -1, sizeof(xsltTransformContext));\r
-    xmlFree(ctxt);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Copy of Nodes in an XSLT fashion                *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-xmlNodePtr xsltCopyTree(xsltTransformContextPtr ctxt,\r
-                        xmlNodePtr node, xmlNodePtr insert, int literal);\r
-\r
-/**\r
- * xsltAddTextString:\r
- * @ctxt:  a XSLT process context\r
- * @target:  the text node where the text will be attached\r
- * @string:  the text string\r
- * @len:  the string length in byte\r
- *\r
- * Extend the current text node with the new string, it handles coalescing\r
- *\r
- * Returns: the text node\r
- */\r
-static xmlNodePtr\r
-xsltAddTextString(xsltTransformContextPtr ctxt, xmlNodePtr target,\r
-                 const xmlChar *string, int len) {\r
-    /*\r
-     * optimization\r
-     */\r
-    if ((len <= 0) || (string == NULL) || (target == NULL))\r
-        return(target);\r
-\r
-    if (ctxt->lasttext == target->content) {\r
-\r
-       if (ctxt->lasttuse + len >= ctxt->lasttsize) {\r
-           xmlChar *newbuf;\r
-           int size;\r
-\r
-           size = ctxt->lasttsize + len + 100;\r
-           size *= 2;\r
-           newbuf = (xmlChar *) xmlRealloc(target->content,size);\r
-           if (newbuf == NULL) {\r
-               xsltTransformError(ctxt, NULL, target,\r
-                "xsltCopyText: text allocation failed\n");\r
-               return(NULL);\r
-           }\r
-           ctxt->lasttsize = size;\r
-           ctxt->lasttext = newbuf;\r
-           target->content = newbuf;\r
-       }\r
-       memcpy(&(target->content[ctxt->lasttuse]), string, len);\r
-       ctxt->lasttuse += len;\r
-       target->content[ctxt->lasttuse] = 0;\r
-    } else {\r
-       xmlNodeAddContent(target, string);\r
-       ctxt->lasttext = target->content;\r
-       len = xmlStrlen(target->content);\r
-       ctxt->lasttsize = len;\r
-       ctxt->lasttuse = len;\r
-    }\r
-    return(target);\r
-}\r
-\r
-/**\r
- * xsltCopyTextString:\r
- * @ctxt:  a XSLT process context\r
- * @target:  the element where the text will be attached\r
- * @string:  the text string\r
- * @noescape:  should disable-escaping be activated for this text node.\r
- *\r
- * Adds @string to a newly created or an existent text node child of\r
- * @target.\r
- *\r
- * Returns: the text node, where the text content of @cur is copied to.\r
- *          NULL in case of API or internal errors.\r
- */\r
-xmlNodePtr\r
-xsltCopyTextString(xsltTransformContextPtr ctxt, xmlNodePtr target,\r
-                  const xmlChar *string, int noescape)\r
-{\r
-    xmlNodePtr copy;\r
-    int len;\r
-\r
-    if (string == NULL)\r
-       return(NULL);\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_COPY_TEXT,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "xsltCopyTextString: copy text %s\n",\r
-                    string));\r
-#endif\r
-\r
-    /*\r
-    * Play save and reset the merging mechanism for every new\r
-    * target node.\r
-    */\r
-    if ((target == NULL) || (target->children == NULL)) {\r
-       ctxt->lasttext = NULL;\r
-    }\r
-\r
-    /* handle coalescing of text nodes here */\r
-    len = xmlStrlen(string);\r
-    if ((ctxt->type == XSLT_OUTPUT_XML) &&\r
-       (ctxt->style->cdataSection != NULL) &&\r
-       (target != NULL) && \r
-       (target->type == XML_ELEMENT_NODE) &&\r
-       (((target->ns == NULL) && \r
-         (xmlHashLookup2(ctxt->style->cdataSection,\r
-                         target->name, NULL) != NULL)) ||\r
-        ((target->ns != NULL) &&\r
-         (xmlHashLookup2(ctxt->style->cdataSection,\r
-                         target->name, target->ns->href) != NULL))))\r
-    {\r
-       /*\r
-       * Process "cdata-section-elements".\r
-       */\r
-       if ((target->last != NULL) &&\r
-           (target->last->type == XML_CDATA_SECTION_NODE))\r
-       {\r
-           return(xsltAddTextString(ctxt, target->last, string, len));\r
-       }\r
-       copy = xmlNewCDataBlock(ctxt->output, string, len);\r
-    } else if (noescape) {\r
-       /*\r
-       * Process "disable-output-escaping".\r
-       */\r
-       if ((target != NULL) && (target->last != NULL) &&\r
-           (target->last->type == XML_TEXT_NODE) &&\r
-           (target->last->name == xmlStringTextNoenc))\r
-       {\r
-           return(xsltAddTextString(ctxt, target->last, string, len));\r
-       }\r
-       copy = xmlNewTextLen(string, len);\r
-       if (copy != NULL)\r
-           copy->name = xmlStringTextNoenc;\r
-    } else {\r
-       /*\r
-       * Default processing.\r
-       */\r
-       if ((target != NULL) && (target->last != NULL) &&\r
-           (target->last->type == XML_TEXT_NODE) &&\r
-           (target->last->name == xmlStringText)) {\r
-           return(xsltAddTextString(ctxt, target->last, string, len));\r
-       }\r
-       copy = xmlNewTextLen(string, len);\r
-    }\r
-    if (copy != NULL) {\r
-       if (target != NULL)\r
-           xmlAddChild(target, copy);\r
-       ctxt->lasttext = copy->content;\r
-       ctxt->lasttsize = len;\r
-       ctxt->lasttuse = len;\r
-    } else {\r
-       xsltTransformError(ctxt, NULL, target,\r
-                        "xsltCopyTextString: text copy failed\n");\r
-       ctxt->lasttext = NULL;\r
-    }\r
-    return(copy);\r
-}\r
-\r
-/**\r
- * xsltCopyText:\r
- * @ctxt:  a XSLT process context\r
- * @target:  the element where the text will be attached\r
- * @cur:  the text or CDATA node\r
- * @interned:  the string is in the target doc dictionnary\r
- *\r
- * Copy the text content of @cur and append it to @target's children.\r
- *\r
- * Returns: the text node, where the text content of @cur is copied to.\r
- *          NULL in case of API or internal errors.\r
- */\r
-static xmlNodePtr\r
-xsltCopyText(xsltTransformContextPtr ctxt, xmlNodePtr target,\r
-            xmlNodePtr cur, int interned)\r
-{\r
-    xmlNodePtr copy;\r
-\r
-    if ((cur->type != XML_TEXT_NODE) &&\r
-       (cur->type != XML_CDATA_SECTION_NODE))\r
-       return(NULL);\r
-    if (cur->content == NULL) \r
-       return(NULL);\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    if (cur->type == XML_CDATA_SECTION_NODE) {\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_COPY_TEXT,xsltGenericDebug(xsltGenericDebugContext,\r
-                        "xsltCopyText: copy CDATA text %s\n",\r
-                        cur->content));\r
-    } else if (cur->name == xmlStringTextNoenc) {\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_COPY_TEXT,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "xsltCopyText: copy unescaped text %s\n",\r
-                        cur->content));\r
-    } else {\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_COPY_TEXT,xsltGenericDebug(xsltGenericDebugContext,\r
-                        "xsltCopyText: copy text %s\n",\r
-                        cur->content));\r
-    }\r
-#endif\r
-\r
-    /*\r
-    * Play save and reset the merging mechanism for every new\r
-    * target node.\r
-    */\r
-    if ((target == NULL) || (target->children == NULL)) {\r
-       ctxt->lasttext = NULL;\r
-    }\r
-\r
-    if ((ctxt->style->cdataSection != NULL) &&\r
-       (ctxt->type == XSLT_OUTPUT_XML) &&      \r
-       (target != NULL) &&\r
-       (target->type == XML_ELEMENT_NODE) &&\r
-       (((target->ns == NULL) && \r
-         (xmlHashLookup2(ctxt->style->cdataSection,\r
-                         target->name, NULL) != NULL)) ||\r
-        ((target->ns != NULL) &&\r
-         (xmlHashLookup2(ctxt->style->cdataSection,\r
-                         target->name, target->ns->href) != NULL))))\r
-    {\r
-       /*\r
-       * Process "cdata-section-elements".\r
-       */\r
-       /* \r
-       * OPTIMIZE TODO: xsltCopyText() is also used for attribute content.     \r
-       */\r
-       /*\r
-       * TODO: Since this doesn't merge adjacent CDATA-section nodes,\r
-       * we'll get: <![CDATA[x]]><!CDATA[y]]>.\r
-       * TODO: Reported in #321505.\r
-       */\r
-       if ((target->last != NULL) &&\r
-            (target->last->type == XML_CDATA_SECTION_NODE))\r
-       {\r
-           /*\r
-           * Append to existing CDATA-section node.\r
-           */\r
-           copy = xsltAddTextString(ctxt, target->last, cur->content,\r
-               xmlStrlen(cur->content));\r
-           goto exit;\r
-       } else {\r
-           unsigned int len;\r
-\r
-           len = xmlStrlen(cur->content);          \r
-           copy = xmlNewCDataBlock(ctxt->output, cur->content, len);\r
-           if (copy == NULL)\r
-               goto exit;\r
-           ctxt->lasttext = copy->content;\r
-           ctxt->lasttsize = len;\r
-           ctxt->lasttuse = len;\r
-       }\r
-    } else if ((target != NULL) &&\r
-       (target->last != NULL) &&\r
-       /* both escaped or both non-escaped text-nodes */\r
-       (((target->last->type == XML_TEXT_NODE) &&\r
-       (target->last->name == cur->name)) ||\r
-        /* non-escaped text nodes and CDATA-section nodes */\r
-       (((target->last->type == XML_CDATA_SECTION_NODE) &&\r
-       (cur->name == xmlStringTextNoenc)))))\r
-    {\r
-       /*\r
-        * we are appending to an existing text node\r
-        */\r
-       copy = xsltAddTextString(ctxt, target->last, cur->content,\r
-           xmlStrlen(cur->content));\r
-       goto exit;\r
-    } else if ((interned) && (target != NULL) &&\r
-       (target->doc != NULL) &&\r
-       (target->doc->dict == ctxt->dict))\r
-    {        \r
-       /*\r
-       * TODO: DO we want to use this also for "text" output?\r
-       */\r
-        copy = xmlNewTextLen(NULL, 0);\r
-       if (copy == NULL)\r
-           goto exit;  \r
-       if (cur->name == xmlStringTextNoenc)\r
-           copy->name = xmlStringTextNoenc;\r
-       \r
-       /*\r
-        * Must confirm that content is in dict (bug 302821)\r
-        * TODO: This check should be not needed for text coming\r
-        * from the stylesheets \r
-        */\r
-       if (xmlDictOwns(ctxt->dict, cur->content))\r
-           copy->content = cur->content;\r
-       else {\r
-           if ((copy->content = xmlStrdup(cur->content)) == NULL)\r
-               return NULL;\r
-       }\r
-    } else {\r
-        /*\r
-        * normal processing. keep counters to extend the text node\r
-        * in xsltAddTextString if needed.\r
-        */\r
-        unsigned int len;\r
-\r
-       len = xmlStrlen(cur->content);\r
-       copy = xmlNewTextLen(cur->content, len);\r
-       if (copy == NULL)\r
-           goto exit;\r
-       if (cur->name == xmlStringTextNoenc)\r
-           copy->name = xmlStringTextNoenc;\r
-       ctxt->lasttext = copy->content;\r
-       ctxt->lasttsize = len;\r
-       ctxt->lasttuse = len;\r
-    }\r
-    if (copy != NULL) {\r
-       if (target != NULL) {\r
-           copy->doc = target->doc;\r
-           /*\r
-           * MAYBE TODO: Maybe we should reset the ctxt->lasttext here\r
-           *  to ensure that the optimized text-merging mechanism\r
-           *  won't interfere with normal node-merging in any case.\r
-           */\r
-           xmlAddChild(target, copy);\r
-       }\r
-    } else {\r
-       xsltTransformError(ctxt, NULL, target,\r
-                        "xsltCopyText: text copy failed\n");\r
-    }\r
-\r
-exit:\r
-    if ((copy == NULL) || (copy->content == NULL)) {\r
-       xsltTransformError(ctxt, NULL, target,\r
-           "Internal error in xsltCopyText(): "\r
-           "Failed to copy the string.\n");\r
-       ctxt->state = XSLT_STATE_STOPPED;\r
-    }\r
-    return(copy);\r
-}\r
-\r
-/**\r
- * xsltShallowCopyAttr:\r
- * @ctxt:  a XSLT process context\r
- * @invocNode: responsible node in the stylesheet; used for error reports\r
- * @target:  the element where the attribute will be grafted\r
- * @attr: the attribute to be copied\r
- *\r
- * Do a copy of an attribute.\r
- * Called by:\r
- *  - xsltCopyTreeInternal()\r
- *  - xsltCopyOf()\r
- *  - xsltCopy()\r
- *\r
- * Returns: a new xmlAttrPtr, or NULL in case of error.\r
- */\r
-static xmlAttrPtr\r
-xsltShallowCopyAttr(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,\r
-            xmlNodePtr target, xmlAttrPtr attr)\r
-{\r
-    xmlAttrPtr copy;\r
-    xmlChar *value;\r
-\r
-    if (attr == NULL)\r
-       return(NULL);\r
-\r
-    if (target->type != XML_ELEMENT_NODE) {\r
-       xsltTransformError(ctxt, NULL, invocNode,\r
-           "Cannot add an attribute node to a non-element node.\n");\r
-       return(NULL);\r
-    }\r
-    \r
-    if (target->children != NULL) {\r
-       xsltTransformError(ctxt, NULL, invocNode,\r
-           "Attribute nodes must be added before "\r
-           "any child nodes to an element.\n");\r
-       return(NULL);\r
-    }\r
-\r
-    value = xmlNodeListGetString(attr->doc, attr->children, 1);\r
-    if (attr->ns != NULL) {\r
-       xmlNsPtr ns; \r
-\r
-       ns = xsltGetSpecialNamespace(ctxt, invocNode,\r
-           attr->ns->href, attr->ns->prefix, target);\r
-       if (ns == NULL) {\r
-           xsltTransformError(ctxt, NULL, invocNode,\r
-               "Namespace fixup error: Failed to acquire an in-scope "\r
-               "namespace binding of the copied attribute '{%s}%s'.\n",\r
-               attr->ns->href, attr->name);\r
-           /*\r
-           * TODO: Should we just stop here?\r
-           */\r
-       }\r
-       /*\r
-       * Note that xmlSetNsProp() will take care of duplicates\r
-       * and assigns the new namespace even to a duplicate.\r
-       */\r
-       copy = xmlSetNsProp(target, ns, attr->name, value);\r
-    } else {\r
-       copy = xmlSetNsProp(target, NULL, attr->name, value);\r
-    }\r
-    if (value != NULL)\r
-       xmlFree(value);\r
-\r
-    if (copy == NULL)\r
-       return(NULL);\r
-\r
-#if 0\r
-    /*\r
-    * NOTE: This was optimized according to bug #342695.\r
-    * TODO: Can this further be optimized, if source and target\r
-    *  share the same dict and attr->children is just 1 text node\r
-    *  which is in the dict? How probable is such a case?\r
-    */\r
-    /*\r
-    * TODO: Do we need to create an empty text node if the value\r
-    *  is the empty string?\r
-    */\r
-    value = xmlNodeListGetString(attr->doc, attr->children, 1);\r
-    if (value != NULL) {\r
-       txtNode = xmlNewDocText(target->doc, NULL);\r
-       if (txtNode == NULL)\r
-           return(NULL);\r
-       if ((target->doc != NULL) &&\r
-           (target->doc->dict != NULL))\r
-       {\r
-           txtNode->content =\r
-               (xmlChar *) xmlDictLookup(target->doc->dict,\r
-                   BAD_CAST value, -1);\r
-           xmlFree(value);\r
-       } else\r
-           txtNode->content = value;\r
-       copy->children = txtNode;\r
-    }\r
-#endif\r
-\r
-    return(copy);\r
-}\r
-\r
-/**\r
- * xsltCopyAttrListNoOverwrite:\r
- * @ctxt:  a XSLT process context\r
- * @invocNode: responsible node in the stylesheet; used for error reports\r
- * @target:  the element where the new attributes will be grafted\r
- * @attr:  the first attribute in the list to be copied\r
- *\r
- * Copies a list of attribute nodes, starting with @attr, over to the\r
- * @target element node.\r
- *\r
- * Called by:\r
- *  - xsltCopyTreeInternal()\r
- *\r
- * Returns 0 on success and -1 on errors and internal errors.\r
- */\r
-static int\r
-xsltCopyAttrListNoOverwrite(xsltTransformContextPtr ctxt,\r
-                           xmlNodePtr invocNode,\r
-                           xmlNodePtr target, xmlAttrPtr attr)\r
-{\r
-    xmlAttrPtr last = NULL, copy;\r
-    xmlNsPtr origNs = NULL, copyNs = NULL;\r
-    xmlChar *value = NULL;\r
-\r
-    /*\r
-    * Don't use xmlCopyProp() here, since it will try to\r
-    * reconciliate namespaces.\r
-    */\r
-    while (attr != NULL) {\r
-       /*\r
-       * Find a namespace node in the tree of @target.\r
-       * Avoid searching for the same ns.\r
-       */\r
-       if (attr->ns != origNs) {\r
-           origNs = attr->ns;\r
-           if (attr->ns != NULL) {\r
-               copyNs = xsltGetSpecialNamespace(ctxt, invocNode,\r
-                   attr->ns->href, attr->ns->prefix, target);\r
-               if (copyNs == NULL)\r
-                   return(-1);\r
-           } else\r
-               copyNs = NULL;\r
-       }\r
-       if (attr->children)\r
-           value = xmlNodeListGetString(attr->doc, attr->children, 1);\r
-       /*\r
-       * REVISIT: I think xmlNewDocProp() is the only attr function\r
-       * which does not eval if the attr is of type ID. This is good,\r
-       * since we don't need this.\r
-       */\r
-       copy = xmlNewDocProp(target->doc, attr->name, BAD_CAST value);\r
-       if (copy == NULL)\r
-           return(-1);\r
-       copy->parent = target;\r
-       copy->ns = copyNs;\r
-       \r
-       if (last == NULL) {\r
-           target->properties = copy;\r
-           last = copy;\r
-       } else {\r
-           last->next = copy;\r
-           copy->prev = last;\r
-           last = copy;\r
-       }\r
-       /*\r
-       * OPTIMIZE TODO: How to avoid this intermediate string?\r
-       */\r
-       if (value != NULL) {\r
-           xmlFree(value);\r
-           value = NULL;\r
-       }\r
-       attr = attr->next;\r
-    }    \r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltShallowCopyElem:\r
- * @ctxt:  the XSLT process context\r
- * @node:  the element node in the source tree\r
- *         or the Literal Result Element\r
- * @insert:  the parent in the result tree\r
- * @isLRE: if @node is a Literal Result Element\r
- *\r
- * Make a copy of the element node @node\r
- * and insert it as last child of @insert.\r
- *\r
- * URGENT TODO: The problem with this one (for the non-refactored code)\r
- * is that it is used for both, Literal Result Elements *and*\r
- * copying input nodes.\r
- *\r
- * BIG NOTE: This is only called for XML_ELEMENT_NODEs.\r
- *\r
- * Called from:\r
- *   xsltApplySequenceConstructor()\r
- *    (for Literal Result Elements - which is a problem)\r
- *   xsltCopy() (for shallow-copying elements via xsl:copy)\r
- *\r
- * Returns a pointer to the new node, or NULL in case of error\r
- */\r
-static xmlNodePtr\r
-xsltShallowCopyElem(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                   xmlNodePtr insert, int isLRE)\r
-{\r
-    xmlNodePtr copy;\r
-\r
-    if ((node->type == XML_DTD_NODE) || (insert == NULL))\r
-       return(NULL);\r
-    if ((node->type == XML_TEXT_NODE) ||\r
-       (node->type == XML_CDATA_SECTION_NODE))\r
-       return(xsltCopyText(ctxt, insert, node, 0));\r
-\r
-    copy = xmlDocCopyNode(node, insert->doc, 0);\r
-    if (copy != NULL) {\r
-       copy->doc = ctxt->output;\r
-       xmlAddChild(insert, copy);\r
-\r
-       if (node->type == XML_ELEMENT_NODE) {\r
-           /*\r
-            * Add namespaces as they are needed\r
-            */\r
-           if (node->nsDef != NULL) {\r
-               /*\r
-               * TODO: Remove the LRE case in the refactored code\r
-               * gets enabled.\r
-               */\r
-               if (isLRE)\r
-                   xsltCopyNamespaceList(ctxt, copy, node->nsDef);\r
-               else\r
-                   xsltCopyNamespaceListInternal(copy, node->nsDef);\r
-           }\r
-\r
-           /*\r
-           * URGENT TODO: The problem with this is that it does not\r
-           *  copy over all namespace nodes in scope.\r
-           *  The damn thing about this is, that we would need to\r
-           *  use the xmlGetNsList(), for every single node; this is\r
-           *  also done in xsltCopyTreeInternal(), but only for the top node.\r
-           */\r
-           if (node->ns != NULL) {\r
-               if (isLRE) {\r
-                   /*\r
-                   * REVISIT TODO: Since the non-refactored code still does\r
-                   *  ns-aliasing, we need to call xsltGetNamespace() here.\r
-                   *  Remove this when ready.\r
-                   */\r
-                   copy->ns = xsltGetNamespace(ctxt, node, node->ns, copy);\r
-               } else {\r
-                   copy->ns = xsltGetSpecialNamespace(ctxt,\r
-                       node, node->ns->href, node->ns->prefix, copy);\r
-                   \r
-               }\r
-           } else if ((insert->type == XML_ELEMENT_NODE) &&\r
-                      (insert->ns != NULL))\r
-           {\r
-               /*\r
-               * "Undeclare" the default namespace.\r
-               */\r
-               xsltGetSpecialNamespace(ctxt, node, NULL, NULL, copy);\r
-           }\r
-       }\r
-    } else {\r
-       xsltTransformError(ctxt, NULL, node,\r
-               "xsltShallowCopyElem: copy %s failed\n", node->name);\r
-    }\r
-    return(copy);\r
-}\r
-\r
-/**\r
- * xsltCopyTreeList:\r
- * @ctxt:  a XSLT process context\r
- * @invocNode: responsible node in the stylesheet; used for error reports\r
- * @list:  the list of element nodes in the source tree.\r
- * @insert:  the parent in the result tree.\r
- * @literal:  is this a literal result element list\r
- *\r
- * Make a copy of the full list of tree @list\r
- * and insert it as last children of @insert\r
- *\r
- * NOTE: Not to be used for Literal Result Elements.\r
- *\r
- * Used by:\r
- *  - xsltCopyOf()\r
- *\r
- * Returns a pointer to the new list, or NULL in case of error\r
- */\r
-static xmlNodePtr\r
-xsltCopyTreeList(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,\r
-                xmlNodePtr list,\r
-                xmlNodePtr insert, int isLRE, int topElemVisited)\r
-{\r
-    xmlNodePtr copy, ret = NULL;\r
-\r
-    while (list != NULL) {\r
-       copy = xsltCopyTreeInternal(ctxt, invocNode,\r
-           list, insert, isLRE, topElemVisited);\r
-       if (copy != NULL) {\r
-           if (ret == NULL) {\r
-               ret = copy;\r
-           }\r
-       }\r
-       list = list->next;\r
-    }\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltCopyNamespaceListInternal:\r
- * @node:  the target node\r
- * @cur:  the first namespace\r
- *\r
- * Do a copy of a namespace list. If @node is non-NULL the\r
- * new namespaces are added automatically.\r
- * Called by:\r
- *   xsltCopyTreeInternal()\r
- *\r
- * QUESTION: What is the exact difference between this function\r
- *  and xsltCopyNamespaceList() in "namespaces.c"?\r
- * ANSWER: xsltCopyNamespaceList() tries to apply ns-aliases.\r
- *\r
- * Returns: a new xmlNsPtr, or NULL in case of error.\r
- */\r
-static xmlNsPtr\r
-xsltCopyNamespaceListInternal(xmlNodePtr elem, xmlNsPtr ns) {\r
-    xmlNsPtr ret = NULL;\r
-    xmlNsPtr p = NULL, q, luNs;\r
-\r
-    if (ns == NULL)\r
-       return(NULL);\r
-    /*\r
-     * One can add namespaces only on element nodes\r
-     */\r
-    if ((elem != NULL) && (elem->type != XML_ELEMENT_NODE))\r
-       elem = NULL;\r
-\r
-    do {\r
-       if (ns->type != XML_NAMESPACE_DECL)\r
-           break;\r
-       /*\r
-        * Avoid duplicating namespace declarations on the tree.\r
-        */\r
-       if (elem != NULL) {         \r
-           if ((elem->ns != NULL) &&\r
-               xmlStrEqual(elem->ns->prefix, ns->prefix) &&\r
-               xmlStrEqual(elem->ns->href, ns->href))\r
-           {\r
-               ns = ns->next;\r
-               continue;\r
-           }\r
-           luNs = xmlSearchNs(elem->doc, elem, ns->prefix);\r
-           if ((luNs != NULL) && (xmlStrEqual(luNs->href, ns->href)))\r
-           {\r
-               ns = ns->next;\r
-               continue;\r
-           }\r
-       }               \r
-       q = xmlNewNs(elem, ns->href, ns->prefix);\r
-       if (p == NULL) {\r
-           ret = p = q;\r
-       } else if (q != NULL) {\r
-           p->next = q;\r
-           p = q;\r
-       }\r
-       ns = ns->next;  \r
-    } while (ns != NULL);\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltShallowCopyNsNode:\r
- * @ctxt:  the XSLT transformation context\r
- * @invocNode: responsible node in the stylesheet; used for error reports\r
- * @insert:  the target element node in the result tree\r
- * @ns: the namespace node\r
- *\r
- * This is used for copying ns-nodes with xsl:copy-of and xsl:copy.\r
- *\r
- * Returns a new/existing ns-node, or NULL.\r
- */\r
-static int\r
-xsltShallowCopyNsNode(xsltTransformContextPtr ctxt,\r
-                     xmlNodePtr invocNode,\r
-                     xmlNodePtr insert,\r
-                     xmlNsPtr ns)\r
-{\r
-    xmlNsPtr tmpns;\r
-\r
-    if ((insert == NULL) || (insert->type != XML_ELEMENT_NODE))\r
-       return(-1);\r
-    \r
-    if (insert->children != NULL) {\r
-       xsltTransformError(ctxt, NULL, invocNode,\r
-           "Namespace nodes must be added before "\r
-           "any child nodes are added to an element.\n");\r
-       return(1);\r
-    }\r
-    /*    \r
-    *\r
-    * BIG NOTE: Xalan-J simply overwrites any ns-decls with\r
-    * an equal prefix. We definitively won't do that.\r
-    *\r
-    * MSXML 4.0 and the .NET ignores ns-decls for which an\r
-    * equal prefix is already in use.\r
-    *\r
-    * Saxon raises an error like:\r
-    * "net.sf.saxon.xpath.DynamicError: Cannot create two namespace\r
-    * nodes with the same name".\r
-    *\r
-    * NOTE: We'll currently follow MSXML here.\r
-    * REVISIT TODO: Check if it's better to follow Saxon here.\r
-    */\r
-    if (ns->prefix == NULL) {\r
-       /*\r
-       * If we are adding ns-nodes to an element using e.g.\r
-       * <xsl:copy-of select="/foo/namespace::*">, then we need\r
-       * to ensure that we don't incorrectly declare a default\r
-       * namespace on an element in no namespace, which otherwise\r
-       * would move the element incorrectly into a namespace, if\r
-       * the node tree is serialized.\r
-       */\r
-       if (insert->ns == NULL)\r
-           goto occupied;\r
-    } else if ((ns->prefix[0] == 'x') &&\r
-       xmlStrEqual(ns->prefix, BAD_CAST "xml"))\r
-    {\r
-       return(0);\r
-    }\r
-\r
-    if (insert->nsDef != NULL) {\r
-       tmpns = insert->nsDef;\r
-       do {\r
-           if ((tmpns->prefix == NULL) == (ns->prefix == NULL)) {              \r
-               if ((tmpns->prefix == ns->prefix) ||\r
-                   xmlStrEqual(tmpns->prefix, ns->prefix))\r
-               {\r
-                   /*\r
-                   * Same prefix.\r
-                   */\r
-                   if (xmlStrEqual(tmpns->href, ns->href))\r
-                       return(0);\r
-                   goto occupied;\r
-               }\r
-           }\r
-           tmpns = tmpns->next;\r
-       } while (tmpns != NULL);\r
-    }\r
-    tmpns = xmlSearchNs(insert->doc, insert, ns->prefix);\r
-    if ((tmpns != NULL) && xmlStrEqual(tmpns->href, ns->href))\r
-       return(0);\r
-    /*\r
-    * Declare a new namespace.\r
-    * TODO: The problem (wrt efficiency) with this xmlNewNs() is\r
-    * that it will again search the already declared namespaces\r
-    * for a duplicate :-/\r
-    */\r
-    xmlNewNs(insert, ns->href, ns->prefix);\r
-    return(0);    \r
-\r
-occupied:\r
-    /*\r
-    * TODO: We could as well raise an error here (like Saxon does),\r
-    * or at least generate a warning.\r
-    */\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltCopyTreeInternal:\r
- * @ctxt:  the XSLT transformation context\r
- * @invocNode: responsible node in the stylesheet; used for error reports\r
- * @node:  the element node in the source tree\r
- * @insert:  the parent in the result tree\r
- * @isLRE:  indicates if @node is a Literal Result Element\r
- * @topElemVisited: indicates if a top-most element was already processed\r
- *\r
- * Make a copy of the full tree under the element node @node\r
- * and insert it as last child of @insert\r
- *\r
- * NOTE: Not to be used for Literal Result Elements.\r
- *\r
- * Used by:\r
- *  - xsltCopyOf()\r
- *\r
- * Returns a pointer to the new tree, or NULL in case of error\r
- */\r
-static xmlNodePtr\r
-xsltCopyTreeInternal(xsltTransformContextPtr ctxt,\r
-                    xmlNodePtr invocNode,\r
-                    xmlNodePtr node,\r
-                    xmlNodePtr insert, int isLRE, int topElemVisited)\r
-{\r
-    xmlNodePtr copy;\r
-\r
-    if (node == NULL)\r
-       return(NULL);\r
-    switch (node->type) {\r
-        case XML_ELEMENT_NODE:\r
-        case XML_ENTITY_REF_NODE:\r
-        case XML_ENTITY_NODE:\r
-        case XML_PI_NODE:\r
-        case XML_COMMENT_NODE:\r
-        case XML_DOCUMENT_NODE:\r
-        case XML_HTML_DOCUMENT_NODE:\r
-#ifdef LIBXML_DOCB_ENABLED\r
-        case XML_DOCB_DOCUMENT_NODE:\r
-#endif\r
-           break;\r
-        case XML_TEXT_NODE: {\r
-           int noenc = (node->name == xmlStringTextNoenc);\r
-           return(xsltCopyTextString(ctxt, insert, node->content, noenc));\r
-           }\r
-        case XML_CDATA_SECTION_NODE:\r
-           return(xsltCopyTextString(ctxt, insert, node->content, 0));\r
-        case XML_ATTRIBUTE_NODE:\r
-           return((xmlNodePtr)\r
-               xsltShallowCopyAttr(ctxt, invocNode, insert, (xmlAttrPtr) node));\r
-        case XML_NAMESPACE_DECL:\r
-           return((xmlNodePtr) xsltShallowCopyNsNode(ctxt, invocNode,\r
-               insert, (xmlNsPtr) node));\r
-           \r
-        case XML_DOCUMENT_TYPE_NODE:\r
-        case XML_DOCUMENT_FRAG_NODE:\r
-        case XML_NOTATION_NODE:\r
-        case XML_DTD_NODE:\r
-        case XML_ELEMENT_DECL:\r
-        case XML_ATTRIBUTE_DECL:\r
-        case XML_ENTITY_DECL:\r
-        case XML_XINCLUDE_START:\r
-        case XML_XINCLUDE_END:\r
-            return(NULL);\r
-    }    \r
-    if (XSLT_IS_RES_TREE_FRAG(node)) {\r
-       if (node->children != NULL)\r
-           copy = xsltCopyTreeList(ctxt, invocNode,\r
-               node->children, insert, 0, 0);\r
-       else\r
-           copy = NULL;\r
-       return(copy);\r
-    }\r
-    copy = xmlDocCopyNode(node, insert->doc, 0);\r
-    if (copy != NULL) {\r
-       copy->doc = ctxt->output;\r
-       xmlAddChild(insert, copy);\r
-       /*\r
-        * The node may have been coalesced into another text node.\r
-        */\r
-       if (insert->last != copy)\r
-           return(insert->last);\r
-       copy->next = NULL;\r
-\r
-       if (node->type == XML_ELEMENT_NODE) {       \r
-           /*\r
-           * Copy in-scope namespace nodes.\r
-           *\r
-           * REVISIT: Since we try to reuse existing in-scope ns-decls by\r
-           *  using xmlSearchNsByHref(), this will eventually change\r
-           *  the prefix of an original ns-binding; thus it might\r
-           *  break QNames in element/attribute content.\r
-           * OPTIMIZE TODO: If we had a xmlNsPtr * on the transformation\r
-           *  context, plus a ns-lookup function, which writes directly\r
-           *  to a given list, then we wouldn't need to create/free the\r
-           *  nsList every time.\r
-           */\r
-           if ((topElemVisited == 0) &&\r
-               (node->parent != NULL) &&\r
-               (node->parent->type != XML_DOCUMENT_NODE) &&\r
-               (node->parent->type != XML_HTML_DOCUMENT_NODE))\r
-           {\r
-               xmlNsPtr *nsList, *curns, ns;\r
-               \r
-               /*\r
-               * If this is a top-most element in a tree to be\r
-               * copied, then we need to ensure that all in-scope\r
-               * namespaces are copied over. For nodes deeper in the\r
-               * tree, it is sufficient to reconcile only the ns-decls\r
-               * (node->nsDef entries).\r
-               */\r
-               \r
-               nsList = xmlGetNsList(node->doc, node);\r
-               if (nsList != NULL) {\r
-                   curns = nsList;\r
-                   do {\r
-                       /*\r
-                       * Search by prefix first in order to break as less\r
-                       * QNames in element/attribute content as possible.\r
-                       */\r
-                       ns = xmlSearchNs(insert->doc, insert,\r
-                           (*curns)->prefix);\r
-                       \r
-                       if ((ns == NULL) ||\r
-                           (! xmlStrEqual(ns->href, (*curns)->href)))\r
-                       {\r
-                           ns = NULL;\r
-                           /*\r
-                           * Search by namespace name.\r
-                           * REVISIT TODO: Currently disabled.\r
-                           */\r
-#if 0\r
-                           ns = xmlSearchNsByHref(insert->doc,\r
-                               insert, (*curns)->href);\r
-#endif\r
-                       }\r
-                       if (ns == NULL) {\r
-                           /*\r
-                           * Declare a new namespace on the copied element.\r
-                           */\r
-                           ns = xmlNewNs(copy, (*curns)->href,\r
-                               (*curns)->prefix);\r
-                           /* TODO: Handle errors */\r
-                       }\r
-                       if (node->ns == *curns) {\r
-                           /*\r
-                           * If this was the original's namespace then set\r
-                           * the generated counterpart on the copy.\r
-                           */\r
-                           copy->ns = ns;\r
-                       }\r
-                       curns++;\r
-                   } while (*curns != NULL);\r
-                   xmlFree(nsList);\r
-               }\r
-           } else if (node->nsDef != NULL) {           \r
-               /*\r
-               * Copy over all namespace declaration attributes.               \r
-               */\r
-               if (node->nsDef != NULL) {\r
-                   if (isLRE)\r
-                       xsltCopyNamespaceList(ctxt, copy, node->nsDef);\r
-                   else\r
-                       xsltCopyNamespaceListInternal(copy, node->nsDef);\r
-               }\r
-           }\r
-           /*\r
-           * Set the namespace.\r
-           */\r
-           if (node->ns != NULL) {\r
-               if (copy->ns == NULL) {\r
-                   /*\r
-                   * This will map copy->ns to one of the newly created\r
-                   * in-scope ns-decls, OR create a new ns-decl on @copy.\r
-                   */\r
-                   copy->ns = xsltGetSpecialNamespace(ctxt, invocNode,\r
-                       node->ns->href, node->ns->prefix, copy);\r
-               }\r
-           } else if ((insert->type == XML_ELEMENT_NODE) &&\r
-               (insert->ns != NULL))\r
-           {\r
-               /*\r
-               * "Undeclare" the default namespace on @copy with xmlns="".\r
-               */\r
-               xsltGetSpecialNamespace(ctxt, invocNode, NULL, NULL, copy);\r
-           }\r
-           /*\r
-           * Copy attribute nodes.\r
-           */\r
-           if (node->properties != NULL) {\r
-               xsltCopyAttrListNoOverwrite(ctxt, invocNode,\r
-                   copy, node->properties);\r
-           }\r
-           if (topElemVisited == 0)\r
-               topElemVisited = 1;\r
-       }\r
-       /*\r
-       * Copy the subtree.\r
-       */\r
-       if (node->children != NULL) {\r
-           xsltCopyTreeList(ctxt, invocNode,\r
-               node->children, copy, isLRE, topElemVisited);\r
-       }\r
-    } else {\r
-       xsltTransformError(ctxt, NULL, invocNode,\r
-           "xsltCopyTreeInternal: Copying of '%s' failed.\n", node->name);\r
-    }\r
-    return(copy);\r
-}\r
-\r
-/**\r
- * xsltCopyTree:\r
- * @ctxt:  the XSLT transformation context\r
- * @node:  the element node in the source tree\r
- * @insert:  the parent in the result tree\r
- * @literal:  indicates if @node is a Literal Result Element\r
- *\r
- * Make a copy of the full tree under the element node @node\r
- * and insert it as last child of @insert\r
- * For literal result element, some of the namespaces may not be copied\r
- * over according to section 7.1.\r
- * TODO: Why is this a public function?\r
- *\r
- * Returns a pointer to the new tree, or NULL in case of error\r
- */\r
-xmlNodePtr\r
-xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-            xmlNodePtr insert, int literal)\r
-{\r
-    return(xsltCopyTreeInternal(ctxt, node, node, insert, literal, 0));\r
-    \r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Error/fallback processing                               *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltApplyFallbacks:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the node in the source tree.\r
- * @inst:  the node generating the error\r
- *\r
- * Process possible xsl:fallback nodes present under @inst\r
- *\r
- * Returns the number of xsl:fallback element found and processed\r
- */\r
-static int\r
-xsltApplyFallbacks(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                  xmlNodePtr inst) {\r
-\r
-    xmlNodePtr child;\r
-    int ret = 0;\r
-    \r
-    if ((ctxt == NULL) || (node == NULL) || (inst == NULL) ||\r
-       (inst->children == NULL))\r
-       return(0);\r
-\r
-    child = inst->children;\r
-    while (child != NULL) {\r
-        if ((IS_XSLT_ELEM(child)) &&\r
-            (xmlStrEqual(child->name, BAD_CAST "fallback"))) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-                            "applying xsl:fallback\n");\r
-#endif\r
-           ret++;\r
-           xsltApplySequenceConstructor(ctxt, node, child->children,\r
-               NULL);\r
-       }\r
-       child = child->next;\r
-    }\r
-    return(ret);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Default processing                              *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-void xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                       xsltStackElemPtr params);\r
-/**\r
- * xsltDefaultProcessOneNode:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the node in the source tree.\r
- * @params: extra parameters passed to the template if any\r
- *\r
- * Process the source node with the default built-in template rule:\r
- * <xsl:template match="*|/">\r
- *   <xsl:apply-templates/>\r
- * </xsl:template>\r
- *\r
- * and\r
- *\r
- * <xsl:template match="text()|@*">\r
- *   <xsl:value-of select="."/>\r
- * </xsl:template>\r
- *\r
- * Note also that namespace declarations are copied directly:\r
- *\r
- * the built-in template rule is the only template rule that is applied\r
- * for namespace nodes.\r
- */\r
-static void\r
-xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                         xsltStackElemPtr params) {\r
-    xmlNodePtr copy;\r
-    xmlNodePtr delete = NULL, cur;\r
-    int nbchild = 0, oldSize;\r
-    int childno = 0, oldPos;\r
-    xsltTemplatePtr template;\r
-\r
-    CHECK_STOPPED;\r
-    /*\r
-     * Handling of leaves\r
-     */\r
-    switch (node->type) {\r
-       case XML_DOCUMENT_NODE:\r
-       case XML_HTML_DOCUMENT_NODE:\r
-       case XML_ELEMENT_NODE:\r
-           break;\r
-       case XML_CDATA_SECTION_NODE:\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltDefaultProcessOneNode: copy CDATA %s\n",\r
-               node->content));\r
-#endif\r
-           copy = xsltCopyText(ctxt, ctxt->insert, node, 0);\r
-           if (copy == NULL) {\r
-               xsltTransformError(ctxt, NULL, node,\r
-                "xsltDefaultProcessOneNode: cdata copy failed\n");\r
-           }\r
-           return;\r
-       case XML_TEXT_NODE:\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-           if (node->content == NULL) {\r
-               XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-                "xsltDefaultProcessOneNode: copy empty text\n"));\r
-           } else {\r
-               XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-                "xsltDefaultProcessOneNode: copy text %s\n",\r
-                       node->content));\r
-            }\r
-#endif\r
-           copy = xsltCopyText(ctxt, ctxt->insert, node, 0);\r
-           if (copy == NULL) {\r
-               xsltTransformError(ctxt, NULL, node,\r
-                "xsltDefaultProcessOneNode: text copy failed\n");\r
-           }\r
-           return;\r
-       case XML_ATTRIBUTE_NODE:\r
-           cur = node->children;\r
-           while ((cur != NULL) && (cur->type != XML_TEXT_NODE))\r
-               cur = cur->next;\r
-           if (cur == NULL) {\r
-               xsltTransformError(ctxt, NULL, node,\r
-                "xsltDefaultProcessOneNode: no text for attribute\n");\r
-           } else {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               if (cur->content == NULL) {\r
-                   XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "xsltDefaultProcessOneNode: copy empty text\n"));\r
-               } else {\r
-                   XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "xsltDefaultProcessOneNode: copy text %s\n",\r
-                       cur->content));\r
-                }\r
-#endif\r
-               copy = xsltCopyText(ctxt, ctxt->insert, cur, 0);\r
-               if (copy == NULL) {\r
-                   xsltTransformError(ctxt, NULL, node,\r
-                    "xsltDefaultProcessOneNode: text copy failed\n");\r
-               }\r
-           }\r
-           return;\r
-       default:\r
-           return;\r
-    }\r
-    /*\r
-     * Handling of Elements: first pass, cleanup and counting\r
-     */\r
-    cur = node->children;\r
-    while (cur != NULL) {\r
-       switch (cur->type) {\r
-           case XML_TEXT_NODE:\r
-           case XML_CDATA_SECTION_NODE:\r
-           case XML_DOCUMENT_NODE:\r
-           case XML_HTML_DOCUMENT_NODE:\r
-           case XML_ELEMENT_NODE:\r
-           case XML_PI_NODE:\r
-           case XML_COMMENT_NODE:\r
-               nbchild++;\r
-               break;\r
-            case XML_DTD_NODE:\r
-               /* Unlink the DTD, it's still reachable using doc->intSubset */\r
-               if (cur->next != NULL)\r
-                   cur->next->prev = cur->prev;\r
-               if (cur->prev != NULL)\r
-                   cur->prev->next = cur->next;\r
-               break;\r
-           default:\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-                "xsltDefaultProcessOneNode: skipping node type %d\n",\r
-                                cur->type));\r
-#endif\r
-               delete = cur;\r
-       }\r
-       cur = cur->next;\r
-       if (delete != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-                "xsltDefaultProcessOneNode: removing ignorable blank node\n"));\r
-#endif\r
-           xmlUnlinkNode(delete);\r
-           xmlFreeNode(delete);\r
-           delete = NULL;\r
-       }\r
-    }\r
-    if (delete != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltDefaultProcessOneNode: removing ignorable blank node\n"));\r
-#endif\r
-       xmlUnlinkNode(delete);\r
-       xmlFreeNode(delete);\r
-       delete = NULL;\r
-    }\r
-\r
-    /*\r
-     * Handling of Elements: second pass, actual processing\r
-     */\r
-    oldSize = ctxt->xpathCtxt->contextSize;\r
-    oldPos = ctxt->xpathCtxt->proximityPosition;\r
-    cur = node->children;\r
-    while (cur != NULL) {\r
-       childno++;\r
-       switch (cur->type) {\r
-           case XML_DOCUMENT_NODE:\r
-           case XML_HTML_DOCUMENT_NODE:\r
-           case XML_ELEMENT_NODE:\r
-               ctxt->xpathCtxt->contextSize = nbchild;\r
-               ctxt->xpathCtxt->proximityPosition = childno;\r
-               xsltProcessOneNode(ctxt, cur, params);\r
-               break;\r
-           case XML_CDATA_SECTION_NODE:\r
-               template = xsltGetTemplate(ctxt, cur, NULL);\r
-               if (template) {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                   XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-                "xsltDefaultProcessOneNode: applying template for CDATA %s\n",\r
-                                    cur->content));\r
-#endif\r
-                   /*\r
-                   * Instantiate the xsl:template.\r
-                   */\r
-                   xsltApplyXSLTTemplate(ctxt, cur, template->content,\r
-                       template, params);\r
-               } else /* if (ctxt->mode == NULL) */ {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                   XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "xsltDefaultProcessOneNode: copy CDATA %s\n",\r
-                                    cur->content));\r
-#endif\r
-                   copy = xsltCopyText(ctxt, ctxt->insert, cur, 0);\r
-                   if (copy == NULL) {\r
-                       xsltTransformError(ctxt, NULL, cur,\r
-                           "xsltDefaultProcessOneNode: cdata copy failed\n");\r
-                   }\r
-               }\r
-               break;\r
-           case XML_TEXT_NODE:\r
-               template = xsltGetTemplate(ctxt, cur, NULL);\r
-               if (template) {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                   XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltDefaultProcessOneNode: applying template for text %s\n",\r
-                                    cur->content));\r
-#endif\r
-                   ctxt->xpathCtxt->contextSize = nbchild;\r
-                   ctxt->xpathCtxt->proximityPosition = childno;\r
-                   /*\r
-                   * Instantiate the xsl:template.\r
-                   */\r
-                   xsltApplyXSLTTemplate(ctxt, cur, template->content,\r
-                       template, params);\r
-               } else /* if (ctxt->mode == NULL) */ {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                   if (cur->content == NULL) {\r
-                       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-                        "xsltDefaultProcessOneNode: copy empty text\n"));\r
-                   } else {\r
-                       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "xsltDefaultProcessOneNode: copy text %s\n",\r
-                                        cur->content));\r
-                    }\r
-#endif\r
-                   copy = xsltCopyText(ctxt, ctxt->insert, cur, 0);\r
-                   if (copy == NULL) {\r
-                       xsltTransformError(ctxt, NULL, cur,\r
-                           "xsltDefaultProcessOneNode: text copy failed\n");\r
-                   }\r
-               }\r
-               break;\r
-           case XML_PI_NODE:\r
-           case XML_COMMENT_NODE:\r
-               template = xsltGetTemplate(ctxt, cur, NULL);\r
-               if (template) {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                   if (cur->type == XML_PI_NODE) {\r
-                       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "xsltDefaultProcessOneNode: template found for PI %s\n",\r
-                                        cur->name));\r
-                   } else if (cur->type == XML_COMMENT_NODE) {\r
-                       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "xsltDefaultProcessOneNode: template found for comment\n"));\r
-                    }\r
-#endif\r
-                   ctxt->xpathCtxt->contextSize = nbchild;\r
-                   ctxt->xpathCtxt->proximityPosition = childno;\r
-                   /*\r
-                   * Instantiate the xsl:template.\r
-                   */\r
-                   xsltApplyXSLTTemplate(ctxt, cur, template->content,\r
-                       template, params);\r
-               }\r
-               break;\r
-           default:\r
-               break;\r
-       }\r
-       cur = cur->next;\r
-    }\r
-    ctxt->xpathCtxt->contextSize = oldSize;\r
-    ctxt->xpathCtxt->proximityPosition = oldPos;\r
-}\r
-\r
-/**\r
- * xsltProcessOneNode:\r
- * @ctxt:  a XSLT process context\r
- * @contextNode:  the "current node" in the source tree\r
- * @withParams:  extra parameters (e.g. xsl:with-param) passed to the\r
- *               template if any\r
- *\r
- * Process the source node.\r
- */\r
-void\r
-xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,\r
-                  xsltStackElemPtr withParams)\r
-{\r
-    xsltTemplatePtr templ;\r
-    xmlNodePtr oldNode;\r
-    \r
-    templ = xsltGetTemplate(ctxt, contextNode, NULL);\r
-    /*\r
-     * If no template is found, apply the default rule.\r
-     */\r
-    if (templ == NULL) {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-       if (contextNode->type == XML_DOCUMENT_NODE) {\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltProcessOneNode: no template found for /\n"));\r
-       } else if (contextNode->type == XML_CDATA_SECTION_NODE) {\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltProcessOneNode: no template found for CDATA\n"));\r
-       } else if (contextNode->type == XML_ATTRIBUTE_NODE) {\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltProcessOneNode: no template found for attribute %s\n",\r
-                            ((xmlAttrPtr) contextNode)->name));\r
-       } else  {\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltProcessOneNode: no template found for %s\n", contextNode->name));\r
-        }\r
-#endif\r
-       oldNode = ctxt->node;\r
-       ctxt->node = contextNode;\r
-       xsltDefaultProcessOneNode(ctxt, contextNode, withParams);\r
-       ctxt->node = oldNode;\r
-       return;\r
-    }\r
-\r
-    if (contextNode->type == XML_ATTRIBUTE_NODE) {\r
-       xsltTemplatePtr oldCurTempRule = ctxt->currentTemplateRule; \r
-       /*\r
-       * Set the "current template rule".\r
-       */\r
-       ctxt->currentTemplateRule = templ;\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltProcessOneNode: applying template '%s' for attribute %s\n",\r
-                        templ->match, contextNode->name));\r
-#endif\r
-       xsltApplyXSLTTemplate(ctxt, contextNode, templ->content, templ, withParams);\r
-\r
-       ctxt->currentTemplateRule = oldCurTempRule;\r
-    } else {\r
-       xsltTemplatePtr oldCurTempRule = ctxt->currentTemplateRule; \r
-       /*\r
-       * Set the "current template rule".\r
-       */\r
-       ctxt->currentTemplateRule = templ;\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-       if (contextNode->type == XML_DOCUMENT_NODE) {\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltProcessOneNode: applying template '%s' for /\n",\r
-                            templ->match));\r
-       } else {\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltProcessOneNode: applying template '%s' for %s\n",\r
-                            templ->match, contextNode->name));\r
-        }\r
-#endif\r
-       xsltApplyXSLTTemplate(ctxt, contextNode, templ->content, templ, withParams);\r
-\r
-       ctxt->currentTemplateRule = oldCurTempRule;\r
-    }\r
-}\r
-\r
-static xmlNodePtr\r
-xsltDebuggerStartSequenceConstructor(xsltTransformContextPtr ctxt,\r
-                                    xmlNodePtr contextNode,\r
-                                    xmlNodePtr list,\r
-                                    xsltTemplatePtr templ,\r
-                                    int *addCallResult)\r
-{\r
-    xmlNodePtr debugedNode = NULL;    \r
-\r
-    if (ctxt->debugStatus != XSLT_DEBUG_NONE) {\r
-        if (templ) {\r
-            *addCallResult = xslAddCall(templ, templ->elem);\r
-        } else {\r
-            *addCallResult = xslAddCall(NULL, list);\r
-        }\r
-        switch (ctxt->debugStatus) {\r
-            case XSLT_DEBUG_RUN_RESTART:\r
-            case XSLT_DEBUG_QUIT:\r
-                if (*addCallResult)\r
-                    xslDropCall();\r
-                return(NULL);\r
-        }\r
-        if (templ) {\r
-            xslHandleDebugger(templ->elem, contextNode, templ, ctxt);\r
-            debugedNode = templ->elem;\r
-        } else if (list) {\r
-            xslHandleDebugger(list, contextNode, templ, ctxt);\r
-            debugedNode = list;\r
-        } else if (ctxt->inst) {\r
-            xslHandleDebugger(ctxt->inst, contextNode, templ, ctxt);\r
-            debugedNode = ctxt->inst;\r
-        }\r
-    }\r
-    return(debugedNode);\r
-}\r
-\r
-static int\r
-xsltLocalVariablePush(xsltTransformContextPtr ctxt,\r
-                     xsltStackElemPtr variable,\r
-                     int level)\r
-{\r
-    if (ctxt->varsMax == 0) {\r
-       ctxt->varsMax = 10;\r
-       ctxt->varsTab =\r
-           (xsltStackElemPtr *) xmlMalloc(ctxt->varsMax *\r
-           sizeof(ctxt->varsTab[0]));\r
-       if (ctxt->varsTab == NULL) {\r
-           xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");\r
-           return (-1);\r
-       }\r
-    }\r
-    if (ctxt->varsNr >= ctxt->varsMax) {\r
-       ctxt->varsMax *= 2;\r
-       ctxt->varsTab =\r
-           (xsltStackElemPtr *) xmlRealloc(ctxt->varsTab,\r
-           ctxt->varsMax *\r
-           sizeof(ctxt->varsTab[0]));\r
-       if (ctxt->varsTab == NULL) {\r
-           xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");\r
-           return (-1);\r
-       }\r
-    }\r
-    ctxt->varsTab[ctxt->varsNr++] = variable;\r
-    ctxt->vars = variable;\r
-    variable->level = level;\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltReleaseLocalRVTs:\r
- *\r
- * Fragments which are results of extension instructions\r
- * are preserved; all other fragments are freed/cached.\r
- */\r
-static void\r
-xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base)\r
-{\r
-    xmlDocPtr cur = ctxt->localRVT, tmp;\r
-    \r
-    while ((cur != NULL) && (cur != base)) {\r
-       if (cur->psvi == (void *) ((long) 1)) {\r
-           cur = (xmlDocPtr) cur->next;\r
-       } else {\r
-           tmp = cur;\r
-           cur = (xmlDocPtr) cur->next;\r
-\r
-           if (tmp == ctxt->localRVT)\r
-               ctxt->localRVT = (xmlDocPtr) tmp->next;\r
-\r
-           /*\r
-           * We need ctxt->localRVTBase for extension instructions\r
-           * which return values (like EXSLT's function).\r
-           */\r
-           if (tmp == ctxt->localRVTBase)\r
-               ctxt->localRVTBase = (xmlDocPtr) tmp->next;\r
-\r
-           if (tmp->prev)\r
-               tmp->prev->next = (xmlNodePtr) cur;\r
-           if (cur)\r
-               cur->prev = tmp->prev;\r
-           xsltReleaseRVT(ctxt, tmp);\r
-       }\r
-    }\r
-}\r
-\r
-/**\r
- * xsltApplySequenceConstructor:\r
- * @ctxt:  a XSLT process context\r
- * @contextNode:  the "current node" in the source tree\r
- * @list:  the nodes of a sequence constructor;\r
- *         (plus leading xsl:param elements)\r
- * @templ: the compiled xsl:template (optional)\r
- *\r
- * Processes a sequence constructor.\r
- * \r
- * NOTE: ctxt->currentTemplateRule was introduced to reflect the\r
- * semantics of "current template rule". I.e. the field ctxt->templ\r
- * is not intended to reflect this, thus always pushed onto the\r
- * template stack.\r
- */\r
-static void\r
-xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,\r
-                            xmlNodePtr contextNode, xmlNodePtr list,\r
-                            xsltTemplatePtr templ)\r
-{\r
-    xmlNodePtr oldInsert, oldInst, oldCurInst, oldContextNode;\r
-    xmlNodePtr cur, insert, copy = NULL;\r
-    int level = 0, oldVarsNr;\r
-    xmlDocPtr oldLocalFragmentTop, oldLocalFragmentBase;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    xsltStylePreCompPtr info;\r
-#endif\r
-\r
-#ifdef WITH_DEBUGGER\r
-    int addCallResult = 0;\r
-    xmlNodePtr debuggedNode = NULL;\r
-#endif\r
-\r
-    if (ctxt == NULL)\r
-       return;\r
-\r
-#ifdef WITH_DEBUGGER \r
-    if (ctxt->debugStatus != XSLT_DEBUG_NONE) {\r
-       debuggedNode =\r
-           xsltDebuggerStartSequenceConstructor(ctxt, contextNode,\r
-               list, templ, &addCallResult);\r
-       if (debuggedNode == NULL)\r
-           return;\r
-    }\r
-#endif\r
-\r
-    if (list == NULL)\r
-        return;\r
-    CHECK_STOPPED;\r
-\r
-    oldLocalFragmentTop = ctxt->localRVT;\r
-    oldInsert = insert = ctxt->insert;\r
-    oldInst = oldCurInst = ctxt->inst;\r
-    oldContextNode = ctxt->node;\r
-    /*\r
-    * Save current number of variables on the stack; new vars are popped when\r
-    * exiting.\r
-    */\r
-    oldVarsNr = ctxt->varsNr;\r
-    /*\r
-    * Process the sequence constructor.\r
-    */\r
-    cur = list;\r
-    while (cur != NULL) {\r
-        ctxt->inst = cur;\r
-\r
-#ifdef WITH_DEBUGGER\r
-        switch (ctxt->debugStatus) {\r
-            case XSLT_DEBUG_RUN_RESTART:\r
-            case XSLT_DEBUG_QUIT:\r
-                break;\r
-\r
-        }\r
-#endif\r
-        /*\r
-         * Test; we must have a valid insertion point.\r
-         */\r
-        if (insert == NULL) {\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-            XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsltApplySequenceConstructor: insert == NULL !\n"));\r
-#endif\r
-            goto error;\r
-        }\r
-\r
-#ifdef WITH_DEBUGGER\r
-        if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (debuggedNode != cur))\r
-            xslHandleDebugger(cur, contextNode, templ, ctxt);\r
-#endif\r
-\r
-#ifdef XSLT_REFACTORED\r
-       if (cur->type == XML_ELEMENT_NODE) {\r
-           info = (xsltStylePreCompPtr) cur->psvi;\r
-           /*\r
-           * We expect a compiled representation on:\r
-           * 1) XSLT instructions of this XSLT version (1.0)\r
-           *    (with a few exceptions)\r
-           * 2) Literal result elements\r
-           * 3) Extension instructions\r
-           * 4) XSLT instructions of future XSLT versions\r
-           *    (forwards-compatible mode).\r
-           */\r
-           if (info == NULL) {\r
-               /*\r
-               * Handle the rare cases where we don't expect a compiled\r
-               * representation on an XSLT element.\r
-               */\r
-               if (IS_XSLT_ELEM_FAST(cur) && IS_XSLT_NAME(cur, "message")) {\r
-                   xsltMessage(ctxt, contextNode, cur);\r
-                   goto skip_children;\r
-               }                                \r
-               /*\r
-               * Something really went wrong:\r
-               */\r
-               xsltTransformError(ctxt, NULL, cur,\r
-                   "Internal error in xsltApplySequenceConstructor(): "\r
-                   "The element '%s' in the stylesheet has no compiled "\r
-                   "representation.\n",\r
-                   cur->name);\r
-                goto skip_children;\r
-            }\r
-\r
-           if (info->type == XSLT_FUNC_LITERAL_RESULT_ELEMENT) {\r
-               xsltStyleItemLRElementInfoPtr lrInfo =\r
-                   (xsltStyleItemLRElementInfoPtr) info;\r
-               /*\r
-               * Literal result elements\r
-               * --------------------------------------------------------\r
-               */\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,\r
-                   xsltGenericDebug(xsltGenericDebugContext,\r
-                   "xsltApplySequenceConstructor: copy literal result "\r
-                   "element '%s'\n", cur->name));\r
-#endif\r
-               /*\r
-               * Copy the raw element-node.\r
-               * OLD: if ((copy = xsltShallowCopyElem(ctxt, cur, insert))\r
-               *     == NULL)\r
-               *   goto error;\r
-               */              \r
-               copy = xmlDocCopyNode(cur, insert->doc, 0);\r
-               if (copy == NULL) {\r
-                   xsltTransformError(ctxt, NULL, cur,\r
-                       "Internal error in xsltApplySequenceConstructor(): "\r
-                       "Failed to copy literal result element '%s'.\n",\r
-                       cur->name);\r
-                   goto error;\r
-               } else {\r
-                   /*\r
-                   * Add the element-node to the result tree.\r
-                   */\r
-                   copy->doc = ctxt->output;\r
-                   xmlAddChild(insert, copy);\r
-                   /*\r
-                   * Create effective namespaces declarations.\r
-                   * OLD: xsltCopyNamespaceList(ctxt, copy, cur->nsDef);\r
-                   */\r
-                   if (lrInfo->effectiveNs != NULL) {\r
-                       xsltEffectiveNsPtr effNs = lrInfo->effectiveNs;\r
-                       xmlNsPtr ns, lastns = NULL;\r
-\r
-                       while (effNs != NULL) {\r
-                           /*\r
-                           * Avoid generating redundant namespace\r
-                           * declarations; thus lookup if there is already\r
-                           * such a ns-decl in the result.\r
-                           */                      \r
-                           ns = xmlSearchNs(copy->doc, copy, effNs->prefix);\r
-                           if ((ns != NULL) &&\r
-                               (xmlStrEqual(ns->href, effNs->nsName)))\r
-                           {\r
-                               effNs = effNs->next;\r
-                               continue;                           \r
-                           }\r
-                           ns = xmlNewNs(copy, effNs->nsName, effNs->prefix);\r
-                           if (ns == NULL) {\r
-                               xsltTransformError(ctxt, NULL, cur,\r
-                                   "Internal error in "\r
-                                   "xsltApplySequenceConstructor(): "\r
-                                   "Failed to copy a namespace "\r
-                                   "declaration.\n");\r
-                               goto error;\r
-                           }\r
-                                                               \r
-                           if (lastns == NULL)\r
-                               copy->nsDef = ns;\r
-                           else\r
-                               lastns->next =ns;\r
-                           lastns = ns;\r
-\r
-                           effNs = effNs->next;\r
-                       }\r
-                       \r
-                   }\r
-                   /*\r
-                   * NOTE that we don't need to apply ns-alising: this was\r
-                   *  already done at compile-time.\r
-                   */\r
-                   if (cur->ns != NULL) {\r
-                       /*\r
-                       * If there's no such ns-decl in the result tree,\r
-                       * then xsltGetSpecialNamespace() will\r
-                       * create a ns-decl on the copied node.\r
-                       */                      \r
-                       copy->ns = xsltGetSpecialNamespace(ctxt, cur,\r
-                           cur->ns->href, cur->ns->prefix, copy);                          \r
-                   } else {\r
-                       /*\r
-                       * Undeclare the default namespace if needed.\r
-                       * This can be skipped, if the result element has\r
-                       *  no ns-decls, in which case the result element\r
-                       *  obviously does not declare a default namespace;\r
-                       *  AND there's either no parent, or the parent\r
-                       *  element is in no namespace; this means there's no\r
-                       *  default namespace is scope to care about.\r
-                       *\r
-                       * REVISIT: This might result in massive\r
-                       *  generation of ns-decls if nodes in a default\r
-                       *  namespaces are mixed with nodes in no namespace.\r
-                       *  \r
-                       */\r
-                       if (copy->nsDef ||\r
-                           ((insert != NULL) &&\r
-                            (insert->type == XML_ELEMENT_NODE) &&\r
-                            (insert->ns != NULL)))\r
-                       {\r
-                           xsltGetSpecialNamespace(ctxt, cur,\r
-                               NULL, NULL, copy);\r
-                       }\r
-                   }\r
-               }\r
-               /*\r
-               * SPEC XSLT 2.0 "Each attribute of the literal result\r
-               *  element, other than an attribute in the XSLT namespace,\r
-               *  is processed to produce an attribute for the element in\r
-               *  the result tree."\r
-               * NOTE: See bug #341325.\r
-               */\r
-               if (cur->properties != NULL) {\r
-                   xsltAttrListTemplateProcess(ctxt, copy, cur->properties);\r
-               }\r
-           } else if (IS_XSLT_ELEM_FAST(cur)) {\r
-               /*\r
-               * XSLT instructions\r
-               * --------------------------------------------------------\r
-               */\r
-               if (info->type == XSLT_FUNC_UNKOWN_FORWARDS_COMPAT) {\r
-                   /*\r
-                   * We hit an unknown XSLT element.\r
-                   * Try to apply one of the fallback cases.\r
-                   */          \r
-                   ctxt->insert = insert;\r
-                   if (!xsltApplyFallbacks(ctxt, contextNode, cur)) {\r
-                       xsltTransformError(ctxt, NULL, cur,\r
-                           "The is no fallback behaviour defined for "\r
-                           "the unknown XSLT element '%s'.\n",\r
-                           cur->name);\r
-                   }                   \r
-                   ctxt->insert = oldInsert;\r
-               } else if (info->func != NULL) {\r
-                   /*\r
-                   * Execute the XSLT instruction.\r
-                   */\r
-                   ctxt->insert = insert;\r
-\r
-                   info->func(ctxt, contextNode, cur,\r
-                       (xsltElemPreCompPtr) info);\r
-\r
-                   /*\r
-                   * Cleanup temporary tree fragments.\r
-                   */\r
-                   if (oldLocalFragmentTop != ctxt->localRVT)\r
-                       xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);\r
-\r
-                   ctxt->insert = oldInsert;\r
-               } else if (info->type == XSLT_FUNC_VARIABLE) {          \r
-                   xsltStackElemPtr tmpvar = ctxt->vars;\r
-               \r
-                   xsltParseStylesheetVariable(ctxt, cur);\r
-                   \r
-                   if (tmpvar != ctxt->vars) {\r
-                       /*\r
-                       * TODO: Using a @tmpvar is an annoying workaround, but\r
-                       *  the current mechanisms do not provide any other way\r
-                       *  of knowing if the var was really pushed onto the\r
-                       *  stack.\r
-                       */\r
-                       ctxt->vars->level = level;\r
-                   }\r
-               } else if (info->type == XSLT_FUNC_MESSAGE) {\r
-                   /*\r
-                   * TODO: Won't be hit, since we don't compile xsl:message.\r
-                   */\r
-                   xsltMessage(ctxt, contextNode, cur);\r
-               } else {\r
-                   xsltTransformError(ctxt, NULL, cur,\r
-                       "Unexpected XSLT element '%s'.\n", cur->name);                  \r
-               }\r
-               goto skip_children;\r
-\r
-           } else {\r
-               xsltTransformFunction func;\r
-               /*\r
-               * Extension intructions (elements)\r
-               * --------------------------------------------------------\r
-               */                              \r
-               if (cur->psvi == xsltExtMarker) {\r
-                   /*\r
-                   * The xsltExtMarker was set during the compilation\r
-                   * of extension instructions if there was no registered\r
-                   * handler for this specific extension function at\r
-                   * compile-time.\r
-                   * Libxslt will now lookup if a handler is\r
-                   * registered in the context of this transformation.\r
-                   */\r
-                   func = (xsltTransformFunction)\r
-                       xsltExtElementLookup(ctxt, cur->name, cur->ns->href);\r
-               } else\r
-                   func = ((xsltElemPreCompPtr) cur->psvi)->func;\r
-               \r
-               if (func == NULL) {\r
-                   /*\r
-                   * No handler available.\r
-                   * Try to execute fallback behaviour via xsl:fallback.\r
-                   */\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                   XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,\r
-                       xsltGenericDebug(xsltGenericDebugContext,\r
-                           "xsltApplySequenceConstructor: unknown extension %s\n",\r
-                           cur->name));\r
-#endif\r
-                   ctxt->insert = insert;\r
-                   if (!xsltApplyFallbacks(ctxt, contextNode, cur)) {\r
-                       xsltTransformError(ctxt, NULL, cur,\r
-                           "Unknown extension instruction '{%s}%s'.\n",\r
-                           cur->ns->href, cur->name);\r
-                   }                   \r
-                   ctxt->insert = oldInsert;               \r
-               } else {\r
-                   /*\r
-                   * Execute the handler-callback.\r
-                   */\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                   XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,\r
-                       "xsltApplySequenceConstructor: extension construct %s\n",\r
-                       cur->name));\r
-#endif             \r
-                   ctxt->insert = insert;\r
-                   /*\r
-                   * We need the fragment base for extension instructions\r
-                   * which return values (like EXSLT's function).\r
-                   */\r
-                   oldLocalFragmentBase = ctxt->localRVTBase;\r
-                   ctxt->localRVTBase = NULL;\r
-\r
-                   func(ctxt, contextNode, cur, cur->psvi);\r
-\r
-                   ctxt->localRVTBase = oldLocalFragmentBase;\r
-                   /*\r
-                   * Cleanup temporary tree fragments.\r
-                   */\r
-                   if (oldLocalFragmentTop != ctxt->localRVT)\r
-                       xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);\r
-\r
-                   ctxt->insert = oldInsert;\r
-               }\r
-               goto skip_children;\r
-           }\r
-\r
-       } else if (XSLT_IS_TEXT_NODE(cur)) {\r
-           /*\r
-           * Text\r
-           * ------------------------------------------------------------\r
-           */\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-            if (cur->name == xmlStringTextNoenc) {\r
-                XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,\r
-                   xsltGenericDebug(xsltGenericDebugContext,\r
-                   "xsltApplySequenceConstructor: copy unescaped text '%s'\n",\r
-                   cur->content));\r
-            } else {\r
-                XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,\r
-                   xsltGenericDebug(xsltGenericDebugContext,\r
-                   "xsltApplySequenceConstructor: copy text '%s'\n",\r
-                   cur->content));\r
-            }\r
-#endif\r
-            if (xsltCopyText(ctxt, insert, cur, ctxt->internalized) == NULL)\r
-               goto error;         \r
-       }\r
-\r
-#else /* XSLT_REFACTORED */\r
-\r
-        if (IS_XSLT_ELEM(cur)) {\r
-            /*\r
-             * This is an XSLT node\r
-             */\r
-            xsltStylePreCompPtr info = (xsltStylePreCompPtr) cur->psvi;\r
-\r
-            if (info == NULL) {\r
-                if (IS_XSLT_NAME(cur, "message")) {\r
-                    xsltMessage(ctxt, contextNode, cur);\r
-                } else {                   \r
-                    /*\r
-                     * That's an error try to apply one of the fallback cases\r
-                     */\r
-                    ctxt->insert = insert;\r
-                    if (!xsltApplyFallbacks(ctxt, contextNode, cur)) {\r
-                        xsltGenericError(xsltGenericErrorContext,\r
-                           "xsltApplySequenceConstructor: %s was not compiled\n",\r
-                           cur->name);\r
-                    }\r
-                    ctxt->insert = oldInsert;\r
-                }\r
-                goto skip_children;\r
-            }      \r
-\r
-            if (info->func != NULL) {\r
-               oldCurInst = ctxt->inst;\r
-               ctxt->inst = cur;\r
-                ctxt->insert = insert;\r
-\r
-                info->func(ctxt, contextNode, cur, (xsltElemPreCompPtr) info);\r
-\r
-               /*\r
-               * Cleanup temporary tree fragments.\r
-               */\r
-               if (oldLocalFragmentTop != ctxt->localRVT)\r
-                   xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);\r
-\r
-                ctxt->insert = oldInsert;\r
-               ctxt->inst = oldCurInst;\r
-                goto skip_children;\r
-            }\r
-\r
-            if (IS_XSLT_NAME(cur, "variable")) {\r
-               xsltStackElemPtr tmpvar = ctxt->vars;\r
-               \r
-               oldCurInst = ctxt->inst;\r
-               ctxt->inst = cur;\r
-\r
-               xsltParseStylesheetVariable(ctxt, cur);\r
-\r
-               ctxt->inst = oldCurInst;\r
-               \r
-               if (tmpvar != ctxt->vars) {\r
-                   /*\r
-                   * TODO: Using a @tmpvar is an annoying workaround, but\r
-                   *  the current mechanisms do not provide any other way\r
-                   *  of knowing if the var was really pushed onto the\r
-                   *  stack.\r
-                   */\r
-                   ctxt->vars->level = level;\r
-               }\r
-            } else if (IS_XSLT_NAME(cur, "message")) {\r
-                xsltMessage(ctxt, contextNode, cur);\r
-            } else {\r
-               xsltTransformError(ctxt, NULL, cur,\r
-                   "Unexpected XSLT element '%s'.\n", cur->name);\r
-            }\r
-            goto skip_children;\r
-        } else if ((cur->type == XML_TEXT_NODE) ||\r
-                   (cur->type == XML_CDATA_SECTION_NODE)) {\r
-\r
-            /*\r
-             * This text comes from the stylesheet\r
-             * For stylesheets, the set of whitespace-preserving\r
-             * element names consists of just xsl:text.\r
-             */\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-            if (cur->type == XML_CDATA_SECTION_NODE) {\r
-                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,\r
-                                 "xsltApplySequenceConstructor: copy CDATA text %s\n",\r
-                                 cur->content));\r
-            } else if (cur->name == xmlStringTextNoenc) {\r
-                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,\r
-                                 "xsltApplySequenceConstructor: copy unescaped text %s\n",\r
-                                 cur->content));\r
-            } else {\r
-                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,\r
-                                 "xsltApplySequenceConstructor: copy text %s\n",\r
-                                 cur->content));\r
-            }\r
-#endif\r
-            if (xsltCopyText(ctxt, insert, cur, ctxt->internalized) == NULL)\r
-               goto error;\r
-        } else if ((cur->type == XML_ELEMENT_NODE) &&\r
-                   (cur->ns != NULL) && (cur->psvi != NULL)) {\r
-            xsltTransformFunction function;\r
-\r
-           oldCurInst = ctxt->inst;\r
-           ctxt->inst = cur;\r
-            /*\r
-             * Flagged as an extension element\r
-             */\r
-            if (cur->psvi == xsltExtMarker)\r
-                function = (xsltTransformFunction)\r
-                    xsltExtElementLookup(ctxt, cur->name, cur->ns->href);\r
-            else\r
-                function = ((xsltElemPreCompPtr) cur->psvi)->func;\r
-\r
-            if (function == NULL) {\r
-                xmlNodePtr child;\r
-                int found = 0;\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,\r
-                   "xsltApplySequenceConstructor: unknown extension %s\n",\r
-                    cur->name));\r
-#endif\r
-                /*\r
-                 * Search if there are fallbacks\r
-                 */\r
-                child = cur->children;\r
-                while (child != NULL) {\r
-                    if ((IS_XSLT_ELEM(child)) &&\r
-                        (IS_XSLT_NAME(child, "fallback")))\r
-                   {\r
-                        found = 1;\r
-                        xsltApplySequenceConstructor(ctxt, contextNode,\r
-                           child->children, NULL);\r
-                    }\r
-                    child = child->next;\r
-                }\r
-\r
-                if (!found) {\r
-                    xsltTransformError(ctxt, NULL, cur,\r
-                       "xsltApplySequenceConstructor: failed to find extension %s\n",\r
-                       cur->name);\r
-                }\r
-            } else {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,\r
-                   "xsltApplySequenceConstructor: extension construct %s\n",\r
-                    cur->name));\r
-#endif\r
-\r
-                ctxt->insert = insert;\r
-               /*\r
-               * We need the fragment base for extension instructions\r
-               * which return values (like EXSLT's function).\r
-               */\r
-               oldLocalFragmentBase = ctxt->localRVTBase;\r
-               ctxt->localRVTBase = NULL;\r
-\r
-                function(ctxt, contextNode, cur, cur->psvi);\r
-               /*\r
-               * Cleanup temporary tree fragments.\r
-               */\r
-               if (oldLocalFragmentTop != ctxt->localRVT)\r
-                   xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);\r
-\r
-               ctxt->localRVTBase = oldLocalFragmentBase;\r
-                ctxt->insert = oldInsert;\r
-\r
-            }\r
-           ctxt->inst = oldCurInst;\r
-            goto skip_children;\r
-        } else if (cur->type == XML_ELEMENT_NODE) {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-            XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsltApplySequenceConstructor: copy node %s\n",\r
-                cur->name));\r
-#endif\r
-           oldCurInst = ctxt->inst;\r
-           ctxt->inst = cur;\r
-\r
-            if ((copy = xsltShallowCopyElem(ctxt, cur, insert, 1)) == NULL)\r
-               goto error;            \r
-            /*\r
-             * Add extra namespaces inherited from the current template\r
-             * if we are in the first level children and this is a\r
-            * "real" template.      \r
-             */\r
-            if ((templ != NULL) && (oldInsert == insert) &&\r
-                (ctxt->templ != NULL) && (ctxt->templ->inheritedNs != NULL)) {\r
-                int i;\r
-                xmlNsPtr ns, ret;\r
-\r
-                for (i = 0; i < ctxt->templ->inheritedNsNr; i++) {\r
-                   const xmlChar *URI = NULL;\r
-                   xsltStylesheetPtr style;\r
-                    ns = ctxt->templ->inheritedNs[i];              \r
-                   \r
-                   /* Note that the XSLT namespace was already excluded\r
-                   * in xsltGetInheritedNsList().\r
-                   */\r
-#if 0\r
-                   if (xmlStrEqual(ns->href, XSLT_NAMESPACE))\r
-                       continue;\r
-#endif\r
-                   style = ctxt->style;\r
-                   while (style != NULL) {\r
-                       if (style->nsAliases != NULL)\r
-                           URI = (const xmlChar *) \r
-                               xmlHashLookup(style->nsAliases, ns->href);\r
-                       if (URI != NULL)\r
-                           break;\r
-                       \r
-                       style = xsltNextImport(style);\r
-                   }\r
-                   if (URI == UNDEFINED_DEFAULT_NS)\r
-                       continue;\r
-                   if (URI == NULL)\r
-                       URI = ns->href;\r
-                   /*\r
-                   * TODO: The following will still be buggy for the\r
-                   * non-refactored code.\r
-                   */\r
-                   ret = xmlSearchNs(copy->doc, copy, ns->prefix);\r
-                   if ((ret == NULL) || (!xmlStrEqual(ret->href, URI)))\r
-                   {\r
-                       xmlNewNs(copy, URI, ns->prefix);\r
-                   }\r
-                }\r
-               if (copy->ns != NULL) {\r
-                   /*\r
-                    * Fix the node namespace if needed\r
-                    */\r
-                   copy->ns = xsltGetNamespace(ctxt, cur, copy->ns, copy);\r
-               }\r
-            }\r
-           /*\r
-             * all the attributes are directly inherited\r
-             */\r
-            if (cur->properties != NULL) {\r
-                xsltAttrListTemplateProcess(ctxt, copy, cur->properties);\r
-            }\r
-           ctxt->inst = oldCurInst;\r
-        }\r
-#endif /* else of XSLT_REFACTORED */\r
-\r
-        /*\r
-         * Descend into content in document order.\r
-         */\r
-        if (cur->children != NULL) {\r
-            if (cur->children->type != XML_ENTITY_DECL) {\r
-                cur = cur->children;\r
-               level++;\r
-                if (copy != NULL)\r
-                    insert = copy;\r
-                continue;\r
-            }\r
-        }\r
-\r
-skip_children:\r
-       /*\r
-       * If xslt:message was just processed, we might have hit a\r
-       * terminate='yes'; if so, then break the loop and clean up.\r
-       * TODO: Do we need to check this also before trying to descend\r
-       *  into the content?\r
-       */\r
-       if (ctxt->state == XSLT_STATE_STOPPED)\r
-           break;\r
-        if (cur->next != NULL) {\r
-            cur = cur->next;\r
-            continue;\r
-        }\r
-\r
-        do {\r
-            cur = cur->parent;\r
-           level--;\r
-           /*\r
-           * Pop variables/params (xsl:variable and xsl:param).\r
-           */\r
-           if ((ctxt->varsNr > oldVarsNr) && (ctxt->vars->level > level)) {\r
-               xsltLocalVariablePop(ctxt, oldVarsNr, level);           \r
-           }\r
-\r
-            insert = insert->parent;\r
-            if (cur == NULL)\r
-                break;\r
-            if (cur == list->parent) {\r
-                cur = NULL;\r
-                break;\r
-            }\r
-            if (cur->next != NULL) {\r
-                cur = cur->next;\r
-                break;\r
-            }\r
-        } while (cur != NULL);\r
-    }\r
-\r
-error:\r
-    /*\r
-    * In case of errors: pop remaining variables.\r
-    */\r
-    if (ctxt->varsNr > oldVarsNr)\r
-       xsltLocalVariablePop(ctxt, oldVarsNr, -1);     \r
-\r
-    ctxt->node = oldContextNode;\r
-    ctxt->inst = oldInst;\r
-    ctxt->insert = oldInsert;\r
-    \r
-#ifdef WITH_DEBUGGER\r
-    if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (addCallResult)) {\r
-        xslDropCall();\r
-    }\r
-#endif\r
-}\r
-\r
-/*\r
-* xsltApplyXSLTTemplate:\r
-* @ctxt:  a XSLT transformation context\r
-* @contextNode:  the node in the source tree.\r
-* @list:  the nodes of a sequence constructor;\r
-*         (plus leading xsl:param elements)\r
-* @templ: the compiled xsl:template declaration;\r
-*         NULL if a sequence constructor\r
-* @withParams:  a set of caller-parameters (xsl:with-param) or NULL\r
-*\r
-* Called by:\r
-* - xsltApplyImports()\r
-* - xsltCallTemplate()\r
-* - xsltDefaultProcessOneNode()\r
-* - xsltProcessOneNode()\r
-*/\r
-static void\r
-xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,\r
-                     xmlNodePtr contextNode,\r
-                     xmlNodePtr list,\r
-                     xsltTemplatePtr templ,\r
-                     xsltStackElemPtr withParams)\r
-{\r
-    int oldVarsBase = 0;\r
-    long start = 0;\r
-    xmlNodePtr cur;\r
-    xsltStackElemPtr tmpParam = NULL;\r
-    xmlDocPtr oldUserFragmentTop, oldLocalFragmentTop;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemParamPtr iparam;\r
-#else\r
-    xsltStylePreCompPtr iparam;\r
-#endif\r
-\r
-#ifdef WITH_DEBUGGER\r
-    int addCallResult = 0;\r
-#endif \r
-\r
-    if (ctxt == NULL)\r
-       return;    \r
-    if (templ == NULL) {\r
-       xsltTransformError(ctxt, NULL, list,\r
-           "xsltApplyXSLTTemplate: Bad arguments; @templ is mandatory.\n");\r
-       return;\r
-    }\r
-\r
-#ifdef WITH_DEBUGGER\r
-    if (ctxt->debugStatus != XSLT_DEBUG_NONE) {\r
-       if (xsltDebuggerStartSequenceConstructor(ctxt, contextNode,\r
-               list, templ, &addCallResult) == NULL)\r
-           return;\r
-    }\r
-#endif\r
-\r
-    if (list == NULL)\r
-        return;\r
-    CHECK_STOPPED;\r
-\r
-    /*\r
-    * Check for infinite recursion: stop if the maximum of nested templates\r
-    * is excceeded. Adjust xsltMaxDepth if you need more.\r
-    */\r
-    if (((ctxt->templNr >= xsltMaxDepth) ||\r
-        (ctxt->varsNr >= 5 * xsltMaxDepth)))\r
-    {\r
-        xsltTransformError(ctxt, NULL, list,\r
-           "xsltApplyXSLTTemplate: A potential infinite template recursion "\r
-           "was detected.\n"\r
-           "You can adjust xsltMaxDepth (--maxdepth) in order to "\r
-           "raise the maximum number of nested template calls and "\r
-           "variables/params (currently set to %d).\n",\r
-           xsltMaxDepth);\r
-        xsltDebug(ctxt, contextNode, list, NULL);\r
-        return;\r
-    }\r
-    \r
-    oldUserFragmentTop = ctxt->tmpRVT;\r
-    ctxt->tmpRVT = NULL;\r
-    oldLocalFragmentTop = ctxt->localRVT;\r
-       \r
-    /*\r
-    * Initiate a distinct scope of local params/variables.\r
-    */\r
-    oldVarsBase = ctxt->varsBase;\r
-    ctxt->varsBase = ctxt->varsNr;\r
-    \r
-    ctxt->node = contextNode;\r
-    if (ctxt->profile) {\r
-       templ->nbCalls++;\r
-       start = xsltTimestamp();\r
-       profPush(ctxt, 0);\r
-    }\r
-    /*\r
-    * Push the xsl:template declaration onto the stack.\r
-    */\r
-    templPush(ctxt, templ);\r
-    \r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    if (templ->name != NULL)\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,\r
-       "applying xsl:template '%s'\n", templ->name));\r
-#endif\r
-    /*\r
-    * Process xsl:param instructions and skip those elements for\r
-    * further processing.\r
-    */\r
-    cur = list;\r
-    do {\r
-       if (cur->type == XML_TEXT_NODE) {\r
-           cur = cur->next;\r
-           continue;\r
-       }\r
-       if ((cur->type != XML_ELEMENT_NODE) ||\r
-           (cur->name[0] != 'p') ||\r
-           (cur->psvi == NULL) ||\r
-           (! xmlStrEqual(cur->name, BAD_CAST "param")) ||\r
-           (! IS_XSLT_ELEM(cur)))\r
-       {\r
-           break;\r
-       }\r
-\r
-       list = cur->next;\r
-\r
-#ifdef XSLT_REFACTORED\r
-       iparam = (xsltStyleItemParamPtr) cur->psvi;\r
-#else\r
-       iparam = (xsltStylePreCompPtr) cur->psvi;\r
-#endif\r
-       \r
-       /*\r
-       * Substitute xsl:param for a given xsl:with-param.\r
-       * Since the XPath expression will reference the params/vars\r
-       * by index, we need to slot the xsl:with-params in the\r
-       * order of encountered xsl:params to keep the sequence of\r
-       * params/variables in the stack exactly as it was at\r
-       * compile time,\r
-       */\r
-       tmpParam = NULL;\r
-       if (withParams) {\r
-           tmpParam = withParams;\r
-           do {\r
-               if ((tmpParam->name == (iparam->name)) &&\r
-                   (tmpParam->nameURI == (iparam->ns)))\r
-               {\r
-                   /*\r
-                   * Push the caller-parameter.\r
-                   */              \r
-                   xsltLocalVariablePush(ctxt, tmpParam, -1);\r
-                   break;\r
-               }\r
-               tmpParam = tmpParam->next;\r
-           } while (tmpParam != NULL);\r
-       }\r
-       /*\r
-       * Push the xsl:param.\r
-       */\r
-       if (tmpParam == NULL) {\r
-           /*\r
-           * Note that we must assume that the added parameter\r
-           * has a @depth of 0.\r
-           */\r
-           xsltParseStylesheetParam(ctxt, cur);\r
-       }\r
-       cur = cur->next;\r
-    } while (cur != NULL);    \r
-    /*\r
-    * Process the sequence constructor.\r
-    */\r
-    xsltApplySequenceConstructor(ctxt, contextNode, list, templ);\r
-    \r
-    /*\r
-    * Remove remaining xsl:param and xsl:with-param items from\r
-    * the stack. Don't free xsl:with-param items.\r
-    */\r
-    if (ctxt->varsNr > ctxt->varsBase)\r
-       xsltTemplateParamsCleanup(ctxt);    \r
-    ctxt->varsBase = oldVarsBase;\r
-    \r
-    /*\r
-    * Clean up remaining local tree fragments.\r
-    * This also frees fragments which are the result of\r
-    * extension instructions. Should normally not be hit; but\r
-    * just for the case xsltExtensionInstructionResultFinalize()\r
-    * was not called by the extension author.\r
-    */\r
-    if (oldLocalFragmentTop != ctxt->localRVT) {\r
-       xmlDocPtr cur = ctxt->localRVT, tmp;\r
-\r
-       do {\r
-           tmp = cur;\r
-           cur = (xmlDocPtr) cur->next;\r
-           xsltReleaseRVT(ctxt, tmp);\r
-       } while (cur != oldLocalFragmentTop);\r
-    }\r
-    ctxt->localRVT = oldLocalFragmentTop;\r
-\r
-    /*\r
-    * Release user-created fragments stored in the scope\r
-    * of xsl:template. Note that this mechanism is deprecated:\r
-    * user code should now use xsltRegisterLocalRVT() instead\r
-    * of the obsolete xsltRegisterTmpRVT().    \r
-    */\r
-    if (ctxt->tmpRVT) {\r
-       xmlDocPtr cur = ctxt->tmpRVT, tmp;\r
-\r
-       while (cur != NULL) {\r
-           tmp = cur;\r
-           cur = (xmlDocPtr) cur->next;\r
-           xsltReleaseRVT(ctxt, tmp);\r
-       }       \r
-    }\r
-    ctxt->tmpRVT = oldUserFragmentTop;    \r
-    \r
-    /*\r
-    * Pop the xsl:template declaration from the stack.\r
-    */\r
-    templPop(ctxt);    \r
-    if (ctxt->profile) {\r
-       long spent, child, total, end;\r
-       \r
-       end = xsltTimestamp();\r
-       child = profPop(ctxt);\r
-       total = end - start;\r
-       spent = total - child;\r
-       if (spent <= 0) {\r
-           /*\r
-           * Not possible unless the original calibration failed\r
-           * we can try to correct it on the fly.\r
-           */\r
-           xsltCalibrateAdjust(spent);\r
-           spent = 0;\r
-       }\r
-       \r
-       templ->time += spent;\r
-       if (ctxt->profNr > 0)\r
-           ctxt->profTab[ctxt->profNr - 1] += total;\r
-    }\r
-    \r
-#ifdef WITH_DEBUGGER\r
-    if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (addCallResult)) {\r
-        xslDropCall();\r
-    }\r
-#endif\r
-}\r
-\r
-\r
-/**\r
- * xsltApplyOneTemplate:\r
- * @ctxt:  a XSLT process context\r
- * @contextNode:  the node in the source tree.\r
- * @list:  the nodes of a sequence constructor\r
- * @templ: not used\r
- * @params:  a set of parameters (xsl:param) or NULL\r
- *\r
- * Processes a sequence constructor on the current node in the source tree.\r
- *\r
- * @params are the already computed variable stack items; this function\r
- * pushes them on the variable stack, and pops them before exiting; it's\r
- * left to the caller to free or reuse @params afterwards. The initial\r
- * states of the variable stack will always be restored before this\r
- * function exits.\r
- * NOTE that this does *not* initiate a new distinct variable scope; i.e.\r
- * variables already on the stack are visible to the process. The caller's\r
- * side needs to start a new variable scope if needed (e.g. in exsl:function).\r
- *\r
- * @templ is obsolete and not used anymore (e.g. <exslt:function> does not\r
- * provide a @templ); a non-NULL @templ might raise an error in the future.\r
- *\r
- * BIG NOTE: This function is not intended to process the content of an\r
- * xsl:template; it does not expect xsl:param instructions in @list and\r
- * will report errors if found.\r
- *\r
- * Called by:\r
- *  - xsltEvalVariable() (variables.c)\r
- *  - exsltFuncFunctionFunction() (libexsl/functions.c)\r
- */\r
-void\r
-xsltApplyOneTemplate(xsltTransformContextPtr ctxt,\r
-                    xmlNodePtr contextNode,\r
-                     xmlNodePtr list,\r
-                    xsltTemplatePtr templ ATTRIBUTE_UNUSED,\r
-                     xsltStackElemPtr params)\r
-{\r
-    if ((ctxt == NULL) || (list == NULL))\r
-       return;\r
-    CHECK_STOPPED;\r
-\r
-    if (params) {\r
-       int oldVarsNr = ctxt->varsNr;\r
-\r
-       /*\r
-       * Push the given xsl:param(s) onto the variable stack.\r
-       */\r
-       while (params != NULL) {\r
-           xsltLocalVariablePush(ctxt, params, -1);\r
-           params = params->next;\r
-       }\r
-       xsltApplySequenceConstructor(ctxt, contextNode, list, templ);\r
-       /*\r
-       * Pop the given xsl:param(s) from the stack but don't free them.\r
-       */\r
-       xsltLocalVariablePop(ctxt, oldVarsNr, -2);\r
-    } else\r
-       xsltApplySequenceConstructor(ctxt, contextNode, list, templ);    \r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                 XSLT-1.1 extensions                                 *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltDocumentElem:\r
- * @ctxt:  an XSLT processing context\r
- * @node:  The current node\r
- * @inst:  the instruction in the stylesheet\r
- * @comp:  precomputed information\r
- *\r
- * Process an EXSLT/XSLT-1.1 document element\r
- */\r
-void\r
-xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                 xmlNodePtr inst, xsltStylePreCompPtr castedComp)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemDocumentPtr comp = (xsltStyleItemDocumentPtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif\r
-    xsltStylesheetPtr style = NULL;\r
-    int ret;\r
-    xmlChar *filename = NULL, *prop, *elements;\r
-    xmlChar *element, *end;\r
-    xmlDocPtr res = NULL;\r
-    xmlDocPtr oldOutput;\r
-    xmlNodePtr oldInsert, root;\r
-    const char *oldOutputFile;\r
-    xsltOutputType oldType;\r
-    xmlChar *URL = NULL;\r
-    const xmlChar *method;\r
-    const xmlChar *doctypePublic;\r
-    const xmlChar *doctypeSystem;\r
-    const xmlChar *version;\r
-\r
-    if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL))\r
-        return;\r
-\r
-    if (comp->filename == NULL) {\r
-\r
-        if (xmlStrEqual(inst->name, (const xmlChar *) "output")) {\r
-           /*\r
-           * The element "output" is in the namespace XSLT_SAXON_NAMESPACE\r
-           *   (http://icl.com/saxon)\r
-           * The @file is in no namespace.\r
-           */\r
-#ifdef WITH_XSLT_DEBUG_EXTRA\r
-            xsltGenericDebug(xsltGenericDebugContext,\r
-                             "Found saxon:output extension\n");\r
-#endif\r
-            URL = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                                 (const xmlChar *) "file",\r
-                                                 XSLT_SAXON_NAMESPACE);\r
-            \r
-           if (URL == NULL)\r
-               URL = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                                 (const xmlChar *) "href",\r
-                                                 XSLT_SAXON_NAMESPACE);\r
-        } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) {\r
-#ifdef WITH_XSLT_DEBUG_EXTRA\r
-            xsltGenericDebug(xsltGenericDebugContext,\r
-                             "Found xalan:write extension\n");\r
-#endif\r
-            URL = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                                 (const xmlChar *)\r
-                                                 "select",\r
-                                                 XSLT_XALAN_NAMESPACE);\r
-           if (URL != NULL) {\r
-               xmlXPathCompExprPtr cmp;\r
-               xmlChar *val;\r
-\r
-               /*\r
-                * Trying to handle bug #59212\r
-                * The value of the "select" attribute is an\r
-                * XPath expression.\r
-                * (see http://xml.apache.org/xalan-j/extensionslib.html#redirect) \r
-                */\r
-               cmp = xmlXPathCompile(URL);\r
-                val = xsltEvalXPathString(ctxt, cmp);\r
-               xmlXPathFreeCompExpr(cmp);\r
-               xmlFree(URL);\r
-               URL = val;\r
-           }\r
-           if (URL == NULL)\r
-               URL = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                                    (const xmlChar *)\r
-                                                    "file",\r
-                                                    XSLT_XALAN_NAMESPACE);\r
-           if (URL == NULL)\r
-               URL = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                                    (const xmlChar *)\r
-                                                    "href",\r
-                                                    XSLT_XALAN_NAMESPACE);\r
-        } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) {\r
-            URL = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                                 (const xmlChar *) "href",\r
-                                                 NULL);\r
-        }\r
-\r
-    } else {\r
-        URL = xmlStrdup(comp->filename);\r
-    }\r
-\r
-    if (URL == NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-                        "xsltDocumentElem: href/URI-Reference not found\n");\r
-       return;\r
-    }\r
-\r
-    /*\r
-     * If the computation failed, it's likely that the URL wasn't escaped\r
-     */\r
-    filename = xmlBuildURI(URL, (const xmlChar *) ctxt->outputFile);\r
-    if (filename == NULL) {\r
-       xmlChar *escURL;\r
-\r
-       escURL=xmlURIEscapeStr(URL, BAD_CAST ":/.?,");\r
-       if (escURL != NULL) {\r
-           filename = xmlBuildURI(escURL, (const xmlChar *) ctxt->outputFile);\r
-           xmlFree(escURL);\r
-       }\r
-    }\r
-\r
-    if (filename == NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-                        "xsltDocumentElem: URL computation failed for %s\n",\r
-                        URL);\r
-       xmlFree(URL);\r
-       return;\r
-    }\r
-\r
-    /*\r
-     * Security checking: can we write to this resource\r
-     */\r
-    if (ctxt->sec != NULL) {\r
-       ret = xsltCheckWrite(ctxt->sec, ctxt, filename);\r
-       if (ret == 0) {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-                "xsltDocumentElem: write rights for %s denied\n",\r
-                            filename);\r
-           xmlFree(URL);\r
-           xmlFree(filename);\r
-           return;\r
-       }\r
-    }\r
-\r
-    oldOutputFile = ctxt->outputFile;\r
-    oldOutput = ctxt->output;\r
-    oldInsert = ctxt->insert;\r
-    oldType = ctxt->type;\r
-    ctxt->outputFile = (const char *) filename;\r
-\r
-    style = xsltNewStylesheet();\r
-    if (style == NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-                         "xsltDocumentElem: out of memory\n");\r
-        goto error;\r
-    }\r
-\r
-    /*\r
-     * Version described in 1.1 draft allows full parameterization\r
-     * of the output.\r
-     */\r
-    prop = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                    (const xmlChar *) "version",\r
-                                    NULL);\r
-    if (prop != NULL) {\r
-       if (style->version != NULL)\r
-           xmlFree(style->version);\r
-       style->version = prop;\r
-    }\r
-    prop = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                    (const xmlChar *) "encoding",\r
-                                    NULL);\r
-    if (prop != NULL) {\r
-       if (style->encoding != NULL)\r
-           xmlFree(style->encoding);\r
-       style->encoding = prop;\r
-    }\r
-    prop = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                    (const xmlChar *) "method",\r
-                                    NULL);\r
-    if (prop != NULL) {\r
-       const xmlChar *URI;\r
-\r
-       if (style->method != NULL)\r
-           xmlFree(style->method);\r
-       style->method = NULL;\r
-       if (style->methodURI != NULL)\r
-           xmlFree(style->methodURI);\r
-       style->methodURI = NULL;\r
-\r
-       URI = xsltGetQNameURI(inst, &prop);\r
-       if (prop == NULL) {\r
-           if (style != NULL) style->errors++;\r
-       } else if (URI == NULL) {\r
-           if ((xmlStrEqual(prop, (const xmlChar *) "xml")) ||\r
-               (xmlStrEqual(prop, (const xmlChar *) "html")) ||\r
-               (xmlStrEqual(prop, (const xmlChar *) "text"))) {\r
-               style->method = prop;\r
-           } else {\r
-               xsltTransformError(ctxt, NULL, inst,\r
-                                "invalid value for method: %s\n", prop);\r
-               if (style != NULL) style->warnings++;\r
-           }\r
-       } else {\r
-           style->method = prop;\r
-           style->methodURI = xmlStrdup(URI);\r
-       }\r
-    }\r
-    prop = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                    (const xmlChar *)\r
-                                    "doctype-system", NULL);\r
-    if (prop != NULL) {\r
-       if (style->doctypeSystem != NULL)\r
-           xmlFree(style->doctypeSystem);\r
-       style->doctypeSystem = prop;\r
-    }\r
-    prop = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                    (const xmlChar *)\r
-                                    "doctype-public", NULL);\r
-    if (prop != NULL) {\r
-       if (style->doctypePublic != NULL)\r
-           xmlFree(style->doctypePublic);\r
-       style->doctypePublic = prop;\r
-    }\r
-    prop = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                    (const xmlChar *) "standalone",\r
-                                    NULL);\r
-    if (prop != NULL) {\r
-       if (xmlStrEqual(prop, (const xmlChar *) "yes")) {\r
-           style->standalone = 1;\r
-       } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {\r
-           style->standalone = 0;\r
-       } else {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-                            "invalid value for standalone: %s\n",\r
-                            prop);\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-       xmlFree(prop);\r
-    }\r
-\r
-    prop = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                    (const xmlChar *) "indent",\r
-                                    NULL);\r
-    if (prop != NULL) {\r
-       if (xmlStrEqual(prop, (const xmlChar *) "yes")) {\r
-           style->indent = 1;\r
-       } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {\r
-           style->indent = 0;\r
-       } else {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-                            "invalid value for indent: %s\n", prop);\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-       xmlFree(prop);\r
-    }\r
-\r
-    prop = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                    (const xmlChar *)\r
-                                    "omit-xml-declaration",\r
-                                    NULL);\r
-    if (prop != NULL) {\r
-       if (xmlStrEqual(prop, (const xmlChar *) "yes")) {\r
-           style->omitXmlDeclaration = 1;\r
-       } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {\r
-           style->omitXmlDeclaration = 0;\r
-       } else {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-                            "invalid value for omit-xml-declaration: %s\n",\r
-                            prop);\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-       xmlFree(prop);\r
-    }\r
-\r
-    elements = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                                        (const xmlChar *)\r
-                                        "cdata-section-elements",\r
-                                        NULL);\r
-    if (elements != NULL) {\r
-       if (style->stripSpaces == NULL)\r
-           style->stripSpaces = xmlHashCreate(10);\r
-       if (style->stripSpaces == NULL)\r
-           return;\r
-\r
-       element = elements;\r
-       while (*element != 0) {\r
-           while (IS_BLANK_CH(*element))\r
-               element++;\r
-           if (*element == 0)\r
-               break;\r
-           end = element;\r
-           while ((*end != 0) && (!IS_BLANK_CH(*end)))\r
-               end++;\r
-           element = xmlStrndup(element, end - element);\r
-           if (element) {\r
-               const xmlChar *URI;\r
-\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-               xsltGenericDebug(xsltGenericDebugContext,\r
-                                "add cdata section output element %s\n",\r
-                                element);\r
-#endif\r
-                URI = xsltGetQNameURI(inst, &element);\r
-\r
-               xmlHashAddEntry2(style->stripSpaces, element, URI,\r
-                               (xmlChar *) "cdata");\r
-               xmlFree(element);\r
-           }\r
-           element = end;\r
-       }\r
-       xmlFree(elements);\r
-    }\r
-\r
-    /*\r
-     * Create a new document tree and process the element template\r
-     */\r
-    XSLT_GET_IMPORT_PTR(method, style, method)\r
-    XSLT_GET_IMPORT_PTR(doctypePublic, style, doctypePublic)\r
-    XSLT_GET_IMPORT_PTR(doctypeSystem, style, doctypeSystem)\r
-    XSLT_GET_IMPORT_PTR(version, style, version)\r
-\r
-    if ((method != NULL) &&\r
-       (!xmlStrEqual(method, (const xmlChar *) "xml"))) {\r
-       if (xmlStrEqual(method, (const xmlChar *) "html")) {\r
-           ctxt->type = XSLT_OUTPUT_HTML;\r
-           if (((doctypePublic != NULL) || (doctypeSystem != NULL)))\r
-               res = htmlNewDoc(doctypeSystem, doctypePublic);\r
-           else {\r
-               if (version != NULL) {\r
-#ifdef XSLT_GENERATE_HTML_DOCTYPE\r
-                   xsltGetHTMLIDs(version, &doctypePublic, &doctypeSystem);\r
-#endif\r
-                }\r
-               res = htmlNewDocNoDtD(doctypeSystem, doctypePublic);\r
-           }\r
-           if (res == NULL)\r
-               goto error;\r
-           res->dict = ctxt->dict;\r
-           xmlDictReference(res->dict);\r
-       } else if (xmlStrEqual(method, (const xmlChar *) "xhtml")) {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-            "xsltDocumentElem: unsupported method xhtml\n",\r
-                            style->method);\r
-           ctxt->type = XSLT_OUTPUT_HTML;\r
-           res = htmlNewDocNoDtD(doctypeSystem, doctypePublic);\r
-           if (res == NULL)\r
-               goto error;\r
-           res->dict = ctxt->dict;\r
-           xmlDictReference(res->dict);\r
-       } else if (xmlStrEqual(method, (const xmlChar *) "text")) {\r
-           ctxt->type = XSLT_OUTPUT_TEXT;\r
-           res = xmlNewDoc(style->version);\r
-           if (res == NULL)\r
-               goto error;\r
-           res->dict = ctxt->dict;\r
-           xmlDictReference(res->dict);\r
-#ifdef WITH_XSLT_DEBUG\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-                     "reusing transformation dict for output\n");\r
-#endif\r
-       } else {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-                            "xsltDocumentElem: unsupported method %s\n",\r
-                            style->method);\r
-           goto error;\r
-       }\r
-    } else {\r
-       ctxt->type = XSLT_OUTPUT_XML;\r
-       res = xmlNewDoc(style->version);\r
-       if (res == NULL)\r
-           goto error;\r
-       res->dict = ctxt->dict;\r
-       xmlDictReference(res->dict);\r
-#ifdef WITH_XSLT_DEBUG\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-                     "reusing transformation dict for output\n");\r
-#endif\r
-    }\r
-    res->charset = XML_CHAR_ENCODING_UTF8;\r
-    if (style->encoding != NULL)\r
-       res->encoding = xmlStrdup(style->encoding);\r
-    ctxt->output = res;\r
-    ctxt->insert = (xmlNodePtr) res;\r
-    xsltApplySequenceConstructor(ctxt, node, inst->children, NULL);\r
-\r
-    /*\r
-     * Do some post processing work depending on the generated output\r
-     */\r
-    root = xmlDocGetRootElement(res);\r
-    if (root != NULL) {\r
-        const xmlChar *doctype = NULL;\r
-\r
-        if ((root->ns != NULL) && (root->ns->prefix != NULL))\r
-           doctype = xmlDictQLookup(ctxt->dict, root->ns->prefix, root->name);\r
-       if (doctype == NULL)\r
-           doctype = root->name;\r
-\r
-        /*\r
-         * Apply the default selection of the method\r
-         */\r
-        if ((method == NULL) &&\r
-            (root->ns == NULL) &&\r
-            (!xmlStrcasecmp(root->name, (const xmlChar *) "html"))) {\r
-            xmlNodePtr tmp;\r
-\r
-            tmp = res->children;\r
-            while ((tmp != NULL) && (tmp != root)) {\r
-                if (tmp->type == XML_ELEMENT_NODE)\r
-                    break;\r
-                if ((tmp->type == XML_TEXT_NODE) && (!xmlIsBlankNode(tmp)))\r
-                    break;\r
-               tmp = tmp->next;\r
-            }\r
-            if (tmp == root) {\r
-                ctxt->type = XSLT_OUTPUT_HTML;\r
-                res->type = XML_HTML_DOCUMENT_NODE;\r
-                if (((doctypePublic != NULL) || (doctypeSystem != NULL))) {\r
-                    res->intSubset = xmlCreateIntSubset(res, doctype,\r
-                                                        doctypePublic,\r
-                                                        doctypeSystem);\r
-#ifdef XSLT_GENERATE_HTML_DOCTYPE\r
-               } else if (version != NULL) {\r
-                    xsltGetHTMLIDs(version, &doctypePublic,\r
-                                   &doctypeSystem);\r
-                    if (((doctypePublic != NULL) || (doctypeSystem != NULL)))\r
-                        res->intSubset =\r
-                            xmlCreateIntSubset(res, doctype,\r
-                                               doctypePublic,\r
-                                               doctypeSystem);\r
-#endif\r
-                }\r
-            }\r
-\r
-        }\r
-        if (ctxt->type == XSLT_OUTPUT_XML) {\r
-            XSLT_GET_IMPORT_PTR(doctypePublic, style, doctypePublic)\r
-                XSLT_GET_IMPORT_PTR(doctypeSystem, style, doctypeSystem)\r
-                if (((doctypePublic != NULL) || (doctypeSystem != NULL)))\r
-                res->intSubset = xmlCreateIntSubset(res, doctype,\r
-                                                    doctypePublic,\r
-                                                    doctypeSystem);\r
-        }\r
-    }\r
-\r
-    /*\r
-     * Save the result\r
-     */\r
-    ret = xsltSaveResultToFilename((const char *) filename,\r
-                                   res, style, 0);\r
-    if (ret < 0) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-                         "xsltDocumentElem: unable to save to %s\n",\r
-                         filename);\r
-       ctxt->state = XSLT_STATE_ERROR;\r
-#ifdef WITH_XSLT_DEBUG_EXTRA\r
-    } else {\r
-        xsltGenericDebug(xsltGenericDebugContext,\r
-                         "Wrote %d bytes to %s\n", ret, filename);\r
-#endif\r
-    }\r
-\r
-  error:\r
-    ctxt->output = oldOutput;\r
-    ctxt->insert = oldInsert;\r
-    ctxt->type = oldType;\r
-    ctxt->outputFile = oldOutputFile;\r
-    if (URL != NULL)\r
-        xmlFree(URL);\r
-    if (filename != NULL)\r
-        xmlFree(filename);\r
-    if (style != NULL)\r
-        xsltFreeStylesheet(style);\r
-    if (res != NULL)\r
-        xmlFreeDoc(res);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Most of the XSLT-1.0 transformations                    *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltSort:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the node in the source tree.\r
- * @inst:  the xslt sort node\r
- * @comp:  precomputed information\r
- *\r
- * function attached to xsl:sort nodes, but this should not be\r
- * called directly\r
- */\r
-void\r
-xsltSort(xsltTransformContextPtr ctxt,\r
-       xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst,\r
-       xsltStylePreCompPtr comp) {\r
-    if (comp == NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-            "xsl:sort : compilation failed\n");\r
-       return;\r
-    }\r
-    xsltTransformError(ctxt, NULL, inst,\r
-        "xsl:sort : improper use this should not be reached\n");\r
-}\r
-\r
-/**\r
- * xsltCopy:\r
- * @ctxt:  an XSLT process context\r
- * @node:  the node in the source tree\r
- * @inst:  the element node of the XSLT-copy instruction\r
- * @comp:  computed information of the XSLT-copy instruction\r
- *\r
- * Execute the XSLT-copy instruction on the source node.\r
- */\r
-void\r
-xsltCopy(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-        xmlNodePtr inst, xsltStylePreCompPtr castedComp)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemCopyPtr comp = (xsltStyleItemCopyPtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif\r
-    xmlNodePtr copy, oldInsert;\r
-   \r
-    oldInsert = ctxt->insert;\r
-    if (ctxt->insert != NULL) {\r
-       switch (node->type) {\r
-           case XML_TEXT_NODE:\r
-           case XML_CDATA_SECTION_NODE:\r
-               /*\r
-                * This text comes from the stylesheet\r
-                * For stylesheets, the set of whitespace-preserving\r
-                * element names consists of just xsl:text.\r
-                */\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               if (node->type == XML_CDATA_SECTION_NODE) {\r
-                   XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,\r
-                        "xsltCopy: CDATA text %s\n", node->content));\r
-               } else {\r
-                   XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,\r
-                        "xsltCopy: text %s\n", node->content));\r
-                }\r
-#endif\r
-               xsltCopyText(ctxt, ctxt->insert, node, 0);\r
-               break;\r
-           case XML_DOCUMENT_NODE:\r
-           case XML_HTML_DOCUMENT_NODE:\r
-               break;\r
-           case XML_ELEMENT_NODE:\r
-               /*\r
-               * REVISIT NOTE: The "fake" is a doc-node, not an element node.\r
-               * REMOVED:\r
-               *   if (xmlStrEqual(node->name, BAD_CAST " fake node libxslt"))\r
-               *    return;\r
-               */              \r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,\r
-                                "xsltCopy: node %s\n", node->name));\r
-#endif\r
-               copy = xsltShallowCopyElem(ctxt, node, ctxt->insert, 0);\r
-               ctxt->insert = copy;\r
-               if (comp->use != NULL) {\r
-                   xsltApplyAttributeSet(ctxt, node, inst, comp->use);\r
-               }\r
-               break;\r
-           case XML_ATTRIBUTE_NODE: {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,\r
-                                "xsltCopy: attribute %s\n", node->name));\r
-#endif\r
-               /*\r
-               * REVISIT: We could also raise an error if the parent is not\r
-               * an element node.\r
-               * OPTIMIZE TODO: Can we set the value/children of the\r
-               * attribute without an intermediate copy of the string value?\r
-               */\r
-               xsltShallowCopyAttr(ctxt, inst, ctxt->insert, (xmlAttrPtr) node);               \r
-               break;\r
-           }\r
-           case XML_PI_NODE:\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,\r
-                                "xsltCopy: PI %s\n", node->name));\r
-#endif\r
-               copy = xmlNewDocPI(ctxt->insert->doc, node->name,\r
-                                  node->content);\r
-               xmlAddChild(ctxt->insert, copy);\r
-               break;\r
-           case XML_COMMENT_NODE:\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,\r
-                                "xsltCopy: comment\n"));\r
-#endif\r
-               copy = xmlNewComment(node->content);\r
-               xmlAddChild(ctxt->insert, copy);\r
-               break;\r
-           case XML_NAMESPACE_DECL:\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,\r
-                                "xsltCopy: namespace declaration\n"));\r
-#endif         \r
-               xsltShallowCopyNsNode(ctxt, inst, ctxt->insert, (xmlNsPtr)node);                     \r
-               break;\r
-           default:\r
-               break;\r
-\r
-       }\r
-    }\r
-\r
-    switch (node->type) {\r
-       case XML_DOCUMENT_NODE:\r
-       case XML_HTML_DOCUMENT_NODE:\r
-       case XML_ELEMENT_NODE:\r
-           xsltApplySequenceConstructor(ctxt, ctxt->node, inst->children,\r
-               NULL);\r
-           break;\r
-       default:\r
-           break;\r
-    }\r
-    ctxt->insert = oldInsert;\r
-}\r
-\r
-/**\r
- * xsltText:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the node in the source tree.\r
- * @inst:  the xslt text node\r
- * @comp:  precomputed information\r
- *\r
- * Process the xslt text node on the source node\r
- */\r
-void\r
-xsltText(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED,\r
-           xmlNodePtr inst, xsltStylePreCompPtr comp ATTRIBUTE_UNUSED) {\r
-    if ((inst->children != NULL) && (comp != NULL)) {\r
-       xmlNodePtr text = inst->children;\r
-       xmlNodePtr copy;\r
-\r
-       while (text != NULL) {\r
-           if ((text->type != XML_TEXT_NODE) &&\r
-                (text->type != XML_CDATA_SECTION_NODE)) {\r
-               xsltTransformError(ctxt, NULL, inst,\r
-                                "xsl:text content problem\n");\r
-               break;\r
-           }\r
-           copy = xmlNewDocText(ctxt->output, text->content);\r
-           if (text->type != XML_CDATA_SECTION_NODE) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-               xsltGenericDebug(xsltGenericDebugContext,\r
-                    "Disable escaping: %s\n", text->content);\r
-#endif\r
-               copy->name = xmlStringTextNoenc;\r
-           }\r
-           xmlAddChild(ctxt->insert, copy);\r
-           text = text->next;\r
-       }\r
-    }\r
-}\r
-\r
-/**\r
- * xsltElement:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the node in the source tree.\r
- * @inst:  the xslt element node\r
- * @comp:  precomputed information\r
- *\r
- * Process the xslt element node on the source node\r
- */\r
-void\r
-xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-           xmlNodePtr inst, xsltStylePreCompPtr castedComp) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemElementPtr comp = (xsltStyleItemElementPtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif\r
-    xmlChar *prop = NULL;\r
-    const xmlChar *name, *prefix = NULL, *nsName = NULL;    \r
-    xmlNodePtr copy;\r
-    xmlNodePtr oldInsert;\r
-\r
-    if (ctxt->insert == NULL)\r
-       return;\r
-\r
-    /* \r
-    * A comp->has_name == 0 indicates that we need to skip this instruction,\r
-    * since it was evaluated to be invalid already during compilation.\r
-    */\r
-    if (!comp->has_name)\r
-        return;\r
-\r
-    /*\r
-     * stack and saves\r
-     */\r
-    oldInsert = ctxt->insert;\r
-\r
-    if (comp->name == NULL) {\r
-       /* TODO: fix attr acquisition wrt to the XSLT namespace */\r
-        prop = xsltEvalAttrValueTemplate(ctxt, inst,\r
-           (const xmlChar *) "name", XSLT_NAMESPACE);\r
-        if (prop == NULL) {\r
-            xsltTransformError(ctxt, NULL, inst,\r
-               "xsl:element: The attribute 'name' is missing.\n");\r
-            goto error;\r
-        }\r
-       if (xmlValidateQName(prop, 0)) {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-               "xsl:element: The effective name '%s' is not a "\r
-               "valid QName.\n", prop);\r
-           /* we fall through to catch any further errors, if possible */\r
-       }\r
-       name = xsltSplitQName(ctxt->dict, prop, &prefix);\r
-       xmlFree(prop);\r
-       if ((prefix != NULL) &&\r
-           (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)))\r
-       {\r
-           /*\r
-           * TODO: Should we really disallow an "xml" prefix?\r
-           */\r
-           goto error;\r
-       }\r
-    } else {\r
-       /*\r
-       * The "name" value was static.\r
-       */\r
-#ifdef XSLT_REFACTORED\r
-       prefix = comp->nsPrefix;\r
-       name = comp->name;\r
-#else  \r
-       name = xsltSplitQName(ctxt->dict, comp->name, &prefix);\r
-#endif\r
-    }\r
-    \r
-    /*\r
-     * Create the new element\r
-     */\r
-    if (ctxt->output->dict == ctxt->dict) {\r
-       copy = xmlNewDocNodeEatName(ctxt->output, NULL, (xmlChar *)name, NULL);\r
-    } else {\r
-       copy = xmlNewDocNode(ctxt->output, NULL, (xmlChar *)name, NULL);\r
-    }\r
-    if (copy == NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-           "xsl:element : creation of %s failed\n", name);\r
-       return;\r
-    }\r
-    xmlAddChild(ctxt->insert, copy);    \r
-\r
-    /*\r
-    * Namespace\r
-    * ---------\r
-    */\r
-    if (comp->has_ns) {         \r
-       if (comp->ns != NULL) {\r
-           /*\r
-           * No AVT; just plain text for the namespace name.\r
-           */\r
-           if (comp->ns[0] != 0)\r
-               nsName = comp->ns;\r
-       } else {\r
-           xmlChar *tmpNsName;\r
-           /*\r
-           * Eval the AVT.\r
-           */\r
-           /* TODO: check attr acquisition wrt to the XSLT namespace */\r
-           tmpNsName = xsltEvalAttrValueTemplate(ctxt, inst,\r
-               (const xmlChar *) "namespace", XSLT_NAMESPACE); \r
-           /*\r
-           * SPEC XSLT 1.0:\r
-           *  "If the string is empty, then the expanded-name of the\r
-           *  attribute has a null namespace URI."\r
-           */\r
-           if ((tmpNsName != NULL) && (tmpNsName[0] != 0))\r
-               nsName = xmlDictLookup(ctxt->dict, BAD_CAST tmpNsName, -1);\r
-           xmlFree(tmpNsName);         \r
-       };          \r
-    } else {\r
-       xmlNsPtr ns;\r
-       /*\r
-       * SPEC XSLT 1.0:\r
-       *  "If the namespace attribute is not present, then the QName is\r
-       *  expanded into an expanded-name using the namespace declarations\r
-       *  in effect for the xsl:element element, including any default\r
-       *  namespace declaration.\r
-       */      \r
-       ns = xmlSearchNs(inst->doc, inst, prefix);\r
-       if (ns == NULL) {\r
-           /*\r
-           * TODO: Check this in the compilation layer in case it's a\r
-           * static value.\r
-           */\r
-           if (prefix != NULL) {\r
-               xsltTransformError(ctxt, NULL, inst,\r
-                   "xsl:element: The QName '%s:%s' has no "\r
-                   "namespace binding in scope in the stylesheet; "\r
-                   "this is an error, since the namespace was not "\r
-                   "specified by the instruction itself.\n", prefix, name);\r
-           }\r
-       } else\r
-           nsName = ns->href;  \r
-    }\r
-    /*\r
-    * Find/create a matching ns-decl in the result tree.\r
-    */\r
-    if (nsName != NULL) {\r
-       copy->ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix, copy);\r
-    } else if ((copy->parent != NULL) &&\r
-       (copy->parent->type == XML_ELEMENT_NODE) &&\r
-       (copy->parent->ns != NULL))\r
-    {\r
-       /*\r
-       * "Undeclare" the default namespace.\r
-       */\r
-       xsltGetSpecialNamespace(ctxt, inst, NULL, NULL, copy);\r
-    }\r
-\r
-    ctxt->insert = copy;\r
-\r
-    if (comp->has_use) {\r
-       if (comp->use != NULL) {\r
-           xsltApplyAttributeSet(ctxt, node, inst, comp->use);\r
-       } else {\r
-           xmlChar *attrSets = NULL;\r
-           /*\r
-           * BUG TODO: use-attribute-sets is not a value template.\r
-           *  use-attribute-sets = qnames\r
-           */\r
-           attrSets = xsltEvalAttrValueTemplate(ctxt, inst,\r
-               (const xmlChar *)"use-attribute-sets", NULL);\r
-           if (attrSets != NULL) {\r
-               xsltApplyAttributeSet(ctxt, node, inst, attrSets);\r
-               xmlFree(attrSets);\r
-           }\r
-       }\r
-    }\r
-    /*\r
-    * Instantiate the sequence constructor.\r
-    */\r
-    if (inst->children != NULL)\r
-       xsltApplySequenceConstructor(ctxt, ctxt->node, inst->children,\r
-           NULL);\r
-\r
-error:\r
-    ctxt->insert = oldInsert;\r
-    return;    \r
-}\r
-\r
-\r
-/**\r
- * xsltComment:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the node in the source tree.\r
- * @inst:  the xslt comment node\r
- * @comp:  precomputed information\r
- *\r
- * Process the xslt comment node on the source node\r
- */\r
-void\r
-xsltComment(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                  xmlNodePtr inst, xsltStylePreCompPtr comp ATTRIBUTE_UNUSED) {\r
-    xmlChar *value = NULL;\r
-    xmlNodePtr commentNode;\r
-    int len;\r
-    \r
-    value = xsltEvalTemplateString(ctxt, node, inst);\r
-    /* TODO: use or generate the compiled form */\r
-    len = xmlStrlen(value);\r
-    if (len > 0) {\r
-        if ((value[len-1] == '-') || \r
-           (xmlStrstr(value, BAD_CAST "--"))) {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-                   "xsl:comment : '--' or ending '-' not allowed in comment\n");\r
-           /* fall through to try to catch further errors */\r
-       }\r
-    }\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    if (value == NULL) {\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_COMMENT,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltComment: empty\n"));\r
-    } else {\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_COMMENT,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltComment: content %s\n", value));\r
-    }\r
-#endif\r
-\r
-    commentNode = xmlNewComment(value);\r
-    xmlAddChild(ctxt->insert, commentNode);\r
-\r
-    if (value != NULL)\r
-       xmlFree(value);\r
-}\r
-\r
-/**\r
- * xsltProcessingInstruction:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the node in the source tree.\r
- * @inst:  the xslt processing-instruction node\r
- * @comp:  precomputed information\r
- *\r
- * Process the xslt processing-instruction node on the source node\r
- */\r
-void\r
-xsltProcessingInstruction(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                  xmlNodePtr inst, xsltStylePreCompPtr castedComp) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemPIPtr comp = (xsltStyleItemPIPtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif\r
-    const xmlChar *name;\r
-    xmlChar *value = NULL;\r
-    xmlNodePtr pi;\r
-\r
-\r
-    if (ctxt->insert == NULL)\r
-       return;\r
-    if (comp->has_name == 0)\r
-       return;\r
-    if (comp->name == NULL) {\r
-       name = xsltEvalAttrValueTemplate(ctxt, inst,\r
-                           (const xmlChar *)"name", NULL);\r
-       if (name == NULL) {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-                "xsl:processing-instruction : name is missing\n");\r
-           goto error;\r
-       }\r
-    } else {\r
-       name = comp->name;\r
-    }\r
-    /* TODO: check that it's both an an NCName and a PITarget. */\r
-\r
-\r
-    value = xsltEvalTemplateString(ctxt, node, inst);\r
-    if (xmlStrstr(value, BAD_CAST "?>") != NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-            "xsl:processing-instruction: '?>' not allowed within PI content\n");\r
-       goto error;\r
-    }\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    if (value == NULL) {\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_PI,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltProcessingInstruction: %s empty\n", name));\r
-    } else {\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_PI,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltProcessingInstruction: %s content %s\n", name, value));\r
-    }\r
-#endif\r
-\r
-    pi = xmlNewDocPI(ctxt->insert->doc, name, value);\r
-    xmlAddChild(ctxt->insert, pi);\r
-\r
-error:\r
-    if ((name != NULL) && (name != comp->name))\r
-        xmlFree((xmlChar *) name);\r
-    if (value != NULL)\r
-       xmlFree(value);\r
-}\r
-\r
-/**\r
- * xsltCopyOf:\r
- * @ctxt:  an XSLT transformation context\r
- * @node:  the current node in the source tree\r
- * @inst:  the element node of the XSLT copy-of instruction \r
- * @comp:  precomputed information of the XSLT copy-of instruction\r
- *\r
- * Process the XSLT copy-of instruction.\r
- */\r
-void\r
-xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                  xmlNodePtr inst, xsltStylePreCompPtr castedComp) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemCopyOfPtr comp = (xsltStyleItemCopyOfPtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif\r
-    xmlXPathObjectPtr res = NULL;\r
-    xmlNodeSetPtr list = NULL;\r
-    int i;\r
-    xmlDocPtr oldXPContextDoc;\r
-    xmlNsPtr *oldXPNamespaces;\r
-    xmlNodePtr oldXPContextNode;\r
-    int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;\r
-    xmlXPathContextPtr xpctxt;\r
-\r
-    if ((ctxt == NULL) || (node == NULL) || (inst == NULL))\r
-       return;\r
-    if ((comp == NULL) || (comp->select == NULL) || (comp->comp == NULL)) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-            "xsl:copy-of : compilation failed\n");\r
-       return;\r
-    }\r
-\r
-     /*\r
-    * SPEC XSLT 1.0:\r
-    *  "The xsl:copy-of element can be used to insert a result tree\r
-    *  fragment into the result tree, without first converting it to\r
-    *  a string as xsl:value-of does (see [7.6.1 Generating Text with\r
-    *  xsl:value-of]). The required select attribute contains an\r
-    *  expression. When the result of evaluating the expression is a\r
-    *  result tree fragment, the complete fragment is copied into the\r
-    *  result tree. When the result is a node-set, all the nodes in the\r
-    *  set are copied in document order into the result tree; copying\r
-    *  an element node copies the attribute nodes, namespace nodes and\r
-    *  children of the element node as well as the element node itself;\r
-    *  a root node is copied by copying its children. When the result\r
-    *  is neither a node-set nor a result tree fragment, the result is\r
-    *  converted to a string and then inserted into the result tree,\r
-    *  as with xsl:value-of.\r
-    */\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_COPY_OF,xsltGenericDebug(xsltGenericDebugContext,\r
-        "xsltCopyOf: select %s\n", comp->select));\r
-#endif\r
-\r
-    /*\r
-    * Evaluate the "select" expression.\r
-    */\r
-    xpctxt = ctxt->xpathCtxt;\r
-    oldXPContextDoc = xpctxt->doc;\r
-    oldXPContextNode = xpctxt->node;\r
-    oldXPProximityPosition = xpctxt->proximityPosition;\r
-    oldXPContextSize = xpctxt->contextSize;\r
-    oldXPNsNr = xpctxt->nsNr;\r
-    oldXPNamespaces = xpctxt->namespaces;\r
-    \r
-    xpctxt->node = node;\r
-    if (comp != NULL) {\r
-\r
-#ifdef XSLT_REFACTORED\r
-       if (comp->inScopeNs != NULL) {\r
-           xpctxt->namespaces = comp->inScopeNs->list;\r
-           xpctxt->nsNr = comp->inScopeNs->xpathNumber;\r
-       } else {\r
-           xpctxt->namespaces = NULL;\r
-           xpctxt->nsNr = 0;\r
-       }\r
-#else\r
-       xpctxt->namespaces = comp->nsList;\r
-       xpctxt->nsNr = comp->nsNr;\r
-#endif\r
-    } else {\r
-       xpctxt->namespaces = NULL;\r
-       xpctxt->nsNr = 0;\r
-    }\r
-\r
-    res = xmlXPathCompiledEval(comp->comp, xpctxt);\r
-\r
-    xpctxt->doc = oldXPContextDoc;\r
-    xpctxt->node = oldXPContextNode;\r
-    xpctxt->contextSize = oldXPContextSize;\r
-    xpctxt->proximityPosition = oldXPProximityPosition;        \r
-    xpctxt->nsNr = oldXPNsNr;\r
-    xpctxt->namespaces = oldXPNamespaces;\r
-\r
-    if (res != NULL) {\r
-       if (res->type == XPATH_NODESET) {\r
-           /*\r
-           * Node-set\r
-           * --------\r
-           */\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_COPY_OF,xsltGenericDebug(xsltGenericDebugContext,\r
-                "xsltCopyOf: result is a node set\n"));\r
-#endif\r
-           list = res->nodesetval;\r
-           if (list != NULL) {\r
-               xmlNodePtr cur;\r
-               /*\r
-               * The list is already sorted in document order by XPath.\r
-               * Append everything in this order under ctxt->insert.\r
-               */\r
-               for (i = 0;i < list->nodeNr;i++) {\r
-                   cur = list->nodeTab[i];\r
-                   if (cur == NULL)\r
-                       continue;\r
-                   if ((cur->type == XML_DOCUMENT_NODE) ||\r
-                       (cur->type == XML_HTML_DOCUMENT_NODE))\r
-                   {\r
-                       xsltCopyTreeList(ctxt, inst,\r
-                           cur->children, ctxt->insert, 0, 0);\r
-                   } else if (cur->type == XML_ATTRIBUTE_NODE) {\r
-                       xsltShallowCopyAttr(ctxt, inst,\r
-                           ctxt->insert, (xmlAttrPtr) cur);\r
-                   } else {\r
-                       xsltCopyTreeInternal(ctxt, inst,\r
-                           cur, ctxt->insert, 0, 0);\r
-                   }\r
-               }\r
-           }\r
-       } else if (res->type == XPATH_XSLT_TREE) {\r
-           /*\r
-           * Result tree fragment\r
-           * --------------------\r
-           * E.g. via <xsl:variable ...><foo/></xsl:variable>\r
-           * Note that the root node of such trees is an xmlDocPtr in Libxslt.\r
-           */\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_COPY_OF,xsltGenericDebug(xsltGenericDebugContext,\r
-                "xsltCopyOf: result is a result tree fragment\n"));\r
-#endif     \r
-           list = res->nodesetval;\r
-           if ((list != NULL) && (list->nodeTab != NULL) &&\r
-               (list->nodeTab[0] != NULL) &&\r
-               (IS_XSLT_REAL_NODE(list->nodeTab[0])))\r
-           {\r
-               xsltCopyTreeList(ctxt, inst,\r
-                   list->nodeTab[0]->children, ctxt->insert, 0, 0);\r
-           }\r
-       } else {\r
-           xmlChar *value = NULL;\r
-           /*\r
-           * Convert to a string.\r
-           */\r
-           value = xmlXPathCastToString(res);\r
-           if (value == NULL) {\r
-               xsltTransformError(ctxt, NULL, inst,\r
-                   "Internal error in xsltCopyOf(): "\r
-                   "failed to cast an XPath object to string.\n");\r
-               ctxt->state = XSLT_STATE_STOPPED;\r
-           } else {\r
-               if (value[0] != 0) {\r
-                   /*\r
-                   * Append content as text node.\r
-                   */\r
-                   xsltCopyTextString(ctxt, ctxt->insert, value, 0);\r
-               }\r
-               \r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               XSLT_TRACE(ctxt,XSLT_TRACE_COPY_OF,xsltGenericDebug(xsltGenericDebugContext,\r
-                   "xsltCopyOf: result %s\n", res->stringval));\r
-#endif\r
-           }\r
-       }\r
-    } else {\r
-       ctxt->state = XSLT_STATE_STOPPED;\r
-    }\r
-\r
-    if (res != NULL)\r
-       xmlXPathFreeObject(res);\r
-}\r
-\r
-/**\r
- * xsltValueOf:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the node in the source tree.\r
- * @inst:  the xslt value-of node\r
- * @comp:  precomputed information\r
- *\r
- * Process the xslt value-of node on the source node\r
- */\r
-void\r
-xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                  xmlNodePtr inst, xsltStylePreCompPtr castedComp)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemValueOfPtr comp = (xsltStyleItemValueOfPtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif\r
-    xmlXPathObjectPtr res = NULL;\r
-    xmlNodePtr copy = NULL;\r
-    xmlChar *value = NULL;\r
-    xmlDocPtr oldXPContextDoc;\r
-    xmlNsPtr *oldXPNamespaces;\r
-    xmlNodePtr oldXPContextNode;\r
-    int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;\r
-    xmlXPathContextPtr xpctxt;\r
-\r
-    if ((ctxt == NULL) || (node == NULL) || (inst == NULL))\r
-       return;\r
-\r
-    if ((comp == NULL) || (comp->select == NULL) || (comp->comp == NULL)) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-           "Internal error in xsltValueOf(): "\r
-           "The XSLT 'value-of' instruction was not compiled.\n");\r
-       return;\r
-    }\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_VALUE_OF,xsltGenericDebug(xsltGenericDebugContext,\r
-        "xsltValueOf: select %s\n", comp->select));\r
-#endif\r
-\r
-    xpctxt = ctxt->xpathCtxt;\r
-    oldXPContextDoc = xpctxt->doc;\r
-    oldXPContextNode = xpctxt->node;\r
-    oldXPProximityPosition = xpctxt->proximityPosition;\r
-    oldXPContextSize = xpctxt->contextSize;\r
-    oldXPNsNr = xpctxt->nsNr;\r
-    oldXPNamespaces = xpctxt->namespaces;\r
-    \r
-    xpctxt->node = node;\r
-    if (comp != NULL) {\r
-\r
-#ifdef XSLT_REFACTORED\r
-       if (comp->inScopeNs != NULL) {\r
-           xpctxt->namespaces = comp->inScopeNs->list;\r
-           xpctxt->nsNr = comp->inScopeNs->xpathNumber;\r
-       } else {\r
-           xpctxt->namespaces = NULL;\r
-           xpctxt->nsNr = 0;\r
-       }\r
-#else\r
-       xpctxt->namespaces = comp->nsList;\r
-       xpctxt->nsNr = comp->nsNr;\r
-#endif\r
-    } else {\r
-       xpctxt->namespaces = NULL;\r
-       xpctxt->nsNr = 0;\r
-    }\r
-\r
-    res = xmlXPathCompiledEval(comp->comp, xpctxt);\r
-\r
-    xpctxt->doc = oldXPContextDoc;\r
-    xpctxt->node = oldXPContextNode;\r
-    xpctxt->contextSize = oldXPContextSize;\r
-    xpctxt->proximityPosition = oldXPProximityPosition;        \r
-    xpctxt->nsNr = oldXPNsNr;\r
-    xpctxt->namespaces = oldXPNamespaces;\r
-\r
-    /*\r
-    * Cast the XPath object to string.\r
-    */\r
-    if (res != NULL) {\r
-       value = xmlXPathCastToString(res);\r
-       if (value == NULL) {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-               "Internal error in xsltValueOf(): "\r
-               "failed to cast an XPath object to string.\n");\r
-           ctxt->state = XSLT_STATE_STOPPED;\r
-           goto error;\r
-       }\r
-       if (value[0] != 0) {\r
-           copy = xsltCopyTextString(ctxt,\r
-               ctxt->insert, value, comp->noescape);\r
-       }\r
-    } else {\r
-       xsltTransformError(ctxt, NULL, inst,        \r
-           "XPath evaluation returned no result.\n");\r
-       ctxt->state = XSLT_STATE_STOPPED;\r
-       goto error;     \r
-    }\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    if (value) {    \r
-       XSLT_TRACE(ctxt,XSLT_TRACE_VALUE_OF,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltValueOf: result '%s'\n", value));\r
-    }\r
-#endif\r
-\r
-error:\r
-    if (value != NULL)\r
-       xmlFree(value);\r
-    if (res != NULL)\r
-       xmlXPathFreeObject(res);\r
-}\r
-\r
-/**\r
- * xsltNumber:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the node in the source tree.\r
- * @inst:  the xslt number node\r
- * @comp:  precomputed information\r
- *\r
- * Process the xslt number node on the source node\r
- */\r
-void\r
-xsltNumber(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-          xmlNodePtr inst, xsltStylePreCompPtr castedComp)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemNumberPtr comp = (xsltStyleItemNumberPtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif\r
-    if (comp == NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-            "xsl:number : compilation failed\n");\r
-       return;\r
-    }\r
-\r
-    if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL))\r
-       return;\r
-\r
-    comp->numdata.doc = inst->doc;\r
-    comp->numdata.node = inst;\r
-    \r
-    xsltNumberFormat(ctxt, &comp->numdata, node);\r
-}\r
-\r
-/**\r
- * xsltApplyImports:\r
- * @ctxt:  an XSLT transformation context\r
- * @contextNode:  the current node in the source tree.\r
- * @inst:  the element node of the XSLT 'apply-imports' instruction\r
- * @comp:  the compiled instruction\r
- *\r
- * Process the XSLT apply-imports element.\r
- */\r
-void\r
-xsltApplyImports(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,\r
-                xmlNodePtr inst,\r
-                xsltStylePreCompPtr comp ATTRIBUTE_UNUSED)\r
-{\r
-    xsltTemplatePtr templ;\r
-\r
-    if ((ctxt == NULL) || (inst == NULL))\r
-       return;\r
-\r
-    if (comp == NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-           "Internal error in xsltApplyImports(): "\r
-           "The XSLT 'apply-imports' instruction was not compiled.\n");\r
-       return;\r
-    }\r
-    /*\r
-    * NOTE that ctxt->currentTemplateRule and ctxt->templ is not the\r
-    * same; the former is the "Current Template Rule" as defined by the\r
-    * XSLT spec, the latter is simply the template struct being\r
-    * currently processed.\r
-    */\r
-    if (ctxt->currentTemplateRule == NULL) {\r
-       /*\r
-       * SPEC XSLT 2.0:\r
-       * "[ERR XTDE0560] It is a non-recoverable dynamic error if\r
-       *  xsl:apply-imports or xsl:next-match is evaluated when the\r
-       *  current template rule is null."\r
-       */\r
-       xsltTransformError(ctxt, NULL, inst,\r
-            "It is an error to call 'apply-imports' "\r
-            "when there's no current template rule.\n");\r
-       return;\r
-    }\r
-    /*\r
-    * TODO: Check if this is correct.\r
-    */\r
-    templ = xsltGetTemplate(ctxt, contextNode,\r
-       ctxt->currentTemplateRule->style);\r
-\r
-    if (templ != NULL) {\r
-       xsltTemplatePtr oldCurTemplRule = ctxt->currentTemplateRule;\r
-       /*\r
-       * Set the current template rule.\r
-       */\r
-       ctxt->currentTemplateRule = templ;\r
-       /*\r
-       * URGENT TODO: Need xsl:with-param be handled somehow here?\r
-       */\r
-       xsltApplyXSLTTemplate(ctxt, contextNode, templ->content,\r
-           templ, NULL);\r
-\r
-       ctxt->currentTemplateRule = oldCurTemplRule;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltCallTemplate:\r
- * @ctxt:  a XSLT transformation context\r
- * @node:  the "current node" in the source tree\r
- * @inst:  the XSLT 'call-template' instruction\r
- * @comp:  the compiled information of the instruction\r
- *\r
- * Processes the XSLT call-template instruction on the source node.\r
- */\r
-void\r
-xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                  xmlNodePtr inst, xsltStylePreCompPtr castedComp)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemCallTemplatePtr comp =\r
-       (xsltStyleItemCallTemplatePtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif\r
-    xsltStackElemPtr withParams = NULL;\r
-\r
-    if (ctxt->insert == NULL)\r
-       return;\r
-    if (comp == NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-            "The XSLT 'call-template' instruction was not compiled.\n");\r
-       return;\r
-    }\r
-\r
-    /*\r
-     * The template must have been precomputed\r
-     */\r
-    if (comp->templ == NULL) {\r
-       comp->templ = xsltFindTemplate(ctxt, comp->name, comp->ns);\r
-       if (comp->templ == NULL) {\r
-           if (comp->ns != NULL) {\r
-               xsltTransformError(ctxt, NULL, inst,\r
-                       "The called template '{%s}%s' was not found.\n",\r
-                       comp->ns, comp->name);\r
-           } else {\r
-               xsltTransformError(ctxt, NULL, inst,\r
-                       "The called template '%s' was not found.\n",\r
-                       comp->name);\r
-           }\r
-           return;\r
-       }\r
-    }\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    if ((comp != NULL) && (comp->name != NULL))\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_CALL_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,\r
-                        "call-template: name %s\n", comp->name));\r
-#endif\r
-\r
-    if (inst->children) {\r
-       xmlNodePtr cur;\r
-       xsltStackElemPtr param;\r
-\r
-       cur = inst->children;\r
-       while (cur != NULL) {\r
-#ifdef WITH_DEBUGGER\r
-           if (ctxt->debugStatus != XSLT_DEBUG_NONE)\r
-               xslHandleDebugger(cur, node, comp->templ, ctxt);\r
-#endif\r
-           if (ctxt->state == XSLT_STATE_STOPPED) break;\r
-           /*\r
-           * TODO: The "with-param"s could be part of the "call-template"\r
-           *   structure. Avoid to "search" for params dynamically\r
-           *   in the XML tree every time.\r
-           */\r
-           if (IS_XSLT_ELEM(cur)) {\r
-               if (IS_XSLT_NAME(cur, "with-param")) {\r
-                   param = xsltParseStylesheetCallerParam(ctxt, cur);\r
-                   if (param != NULL) {\r
-                       param->next = withParams;\r
-                       withParams = param;\r
-                   }\r
-               } else {\r
-                   xsltGenericError(xsltGenericErrorContext,\r
-                       "xsl:call-template: misplaced xsl:%s\n", cur->name);\r
-               }\r
-           } else {\r
-               xsltGenericError(xsltGenericErrorContext,\r
-                   "xsl:call-template: misplaced %s element\n", cur->name);\r
-           }\r
-           cur = cur->next;\r
-       }\r
-    }\r
-    /*\r
-     * Create a new frame using the params first     \r
-     */\r
-    xsltApplyXSLTTemplate(ctxt, node, comp->templ->content, comp->templ,\r
-       withParams);\r
-    if (withParams != NULL)\r
-       xsltFreeStackElemList(withParams);\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    if ((comp != NULL) && (comp->name != NULL))\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_CALL_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,\r
-                        "call-template returned: name %s\n", comp->name));\r
-#endif\r
-}\r
-\r
-/**\r
- * xsltApplyTemplates:\r
- * @ctxt:  a XSLT transformation context\r
- * @node:  the 'current node' in the source tree\r
- * @inst:  the element node of an XSLT 'apply-templates' instruction\r
- * @comp:  the compiled instruction\r
- *\r
- * Processes the XSLT 'apply-templates' instruction on the current node.\r
- */\r
-void\r
-xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,\r
-                  xmlNodePtr inst, xsltStylePreCompPtr castedComp)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemApplyTemplatesPtr comp =\r
-       (xsltStyleItemApplyTemplatesPtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif\r
-    int i;\r
-    xmlNodePtr cur, delNode = NULL, oldContextNode;    \r
-    xmlNodeSetPtr list = NULL, oldList;\r
-    xsltStackElemPtr withParams = NULL;\r
-    int oldXPProximityPosition, oldXPContextSize;\r
-    const xmlChar *oldMode, *oldModeURI;\r
-    xmlDocPtr oldDoc;\r
-    xsltDocumentPtr oldDocInfo;\r
-    xmlXPathContextPtr xpctxt;\r
-\r
-    if (comp == NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-            "xsl:apply-templates : compilation failed\n");\r
-       return;\r
-    }\r
-    if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL))\r
-       return;\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    if ((node != NULL) && (node->name != NULL))\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltApplyTemplates: node: '%s'\n", node->name));\r
-#endif\r
-\r
-    xpctxt = ctxt->xpathCtxt;   \r
-    /*\r
-    * Save context states.\r
-    */\r
-    oldContextNode = ctxt->node;\r
-    oldMode = ctxt->mode;\r
-    oldModeURI = ctxt->modeURI;    \r
-    oldDocInfo = ctxt->document;\r
-    oldDoc = ctxt->tmpDoc;\r
-    oldList = ctxt->nodeList;    \r
-\r
-    /*\r
-     * The xpath context size and proximity position, as\r
-     * well as the xpath and context documents, may be changed\r
-     * so we save their initial state and will restore on exit\r
-     */    \r
-    oldXPContextSize = xpctxt->contextSize;\r
-    oldXPProximityPosition = xpctxt->proximityPosition;\r
-\r
-    /*\r
-    * Set up contexts.\r
-    */\r
-    ctxt->mode = comp->mode;\r
-    ctxt->modeURI = comp->modeURI;\r
-\r
-    if (comp->select != NULL) {        \r
-       xmlXPathObjectPtr res = NULL;\r
-\r
-       if (comp->comp == NULL) {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-                "xsl:apply-templates : compilation failed\n");\r
-           goto error;\r
-       }\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltApplyTemplates: select %s\n", comp->select));\r
-#endif\r
-\r
-       /*\r
-       * Set up XPath.\r
-       */\r
-       xpctxt->node = node; /* Set the "context node" */\r
-#ifdef XSLT_REFACTORED\r
-       if (comp->inScopeNs != NULL) {\r
-           xpctxt->namespaces = comp->inScopeNs->list;\r
-           xpctxt->nsNr = comp->inScopeNs->xpathNumber;\r
-       } else {\r
-           xpctxt->namespaces = NULL;\r
-           xpctxt->nsNr = 0;\r
-       }\r
-#else\r
-       xpctxt->namespaces = comp->nsList;\r
-       xpctxt->nsNr = comp->nsNr;\r
-#endif\r
-       res = xmlXPathCompiledEval(comp->comp, xpctxt);\r
-\r
-       xpctxt->contextSize = oldXPContextSize;\r
-       xpctxt->proximityPosition = oldXPProximityPosition;\r
-       if (res != NULL) {\r
-           if (res->type == XPATH_NODESET) {\r
-               list = res->nodesetval; /* consume the node set */\r
-               res->nodesetval = NULL; \r
-           } else {\r
-               xsltTransformError(ctxt, NULL, inst,\r
-                   "The 'select' expression did not evaluate to a "\r
-                   "node set.\n");\r
-               ctxt->state = XSLT_STATE_STOPPED;\r
-               xmlXPathFreeObject(res);\r
-               goto error;\r
-           }\r
-           xmlXPathFreeObject(res);\r
-           /*\r
-           * Note: An xsl:apply-templates with a 'select' attribute,\r
-           * can change the current source doc.\r
-           */      \r
-       } else {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-               "Failed to evaluate the 'select' expression.\n");\r
-           ctxt->state = XSLT_STATE_STOPPED;\r
-           goto error;\r
-       }          \r
-       if (list == NULL) {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsltApplyTemplates: select didn't evaluate to a node list\n"));\r
-#endif\r
-           goto exit;\r
-       }\r
-       /*\r
-       * \r
-       * NOTE: Previously a document info (xsltDocument) was\r
-       * created and attached to the Result Tree Fragment.\r
-       * But such a document info is created on demand in\r
-       * xsltKeyFunction() (functions.c), so we need to create\r
-       * it here beforehand.\r
-       * In order to take care of potential keys we need to\r
-       * do some extra work for the case when a Result Tree Fragment\r
-       * is converted into a nodeset (e.g. exslt:node-set()) :\r
-       * We attach a "pseudo-doc" (xsltDocument) to _private.          \r
-       * This xsltDocument, together with the keyset, will be freed\r
-       * when the Result Tree Fragment is freed.\r
-       *               \r
-       */\r
-#if 0\r
-       if ((ctxt->nbKeys > 0) &&\r
-           (list->nodeNr != 0) &&                  \r
-           (list->nodeTab[0]->doc != NULL) &&\r
-           XSLT_IS_RES_TREE_FRAG(list->nodeTab[0]->doc))\r
-       {\r
-           /*\r
-           * NOTE that it's also OK if @effectiveDocInfo will be\r
-           * set to NULL.\r
-           */\r
-           isRTF = 1;\r
-           effectiveDocInfo = list->nodeTab[0]->doc->_private;\r
-       }\r
-#endif\r
-    } else {\r
-       /*\r
-        * Build an XPath node set with the children\r
-        */\r
-       list = xmlXPathNodeSetCreate(NULL);\r
-       if (list == NULL)\r
-           goto error;\r
-       cur = node->children;\r
-       while (cur != NULL) {\r
-           switch (cur->type) {\r
-               case XML_TEXT_NODE:\r
-                   if ((IS_BLANK_NODE(cur)) &&\r
-                       (cur->parent != NULL) &&\r
-                       (cur->parent->type == XML_ELEMENT_NODE) &&\r
-                       (ctxt->style->stripSpaces != NULL)) {\r
-                       const xmlChar *val;\r
-\r
-                       if (cur->parent->ns != NULL) {\r
-                           val = (const xmlChar *)\r
-                                 xmlHashLookup2(ctxt->style->stripSpaces,\r
-                                                cur->parent->name,\r
-                                                cur->parent->ns->href);\r
-                           if (val == NULL) {\r
-                               val = (const xmlChar *)\r
-                                 xmlHashLookup2(ctxt->style->stripSpaces,\r
-                                                BAD_CAST "*",\r
-                                                cur->parent->ns->href);\r
-                           }\r
-                       } else {\r
-                           val = (const xmlChar *)\r
-                                 xmlHashLookup2(ctxt->style->stripSpaces,\r
-                                                cur->parent->name, NULL);\r
-                       }\r
-                       if ((val != NULL) &&\r
-                           (xmlStrEqual(val, (xmlChar *) "strip"))) {\r
-                           delNode = cur;\r
-                           break;\r
-                       }\r
-                   }\r
-                   /* no break on purpose */\r
-               case XML_ELEMENT_NODE:\r
-               case XML_DOCUMENT_NODE:\r
-               case XML_HTML_DOCUMENT_NODE:\r
-               case XML_CDATA_SECTION_NODE:\r
-               case XML_PI_NODE:\r
-               case XML_COMMENT_NODE:\r
-                   xmlXPathNodeSetAddUnique(list, cur);\r
-                   break;\r
-               case XML_DTD_NODE:\r
-                   /* Unlink the DTD, it's still reachable\r
-                    * using doc->intSubset */\r
-                   if (cur->next != NULL)\r
-                       cur->next->prev = cur->prev;\r
-                   if (cur->prev != NULL)\r
-                       cur->prev->next = cur->next;\r
-                   break;\r
-               default:\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                   XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "xsltApplyTemplates: skipping cur type %d\n",\r
-                                    cur->type));\r
-#endif\r
-                   delNode = cur;\r
-           }\r
-           cur = cur->next;\r
-           if (delNode != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "xsltApplyTemplates: removing ignorable blank cur\n"));\r
-#endif\r
-               xmlUnlinkNode(delNode);\r
-               xmlFreeNode(delNode);\r
-               delNode = NULL;\r
-           }\r
-       }\r
-    }\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    if (list != NULL)\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,\r
-       "xsltApplyTemplates: list of %d nodes\n", list->nodeNr));\r
-#endif\r
-\r
-    if ((list == NULL) || (list->nodeNr == 0))\r
-       goto exit;\r
-\r
-    /*\r
-    * Set the context's node set and size; this is also needed for\r
-    * for xsltDoSortFunction().\r
-    */\r
-    ctxt->nodeList = list;\r
-    /* \r
-    * Process xsl:with-param and xsl:sort instructions.\r
-    * (The code became so verbose just to avoid the\r
-    *  xmlNodePtr sorts[XSLT_MAX_SORT] if there's no xsl:sort)\r
-    * BUG TODO: We are not using namespaced potentially defined on the\r
-    * xsl:sort or xsl:with-param elements; XPath expression might fail.\r
-    */\r
-    if (inst->children) {\r
-       xsltStackElemPtr param;\r
-\r
-       cur = inst->children;\r
-       while (cur) {\r
-\r
-#ifdef WITH_DEBUGGER\r
-           if (ctxt->debugStatus != XSLT_DEBUG_NONE)\r
-               xslHandleDebugger(cur, node, NULL, ctxt);\r
-#endif\r
-           if (ctxt->state == XSLT_STATE_STOPPED)\r
-               break;\r
-           if (cur->type == XML_TEXT_NODE) {\r
-               cur = cur->next;\r
-               continue;\r
-           }       \r
-           if (! IS_XSLT_ELEM(cur))\r
-               break;\r
-           if (IS_XSLT_NAME(cur, "with-param")) {\r
-               param = xsltParseStylesheetCallerParam(ctxt, cur);\r
-               if (param != NULL) {\r
-                   param->next = withParams;\r
-                   withParams = param;\r
-               }\r
-           }\r
-           if (IS_XSLT_NAME(cur, "sort")) {\r
-               xsltTemplatePtr oldCurTempRule =\r
-                   ctxt->currentTemplateRule;\r
-               int nbsorts = 0;\r
-               xmlNodePtr sorts[XSLT_MAX_SORT];                \r
-               \r
-               sorts[nbsorts++] = cur;\r
-               \r
-               while (cur) {\r
-                   \r
-#ifdef WITH_DEBUGGER\r
-                   if (ctxt->debugStatus != XSLT_DEBUG_NONE)\r
-                       xslHandleDebugger(cur, node, NULL, ctxt);\r
-#endif\r
-                   if (ctxt->state == XSLT_STATE_STOPPED)\r
-                       break;\r
-                   \r
-                   if (cur->type == XML_TEXT_NODE) {\r
-                       cur = cur->next;\r
-                       continue;\r
-                   }\r
-                   \r
-                   if (! IS_XSLT_ELEM(cur))\r
-                       break;\r
-                   if (IS_XSLT_NAME(cur, "with-param")) {\r
-                       param = xsltParseStylesheetCallerParam(ctxt, cur);\r
-                       if (param != NULL) {\r
-                           param->next = withParams;\r
-                           withParams = param;\r
-                       }\r
-                   }   \r
-                   if (IS_XSLT_NAME(cur, "sort")) {\r
-                       if (nbsorts >= XSLT_MAX_SORT) {\r
-                           xsltTransformError(ctxt, NULL, cur,\r
-                               "The number (%d) of xsl:sort instructions exceeds the "\r
-                               "maximum allowed by this processor's settings.\n",\r
-                               nbsorts);\r
-                           ctxt->state = XSLT_STATE_STOPPED;\r
-                           break;\r
-                       } else {\r
-                           sorts[nbsorts++] = cur;\r
-                       }\r
-                   }\r
-                   cur = cur->next;\r
-               }\r
-               /*\r
-               * The "current template rule" is cleared for xsl:sort.\r
-               */\r
-               ctxt->currentTemplateRule = NULL;\r
-               /*\r
-               * Sort.\r
-               */\r
-               xsltDoSortFunction(ctxt, sorts, nbsorts);\r
-               ctxt->currentTemplateRule = oldCurTempRule;\r
-               break;\r
-           }\r
-           cur = cur->next;\r
-       }\r
-    }    \r
-    xpctxt->contextSize = list->nodeNr;\r
-    /*\r
-    * Apply templates for all selected source nodes.\r
-    */    \r
-    for (i = 0; i < list->nodeNr; i++) {\r
-       cur = list->nodeTab[i];\r
-       /*\r
-       * The node becomes the "current node".\r
-       */\r
-       ctxt->node = cur;\r
-       /*\r
-       * An xsl:apply-templates can change the current context doc.\r
-       * OPTIMIZE TODO: Get rid of the need to set the context doc.\r
-       */\r
-       if ((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL))\r
-           xpctxt->doc = cur->doc;\r
-\r
-       xpctxt->proximityPosition = i + 1;\r
-       /*\r
-       * Find and apply a template for this node.\r
-       */\r
-       xsltProcessOneNode(ctxt, cur, withParams);\r
-    }\r
-\r
-exit:\r
-error:\r
-    /*\r
-    * Free the parameter list.\r
-    */\r
-    if (withParams != NULL)\r
-       xsltFreeStackElemList(withParams);\r
-    if (list != NULL)\r
-       xmlXPathFreeNodeSet(list);    \r
-    /*\r
-    * Restore context states.\r
-    */\r
-    xpctxt->doc = oldDoc;\r
-    xpctxt->contextSize = oldXPContextSize;\r
-    xpctxt->proximityPosition = oldXPProximityPosition;\r
-    \r
-    ctxt->tmpDoc = oldDoc;\r
-    ctxt->document = oldDocInfo;\r
-    ctxt->nodeList = oldList;\r
-    ctxt->node = oldContextNode;\r
-    ctxt->mode = oldMode;\r
-    ctxt->modeURI = oldModeURI;\r
-}\r
-\r
-\r
-/**\r
- * xsltChoose:\r
- * @ctxt:  a XSLT process context\r
- * @contextNode:  the current node in the source tree\r
- * @inst:  the xsl:choose instruction\r
- * @comp:  compiled information of the instruction\r
- *\r
- * Processes the xsl:choose instruction on the source node.\r
- */\r
-void\r
-xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,\r
-          xmlNodePtr inst, xsltStylePreCompPtr comp ATTRIBUTE_UNUSED)\r
-{\r
-    xmlNodePtr cur;\r
-\r
-    if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))\r
-       return;\r
-    \r
-    /* \r
-    * TODO: Content model checks should be done only at compilation\r
-    * time.\r
-    */\r
-    cur = inst->children;\r
-    if (cur == NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-           "xsl:choose: The instruction has no content.\n");\r
-       return;\r
-    }\r
-\r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * We don't check the content model during transformation.\r
-    */\r
-#else\r
-    if ((! IS_XSLT_ELEM(cur)) || (! IS_XSLT_NAME(cur, "when"))) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-            "xsl:choose: xsl:when expected first\n");\r
-       return;\r
-    }\r
-#endif\r
-\r
-    {\r
-       int testRes = 0, res = 0;\r
-       xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;    \r
-       xmlDocPtr oldXPContextDoc = xpctxt->doc;\r
-       int oldXPProximityPosition = xpctxt->proximityPosition;\r
-       int oldXPContextSize = xpctxt->contextSize;\r
-       \r
-#ifdef XSLT_REFACTORED\r
-       xsltStyleItemWhenPtr wcomp = NULL;\r
-#else\r
-       xsltStylePreCompPtr wcomp = NULL;\r
-#endif\r
-\r
-       /*\r
-       * Process xsl:when ---------------------------------------------------\r
-       */\r
-       while (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "when")) {        \r
-           wcomp = cur->psvi;\r
-           \r
-           if ((wcomp == NULL) || (wcomp->test == NULL) ||\r
-               (wcomp->comp == NULL))\r
-           {\r
-               xsltTransformError(ctxt, NULL, cur,\r
-                   "Internal error in xsltChoose(): "\r
-                   "The XSLT 'when' instruction was not compiled.\n");\r
-               goto error;\r
-           }\r
-           \r
-           \r
-#ifdef WITH_DEBUGGER\r
-           if (xslDebugStatus != XSLT_DEBUG_NONE) {\r
-               /* \r
-               * TODO: Isn't comp->templ always NULL for xsl:choose?\r
-               */\r
-               xslHandleDebugger(cur, contextNode, NULL, ctxt);\r
-           }\r
-#endif\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_CHOOSE,xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsltChoose: test %s\n", wcomp->test));\r
-#endif\r
-\r
-           xpctxt->node = contextNode;\r
-           xpctxt->doc = oldXPContextDoc;\r
-           xpctxt->proximityPosition = oldXPProximityPosition;\r
-           xpctxt->contextSize = oldXPContextSize;\r
-           \r
-#ifdef XSLT_REFACTORED\r
-           if (wcomp->inScopeNs != NULL) {\r
-               xpctxt->namespaces = wcomp->inScopeNs->list;\r
-               xpctxt->nsNr = wcomp->inScopeNs->xpathNumber;\r
-           } else {\r
-               xpctxt->namespaces = NULL;\r
-               xpctxt->nsNr = 0;\r
-           }\r
-#else\r
-           xpctxt->namespaces = wcomp->nsList;\r
-           xpctxt->nsNr = wcomp->nsNr;\r
-#endif\r
-           \r
-           \r
-#ifdef XSLT_FAST_IF\r
-           res = xmlXPathCompiledEvalToBoolean(wcomp->comp, xpctxt);\r
-           \r
-           if (res == -1) {\r
-               ctxt->state = XSLT_STATE_STOPPED;\r
-               goto error;\r
-           }\r
-           testRes = (res == 1) ? 1 : 0;       \r
-           \r
-#else /* XSLT_FAST_IF */\r
-           \r
-           res = xmlXPathCompiledEval(wcomp->comp, xpctxt);\r
-           \r
-           if (res != NULL) {\r
-               if (res->type != XPATH_BOOLEAN)\r
-                   res = xmlXPathConvertBoolean(res);\r
-               if (res->type == XPATH_BOOLEAN)\r
-                   testRes = res->boolval;\r
-               else {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                   XSLT_TRACE(ctxt,XSLT_TRACE_CHOOSE,xsltGenericDebug(xsltGenericDebugContext,\r
-                       "xsltChoose: test didn't evaluate to a boolean\n"));\r
-#endif\r
-                   goto error;\r
-               }\r
-               xmlXPathFreeObject(res);\r
-               res = NULL;\r
-           } else {\r
-               ctxt->state = XSLT_STATE_STOPPED;\r
-               goto error;\r
-           }\r
-           \r
-#endif /* else of XSLT_FAST_IF */\r
-           \r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_CHOOSE,xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsltChoose: test evaluate to %d\n", testRes));\r
-#endif\r
-           if (testRes)                \r
-               goto test_is_true;\r
-           \r
-           cur = cur->next;\r
-       }\r
-    \r
-       /*\r
-       * Process xsl:otherwise ----------------------------------------------\r
-       */\r
-       if (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "otherwise")) {\r
-           \r
-#ifdef WITH_DEBUGGER\r
-           if (xslDebugStatus != XSLT_DEBUG_NONE)\r
-               xslHandleDebugger(cur, contextNode, NULL, ctxt);\r
-#endif\r
-           \r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_CHOOSE,xsltGenericDebug(xsltGenericDebugContext,\r
-               "evaluating xsl:otherwise\n"));\r
-#endif     \r
-           goto test_is_true;\r
-       }\r
-       xpctxt->node = contextNode;\r
-       xpctxt->doc = oldXPContextDoc;\r
-       xpctxt->proximityPosition = oldXPProximityPosition;\r
-       xpctxt->contextSize = oldXPContextSize;\r
-       goto exit;\r
-\r
-test_is_true:\r
-\r
-       xpctxt->node = contextNode;\r
-       xpctxt->doc = oldXPContextDoc;\r
-       xpctxt->proximityPosition = oldXPProximityPosition;\r
-       xpctxt->contextSize = oldXPContextSize;\r
-       goto process_sequence;\r
-    }\r
-\r
-process_sequence:\r
-    \r
-    /*\r
-    * Instantiate the sequence constructor.\r
-    */\r
-    xsltApplySequenceConstructor(ctxt, ctxt->node, cur->children,\r
-       NULL);\r
-\r
-exit:\r
-error:\r
-    return;\r
-}\r
-\r
-/**\r
- * xsltIf:\r
- * @ctxt:  a XSLT process context\r
- * @contextNode:  the current node in the source tree\r
- * @inst:  the xsl:if instruction\r
- * @comp:  compiled information of the instruction\r
- *\r
- * Processes the xsl:if instruction on the source node.\r
- */\r
-void\r
-xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,\r
-                  xmlNodePtr inst, xsltStylePreCompPtr castedComp)\r
-{\r
-    int res = 0;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemIfPtr comp = (xsltStyleItemIfPtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif\r
-\r
-    if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))\r
-       return;\r
-    if ((comp == NULL) || (comp->test == NULL) || (comp->comp == NULL)) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-           "Internal error in xsltIf(): "\r
-           "The XSLT 'if' instruction was not compiled.\n");\r
-       return;\r
-    }\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_IF,xsltGenericDebug(xsltGenericDebugContext,\r
-        "xsltIf: test %s\n", comp->test));\r
-#endif\r
-\r
-#ifdef XSLT_FAST_IF    \r
-    {\r
-       xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;\r
-       xmlDocPtr oldXPContextDoc = xpctxt->doc;\r
-       xmlNsPtr *oldXPNamespaces = xpctxt->namespaces;\r
-       xmlNodePtr oldXPContextNode = xpctxt->node;\r
-       int oldXPProximityPosition = xpctxt->proximityPosition;\r
-       int oldXPContextSize = xpctxt->contextSize;\r
-       int oldXPNsNr = xpctxt->nsNr;\r
-       xmlDocPtr oldLocalFragmentTop = ctxt->localRVT; \r
-       \r
-       xpctxt->node = contextNode;\r
-       if (comp != NULL) {\r
-           \r
-#ifdef XSLT_REFACTORED\r
-           if (comp->inScopeNs != NULL) {\r
-               xpctxt->namespaces = comp->inScopeNs->list;\r
-               xpctxt->nsNr = comp->inScopeNs->xpathNumber;\r
-           } else {\r
-               xpctxt->namespaces = NULL;\r
-               xpctxt->nsNr = 0;\r
-           }\r
-#else\r
-           xpctxt->namespaces = comp->nsList;\r
-           xpctxt->nsNr = comp->nsNr;\r
-#endif\r
-       } else {\r
-           xpctxt->namespaces = NULL;\r
-           xpctxt->nsNr = 0;\r
-       }\r
-       /*\r
-       * This XPath function is optimized for boolean results.\r
-       */      \r
-       res = xmlXPathCompiledEvalToBoolean(comp->comp, xpctxt);\r
-\r
-       /*\r
-       * Cleanup fragments created during evaluation of the\r
-       * "select" expression.\r
-       */\r
-       if (oldLocalFragmentTop != ctxt->localRVT)\r
-           xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);\r
-       \r
-       xpctxt->doc = oldXPContextDoc;\r
-       xpctxt->node = oldXPContextNode;\r
-       xpctxt->contextSize = oldXPContextSize;\r
-       xpctxt->proximityPosition = oldXPProximityPosition;     \r
-       xpctxt->nsNr = oldXPNsNr;\r
-       xpctxt->namespaces = oldXPNamespaces;\r
-    }\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_IF,xsltGenericDebug(xsltGenericDebugContext,\r
-       "xsltIf: test evaluate to %d\n", res));\r
-#endif\r
-    \r
-    if (res == -1) {\r
-       ctxt->state = XSLT_STATE_STOPPED;\r
-       goto error;\r
-    }\r
-    if (res == 1) {\r
-       /*\r
-       * Instantiate the sequence constructor of xsl:if.\r
-       */\r
-       xsltApplySequenceConstructor(ctxt,\r
-           contextNode, inst->children, NULL);\r
-    }\r
-       \r
-#else /* XSLT_FAST_IF */\r
-    {\r
-       xmlXPathObjectPtr xpobj = NULL;\r
-       /*\r
-       * OLD CODE:\r
-       */\r
-       {\r
-           xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;\r
-           xmlDocPtr oldXPContextDoc = xpctxt->doc;\r
-           xmlNsPtr *oldXPNamespaces = xpctxt->namespaces;\r
-           xmlNodePtr oldXPContextNode = xpctxt->node;\r
-           int oldXPProximityPosition = xpctxt->proximityPosition;\r
-           int oldXPContextSize = xpctxt->contextSize;\r
-           int oldXPNsNr = xpctxt->nsNr;       \r
-           \r
-           xpctxt->node = contextNode;\r
-           if (comp != NULL) {\r
-               \r
-#ifdef XSLT_REFACTORED\r
-               if (comp->inScopeNs != NULL) {\r
-                   xpctxt->namespaces = comp->inScopeNs->list;\r
-                   xpctxt->nsNr = comp->inScopeNs->xpathNumber;\r
-               } else {\r
-                   xpctxt->namespaces = NULL;\r
-                   xpctxt->nsNr = 0;\r
-               }\r
-#else\r
-               xpctxt->namespaces = comp->nsList;\r
-               xpctxt->nsNr = comp->nsNr;\r
-#endif\r
-           } else {\r
-               xpctxt->namespaces = NULL;\r
-               xpctxt->nsNr = 0;\r
-           }\r
-           \r
-           /*\r
-           * This XPath function is optimized for boolean results.\r
-           */  \r
-           xpobj = xmlXPathCompiledEval(comp->comp, xpctxt);\r
-           \r
-           xpctxt->doc = oldXPContextDoc;\r
-           xpctxt->node = oldXPContextNode;\r
-           xpctxt->contextSize = oldXPContextSize;\r
-           xpctxt->proximityPosition = oldXPProximityPosition; \r
-           xpctxt->nsNr = oldXPNsNr;\r
-           xpctxt->namespaces = oldXPNamespaces;\r
-       }\r
-       if (xpobj != NULL) {\r
-           if (xpobj->type != XPATH_BOOLEAN)\r
-               xpobj = xmlXPathConvertBoolean(xpobj);\r
-           if (xpobj->type == XPATH_BOOLEAN) {\r
-               res = xpobj->boolval;\r
-               \r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               XSLT_TRACE(ctxt,XSLT_TRACE_IF,xsltGenericDebug(xsltGenericDebugContext,\r
-                   "xsltIf: test evaluate to %d\n", res));\r
-#endif\r
-               if (res) {\r
-                   xsltApplySequenceConstructor(ctxt,\r
-                       contextNode, inst->children, NULL);\r
-               }\r
-           } else {\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-               XSLT_TRACE(ctxt, XSLT_TRACE_IF,\r
-                   xsltGenericDebug(xsltGenericDebugContext,\r
-                   "xsltIf: test didn't evaluate to a boolean\n"));\r
-#endif\r
-               ctxt->state = XSLT_STATE_STOPPED;\r
-           }\r
-           xmlXPathFreeObject(xpobj);\r
-       } else {\r
-           ctxt->state = XSLT_STATE_STOPPED;\r
-       }\r
-    }\r
-#endif /* else of XSLT_FAST_IF */\r
-\r
-error:\r
-    return;\r
-}\r
-\r
-/**\r
- * xsltForEach:\r
- * @ctxt:  an XSLT transformation context\r
- * @node:  the "current node" in the source tree  \r
- * @inst:  the element node of the xsl:for-each instruction\r
- * @comp:  the compiled information of the instruction\r
- *\r
- * Process the xslt for-each node on the source node\r
- */\r
-void\r
-xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,\r
-           xmlNodePtr inst, xsltStylePreCompPtr castedComp)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemForEachPtr comp = (xsltStyleItemForEachPtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif\r
-    int i;\r
-    xmlXPathObjectPtr res = NULL;\r
-    xmlNodePtr cur, curInst;\r
-    xmlNodeSetPtr list = NULL;\r
-    xmlNodeSetPtr oldList;        \r
-    int oldXPProximityPosition, oldXPContextSize;\r
-    xmlNodePtr oldContextNode;\r
-    xsltTemplatePtr oldCurTemplRule;    \r
-    xmlDocPtr oldSourceDoc;\r
-    xsltDocumentPtr oldDocInfo;\r
-    xmlXPathContextPtr xpctxt;\r
-\r
-    if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL)) {\r
-       xsltGenericError(xsltGenericErrorContext,       \r
-           "xsltForEach(): Bad arguments.\n");\r
-       return;\r
-    }\r
-\r
-    if (comp == NULL) {\r
-        xsltTransformError(ctxt, NULL, inst,\r
-           "Internal error in xsltForEach(): "\r
-           "The XSLT 'for-each' instruction was not compiled.\n");\r
-        return;\r
-    }\r
-    if ((comp->select == NULL) || (comp->comp == NULL)) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-           "Internal error in xsltForEach(): "\r
-           "The selecting expression of the XSLT 'for-each' "\r
-           "instruction was not compiled correctly.\n");\r
-       return;\r
-    }\r
-    xpctxt = ctxt->xpathCtxt;    \r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_FOR_EACH,xsltGenericDebug(xsltGenericDebugContext,\r
-        "xsltForEach: select %s\n", comp->select));\r
-#endif\r
-\r
-    /*\r
-    * Save context states.\r
-    */\r
-    oldDocInfo = ctxt->document;\r
-    oldList = ctxt->nodeList;\r
-    oldSourceDoc = ctxt->tmpDoc;\r
-    oldContextNode = ctxt->node;\r
-    /*\r
-    * The "current template rule" is cleared for the instantiation of\r
-    * xsl:for-each.\r
-    */\r
-    oldCurTemplRule = ctxt->currentTemplateRule;\r
-    ctxt->currentTemplateRule = NULL;\r
-\r
-    oldXPProximityPosition = xpctxt->proximityPosition;\r
-    oldXPContextSize = xpctxt->contextSize;\r
-    /*\r
-    * Set up XPath.\r
-    */\r
-    xpctxt->node = contextNode;\r
-#ifdef XSLT_REFACTORED\r
-    if (comp->inScopeNs != NULL) {\r
-       xpctxt->namespaces = comp->inScopeNs->list;\r
-       xpctxt->nsNr = comp->inScopeNs->xpathNumber;\r
-    } else {\r
-       xpctxt->namespaces = NULL;\r
-       xpctxt->nsNr = 0;\r
-    }\r
-#else\r
-    xpctxt->namespaces = comp->nsList;\r
-    xpctxt->nsNr = comp->nsNr;\r
-#endif   \r
-    \r
-    /*\r
-    * Evaluate the 'select' expression.\r
-    */\r
-    res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt);\r
-\r
-    if (res != NULL) {\r
-       if (res->type == XPATH_NODESET)\r
-           list = res->nodesetval;\r
-       else {\r
-           xsltTransformError(ctxt, NULL, inst,\r
-               "The 'select' expression does not evaluate to a node set.\n");\r
-           \r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_FOR_EACH,xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsltForEach: select didn't evaluate to a node list\n"));\r
-#endif\r
-           goto error;\r
-       }\r
-    } else {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-           "Failed to evaluate the 'select' expression.\n");\r
-       ctxt->state = XSLT_STATE_STOPPED;\r
-       goto error;\r
-    }\r
-\r
-    if ((list == NULL) || (list->nodeNr <= 0))\r
-       goto exit;\r
-\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_FOR_EACH,xsltGenericDebug(xsltGenericDebugContext,\r
-       "xsltForEach: select evaluates to %d nodes\n", list->nodeNr));\r
-#endif\r
-\r
-    /*\r
-    * Restore XPath states for the "current node".\r
-    */\r
-    xpctxt->contextSize = oldXPContextSize;\r
-    xpctxt->proximityPosition = oldXPProximityPosition;\r
-    xpctxt->node = contextNode;\r
-    \r
-    /*\r
-    * Set the list; this has to be done already here for xsltDoSortFunction().\r
-    */\r
-    ctxt->nodeList = list;    \r
-    /* \r
-    * Handle xsl:sort instructions and skip them for further processing.\r
-    * BUG TODO: We are not using namespaced potentially defined on the\r
-    * xsl:sort element; XPath expression might fail.\r
-    */\r
-    curInst = inst->children;\r
-    if (IS_XSLT_ELEM(curInst) && IS_XSLT_NAME(curInst, "sort")) {\r
-       int nbsorts = 0;\r
-       xmlNodePtr sorts[XSLT_MAX_SORT];\r
-\r
-       sorts[nbsorts++] = curInst;\r
-\r
-#ifdef WITH_DEBUGGER\r
-       if (xslDebugStatus != XSLT_DEBUG_NONE)\r
-           xslHandleDebugger(curInst, contextNode, NULL, ctxt);\r
-#endif\r
-\r
-       curInst = curInst->next;\r
-       while (IS_XSLT_ELEM(curInst) && IS_XSLT_NAME(curInst, "sort")) {\r
-           if (nbsorts >= XSLT_MAX_SORT) {\r
-               xsltTransformError(ctxt, NULL, curInst,\r
-                   "The number of xsl:sort instructions exceeds the "\r
-                   "maximum (%d) allowed by this processor.\n",\r
-                   XSLT_MAX_SORT);\r
-               goto error;\r
-           } else {\r
-               sorts[nbsorts++] = curInst;\r
-           }\r
-           \r
-#ifdef WITH_DEBUGGER\r
-           if (xslDebugStatus != XSLT_DEBUG_NONE)\r
-               xslHandleDebugger(curInst, contextNode, NULL, ctxt);\r
-#endif\r
-           curInst = curInst->next;\r
-       }\r
-       xsltDoSortFunction(ctxt, sorts, nbsorts);\r
-    }    \r
-    xpctxt->contextSize = list->nodeNr;\r
-    /*\r
-    * Instantiate the sequence constructor for each selected node.\r
-    */    \r
-    for (i = 0; i < list->nodeNr; i++) {\r
-       cur = list->nodeTab[i];\r
-       /*\r
-       * The selected node becomes the "current node".\r
-       */\r
-       ctxt->node = cur;\r
-       /*\r
-       * An xsl:for-each can change the current context doc.\r
-       * OPTIMIZE TODO: Get rid of the need to set the context doc.\r
-       */\r
-       if ((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL))\r
-           xpctxt->doc = cur->doc;\r
-\r
-       xpctxt->proximityPosition = i + 1;\r
-\r
-       xsltApplySequenceConstructor(ctxt, cur, curInst, NULL);\r
-    }\r
-\r
-exit:\r
-error:\r
-    if (res != NULL)\r
-       xmlXPathFreeObject(res);\r
-    /*\r
-    * Restore old states.\r
-    */\r
-    ctxt->tmpDoc = oldSourceDoc;\r
-    ctxt->document = oldDocInfo;\r
-    ctxt->nodeList = oldList;\r
-    ctxt->node = oldContextNode;\r
-    ctxt->currentTemplateRule = oldCurTemplRule;\r
-\r
-    xpctxt->doc = oldSourceDoc;\r
-    xpctxt->contextSize = oldXPContextSize;\r
-    xpctxt->proximityPosition = oldXPProximityPosition;\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Generic interface                               *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-#ifdef XSLT_GENERATE_HTML_DOCTYPE\r
-typedef struct xsltHTMLVersion {\r
-    const char *version;\r
-    const char *public;\r
-    const char *system;\r
-} xsltHTMLVersion;\r
-\r
-static xsltHTMLVersion xsltHTMLVersions[] = {\r
-    { "4.01frame", "-//W3C//DTD HTML 4.01 Frameset//EN",\r
-      "http://www.w3.org/TR/1999/REC-html401-19991224/frameset.dtd"},\r
-    { "4.01strict", "-//W3C//DTD HTML 4.01//EN",\r
-      "http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd"},\r
-    { "4.01trans", "-//W3C//DTD HTML 4.01 Transitional//EN",\r
-      "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd"},\r
-    { "4.01", "-//W3C//DTD HTML 4.01 Transitional//EN",\r
-      "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd"},\r
-    { "4.0strict", "-//W3C//DTD HTML 4.01//EN",\r
-      "http://www.w3.org/TR/html4/strict.dtd"},\r
-    { "4.0trans", "-//W3C//DTD HTML 4.01 Transitional//EN",\r
-      "http://www.w3.org/TR/html4/loose.dtd"},\r
-    { "4.0frame", "-//W3C//DTD HTML 4.01 Frameset//EN",\r
-      "http://www.w3.org/TR/html4/frameset.dtd"},\r
-    { "4.0", "-//W3C//DTD HTML 4.01 Transitional//EN",\r
-      "http://www.w3.org/TR/html4/loose.dtd"},\r
-    { "3.2", "-//W3C//DTD HTML 3.2//EN", NULL }\r
-};\r
-\r
-/**\r
- * xsltGetHTMLIDs:\r
- * @version:  the version string\r
- * @publicID:  used to return the public ID\r
- * @systemID:  used to return the system ID\r
- *\r
- * Returns -1 if not found, 0 otherwise and the system and public\r
- *         Identifier for this given verion of HTML\r
- */\r
-static int\r
-xsltGetHTMLIDs(const xmlChar *version, const xmlChar **publicID,\r
-                   const xmlChar **systemID) {\r
-    unsigned int i;\r
-    if (version == NULL)\r
-       return(-1);\r
-    for (i = 0;i < (sizeof(xsltHTMLVersions)/sizeof(xsltHTMLVersions[1]));\r
-        i++) {\r
-       if (!xmlStrcasecmp(version,\r
-                          (const xmlChar *) xsltHTMLVersions[i].version)) {\r
-           if (publicID != NULL)\r
-               *publicID = (const xmlChar *) xsltHTMLVersions[i].public;\r
-           if (systemID != NULL)\r
-               *systemID = (const xmlChar *) xsltHTMLVersions[i].system;\r
-           return(0);\r
-       }\r
-    }\r
-    return(-1);\r
-}\r
-#endif\r
-\r
-/**\r
- * xsltApplyStripSpaces:\r
- * @ctxt:  a XSLT process context\r
- * @node:  the root of the XML tree\r
- *\r
- * Strip the unwanted ignorable spaces from the input tree\r
- */\r
-void\r
-xsltApplyStripSpaces(xsltTransformContextPtr ctxt, xmlNodePtr node) {\r
-    xmlNodePtr current;\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    int nb = 0;\r
-#endif\r
-\r
-\r
-    current = node;\r
-    while (current != NULL) {\r
-       /*\r
-        * Cleanup children empty nodes if asked for\r
-        */\r
-       if ((IS_XSLT_REAL_NODE(current)) &&\r
-           (current->children != NULL) &&\r
-           (xsltFindElemSpaceHandling(ctxt, current))) {\r
-           xmlNodePtr delete = NULL, cur = current->children;\r
-\r
-           while (cur != NULL) {\r
-               if (IS_BLANK_NODE(cur))\r
-                   delete = cur;\r
-               \r
-               cur = cur->next;\r
-               if (delete != NULL) {\r
-                   xmlUnlinkNode(delete);\r
-                   xmlFreeNode(delete);\r
-                   delete = NULL;\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                   nb++;\r
-#endif\r
-               }\r
-           }\r
-       }\r
-\r
-       /*\r
-        * Skip to next node in document order.\r
-        */\r
-       if (node->type == XML_ENTITY_REF_NODE) {\r
-           /* process deep in entities */\r
-           xsltApplyStripSpaces(ctxt, node->children);\r
-       }\r
-       if ((current->children != NULL) &&\r
-            (current->type != XML_ENTITY_REF_NODE)) {\r
-           current = current->children;\r
-       } else if (current->next != NULL) {\r
-           current = current->next;\r
-       } else {\r
-           do {\r
-               current = current->parent;\r
-               if (current == NULL)\r
-                   break;\r
-               if (current == node)\r
-                   goto done;\r
-               if (current->next != NULL) {\r
-                   current = current->next;\r
-                   break;\r
-               }\r
-           } while (current != NULL);\r
-       }\r
-    }\r
-\r
-done:\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_STRIP_SPACES,xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltApplyStripSpaces: removed %d ignorable blank node\n", nb));\r
-#endif\r
-    return;\r
-}\r
-\r
-#ifdef XSLT_REFACTORED_KEYCOMP\r
-static int\r
-xsltCountKeys(xsltTransformContextPtr ctxt)\r
-{\r
-    xsltStylesheetPtr style;\r
-    xsltKeyDefPtr keyd;\r
-\r
-    if (ctxt == NULL)\r
-       return(-1);    \r
-\r
-    /*\r
-    * Do we have those nastly templates with a key() in the match pattern?\r
-    */\r
-    ctxt->hasTemplKeyPatterns = 0;\r
-    style = ctxt->style;\r
-    while (style != NULL) {\r
-       if (style->keyMatch != NULL) {\r
-           ctxt->hasTemplKeyPatterns = 1;\r
-           break;\r
-       }\r
-       style = xsltNextImport(style);\r
-    }\r
-    /*\r
-    * Count number of key declarations.\r
-    */\r
-    ctxt->nbKeys = 0;\r
-    style = ctxt->style;\r
-    while (style != NULL) {\r
-       keyd = style->keys;\r
-       while (keyd) {\r
-           ctxt->nbKeys++;\r
-           keyd = keyd->next;\r
-       }\r
-       style = xsltNextImport(style);\r
-    }        \r
-    return(ctxt->nbKeys);\r
-}\r
-#endif /* XSLT_REFACTORED_KEYCOMP */\r
-\r
-/**\r
- * xsltApplyStylesheetInternal:\r
- * @style:  a parsed XSLT stylesheet\r
- * @doc:  a parsed XML document\r
- * @params:  a NULL terminated array of parameters names/values tuples\r
- * @output:  the targetted output\r
- * @profile:  profile FILE * output or NULL\r
- * @user:  user provided parameter\r
- *\r
- * Apply the stylesheet to the document\r
- * NOTE: This may lead to a non-wellformed output XML wise !\r
- *\r
- * Returns the result document or NULL in case of error\r
- */\r
-static xmlDocPtr\r
-xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,\r
-                            const char **params, const char *output,\r
-                            FILE * profile, xsltTransformContextPtr userCtxt)\r
-{\r
-    xmlDocPtr res = NULL;\r
-    xsltTransformContextPtr ctxt = NULL;\r
-    xmlNodePtr root, node;\r
-    const xmlChar *method;\r
-    const xmlChar *doctypePublic;\r
-    const xmlChar *doctypeSystem;\r
-    const xmlChar *version;\r
-    xsltStackElemPtr variables;\r
-    xsltStackElemPtr vptr;\r
-\r
-    if ((style == NULL) || (doc == NULL))\r
-        return (NULL);\r
-\r
-    if (style->internalized == 0) {\r
-#ifdef WITH_XSLT_DEBUG\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-                        "Stylesheet was not fully internalized !\n");\r
-#endif\r
-    }\r
-    if (doc->intSubset != NULL) {\r
-       /*\r
-        * Avoid hitting the DTD when scanning nodes\r
-        * but keep it linked as doc->intSubset\r
-        */\r
-       xmlNodePtr cur = (xmlNodePtr) doc->intSubset;\r
-       if (cur->next != NULL)\r
-           cur->next->prev = cur->prev;\r
-       if (cur->prev != NULL)\r
-           cur->prev->next = cur->next;\r
-       if (doc->children == cur)\r
-           doc->children = cur->next;\r
-       if (doc->last == cur)\r
-           doc->last = cur->prev;\r
-       cur->prev = cur->next = NULL;\r
-    }\r
-\r
-    /*\r
-     * Check for XPath document order availability\r
-     */\r
-    root = xmlDocGetRootElement(doc);\r
-    if (root != NULL) {\r
-       if (((long) root->content) >= 0 && (xslDebugStatus == XSLT_DEBUG_NONE))\r
-           xmlXPathOrderDocElems(doc);\r
-    }\r
-\r
-    if (userCtxt != NULL)\r
-       ctxt = userCtxt;\r
-    else\r
-       ctxt = xsltNewTransformContext(style, doc);\r
-\r
-    if (ctxt == NULL)\r
-        return (NULL);\r
-\r
-    ctxt->initialContextDoc = doc;\r
-    ctxt->initialContextNode = (xmlNodePtr) doc;\r
-\r
-    if (profile != NULL)\r
-        ctxt->profile = 1;\r
-\r
-    if (output != NULL)\r
-        ctxt->outputFile = output;\r
-    else\r
-        ctxt->outputFile = NULL;\r
-\r
-    /*\r
-     * internalize the modes if needed\r
-     */\r
-    if (ctxt->dict != NULL) {\r
-        if (ctxt->mode != NULL)\r
-           ctxt->mode = xmlDictLookup(ctxt->dict, ctxt->mode, -1);\r
-        if (ctxt->modeURI != NULL)\r
-           ctxt->modeURI = xmlDictLookup(ctxt->dict, ctxt->modeURI, -1);\r
-    }\r
-\r
-    XSLT_GET_IMPORT_PTR(method, style, method)\r
-    XSLT_GET_IMPORT_PTR(doctypePublic, style, doctypePublic)\r
-    XSLT_GET_IMPORT_PTR(doctypeSystem, style, doctypeSystem)\r
-    XSLT_GET_IMPORT_PTR(version, style, version)\r
-\r
-    if ((method != NULL) &&\r
-       (!xmlStrEqual(method, (const xmlChar *) "xml")))\r
-    {\r
-        if (xmlStrEqual(method, (const xmlChar *) "html")) {\r
-            ctxt->type = XSLT_OUTPUT_HTML;\r
-            if (((doctypePublic != NULL) || (doctypeSystem != NULL))) {\r
-                res = htmlNewDoc(doctypeSystem, doctypePublic);\r
-           } else {\r
-                if (version == NULL) {\r
-                   xmlDtdPtr dtd;\r
-                   \r
-                   res = htmlNewDoc(NULL, NULL);\r
-                   /*\r
-                   * Make sure no DTD node is generated in this case\r
-                   */\r
-                   if (res != NULL) {\r
-                       dtd = xmlGetIntSubset(res);\r
-                       if (dtd != NULL) {\r
-                           xmlUnlinkNode((xmlNodePtr) dtd);\r
-                           xmlFreeDtd(dtd);\r
-                       }\r
-                       res->intSubset = NULL;\r
-                       res->extSubset = NULL;\r
-                   }\r
-               } else {\r
-\r
-#ifdef XSLT_GENERATE_HTML_DOCTYPE\r
-                   xsltGetHTMLIDs(version, &doctypePublic, &doctypeSystem);\r
-#endif\r
-                   res = htmlNewDoc(doctypeSystem, doctypePublic);\r
-               }\r
-            }\r
-            if (res == NULL)\r
-                goto error;\r
-           res->dict = ctxt->dict;\r
-           xmlDictReference(res->dict);\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-               "reusing transformation dict for output\n");\r
-#endif\r
-        } else if (xmlStrEqual(method, (const xmlChar *) "xhtml")) {\r
-           xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,\r
-               "xsltApplyStylesheetInternal: unsupported method xhtml, using html\n",\r
-               style->method);\r
-            ctxt->type = XSLT_OUTPUT_HTML;\r
-            res = htmlNewDoc(doctypeSystem, doctypePublic);\r
-            if (res == NULL)\r
-                goto error;\r
-           res->dict = ctxt->dict;\r
-           xmlDictReference(res->dict);\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-               "reusing transformation dict for output\n");\r
-#endif\r
-        } else if (xmlStrEqual(method, (const xmlChar *) "text")) {\r
-            ctxt->type = XSLT_OUTPUT_TEXT;\r
-            res = xmlNewDoc(style->version);\r
-            if (res == NULL)\r
-                goto error;\r
-           res->dict = ctxt->dict;\r
-           xmlDictReference(res->dict);\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-               "reusing transformation dict for output\n");\r
-#endif\r
-        } else {\r
-           xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,\r
-               "xsltApplyStylesheetInternal: unsupported method %s\n",\r
-               style->method);\r
-            goto error;\r
-        }\r
-    } else {\r
-        ctxt->type = XSLT_OUTPUT_XML;\r
-        res = xmlNewDoc(style->version);\r
-        if (res == NULL)\r
-            goto error;\r
-       res->dict = ctxt->dict;\r
-       xmlDictReference(ctxt->dict);\r
-#ifdef WITH_XSLT_DEBUG\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-                        "reusing transformation dict for output\n");\r
-#endif\r
-    }\r
-    res->charset = XML_CHAR_ENCODING_UTF8;\r
-    if (style->encoding != NULL)\r
-        res->encoding = xmlStrdup(style->encoding);\r
-    variables = style->variables;\r
-\r
-    /*\r
-     * Start the evaluation, evaluate the params, the stylesheets globals\r
-     * and start by processing the top node.\r
-     */\r
-    if (xsltNeedElemSpaceHandling(ctxt))\r
-       xsltApplyStripSpaces(ctxt, xmlDocGetRootElement(doc));    \r
-    /*\r
-    * Evaluate global params and user-provided params.\r
-    */\r
-    ctxt->tmpDoc = doc;\r
-    ctxt->node = (xmlNodePtr) doc;\r
-    if (ctxt->globalVars == NULL)\r
-       ctxt->globalVars = xmlHashCreate(20);\r
-    if (params != NULL) {      \r
-        xsltEvalUserParams(ctxt, params);\r
-    }\r
-    xsltEvalGlobalVariables(ctxt);\r
-\r
-#ifdef XSLT_REFACTORED_KEYCOMP    \r
-    xsltCountKeys(ctxt);\r
-#endif\r
-\r
-    ctxt->tmpDoc = doc;\r
-    ctxt->node = (xmlNodePtr) doc;\r
-    ctxt->output = res;\r
-    ctxt->insert = (xmlNodePtr) res;    \r
-    ctxt->varsBase = ctxt->varsNr - 1; \r
-    \r
-    ctxt->xpathCtxt->contextSize = 1;\r
-    ctxt->xpathCtxt->proximityPosition = 1;\r
-    ctxt->xpathCtxt->node = NULL; /* TODO: Set the context node here? */\r
-    /*\r
-    * Start processing the source tree -----------------------------------\r
-    */\r
-    xsltProcessOneNode(ctxt, ctxt->node, NULL);\r
-    /*\r
-    * Remove all remaining vars from the stack.\r
-    */\r
-    xsltLocalVariablePop(ctxt, 0, -2);\r
-    xsltShutdownCtxtExts(ctxt);\r
-\r
-    xsltCleanupTemplates(style); /* TODO: <- style should be read only */\r
-\r
-    /*\r
-     * Now cleanup our variables so stylesheet can be re-used\r
-     *\r
-     * TODO: this is not needed anymore global variables are copied\r
-     *       and not evaluated directly anymore, keep this as a check\r
-     */\r
-    if (style->variables != variables) {\r
-        vptr = style->variables;\r
-        while (vptr->next != variables)\r
-            vptr = vptr->next;\r
-        vptr->next = NULL;\r
-        xsltFreeStackElemList(style->variables);\r
-        style->variables = variables;\r
-    }\r
-    vptr = style->variables;\r
-    while (vptr != NULL) {\r
-        if (vptr->computed) {\r
-            if (vptr->value != NULL) {\r
-                xmlXPathFreeObject(vptr->value);\r
-                vptr->value = NULL;\r
-                vptr->computed = 0;\r
-            }\r
-        }\r
-        vptr = vptr->next;\r
-    }\r
-    /*\r
-    * Free all remaining tree fragments.\r
-    */\r
-    xsltFreeRVTs(ctxt);\r
-    /*\r
-     * Do some post processing work depending on the generated output\r
-     */\r
-    root = xmlDocGetRootElement(res);\r
-    if (root != NULL) {\r
-        const xmlChar *doctype = NULL;\r
-\r
-        if ((root->ns != NULL) && (root->ns->prefix != NULL))\r
-           doctype = xmlDictQLookup(ctxt->dict, root->ns->prefix, root->name);\r
-       if (doctype == NULL)\r
-           doctype = root->name;\r
-\r
-        /*\r
-         * Apply the default selection of the method\r
-         */\r
-        if ((method == NULL) &&\r
-            (root->ns == NULL) &&\r
-            (!xmlStrcasecmp(root->name, (const xmlChar *) "html"))) {\r
-            xmlNodePtr tmp;\r
-\r
-            tmp = res->children;\r
-            while ((tmp != NULL) && (tmp != root)) {\r
-                if (tmp->type == XML_ELEMENT_NODE)\r
-                    break;\r
-                if ((tmp->type == XML_TEXT_NODE) && (!xmlIsBlankNode(tmp)))\r
-                    break;\r
-               tmp = tmp->next;\r
-            }\r
-            if (tmp == root) {\r
-                ctxt->type = XSLT_OUTPUT_HTML;\r
-               /*\r
-               * REVISIT TODO: XML_HTML_DOCUMENT_NODE is set after the\r
-               *  transformation on the doc, but functions like\r
-               */\r
-                res->type = XML_HTML_DOCUMENT_NODE;\r
-                if (((doctypePublic != NULL) || (doctypeSystem != NULL))) {\r
-                    res->intSubset = xmlCreateIntSubset(res, doctype,\r
-                                                        doctypePublic,\r
-                                                        doctypeSystem);\r
-#ifdef XSLT_GENERATE_HTML_DOCTYPE\r
-               } else if (version != NULL) {\r
-                    xsltGetHTMLIDs(version, &doctypePublic,\r
-                                   &doctypeSystem);\r
-                    if (((doctypePublic != NULL) || (doctypeSystem != NULL)))\r
-                        res->intSubset =\r
-                            xmlCreateIntSubset(res, doctype,\r
-                                               doctypePublic,\r
-                                               doctypeSystem);\r
-#endif\r
-                }\r
-            }\r
-\r
-        }\r
-        if (ctxt->type == XSLT_OUTPUT_XML) {\r
-            XSLT_GET_IMPORT_PTR(doctypePublic, style, doctypePublic)\r
-            XSLT_GET_IMPORT_PTR(doctypeSystem, style, doctypeSystem)\r
-            if (((doctypePublic != NULL) || (doctypeSystem != NULL))) {\r
-               xmlNodePtr last;\r
-               /* Need a small "hack" here to assure DTD comes before\r
-                  possible comment nodes */\r
-               node = res->children;\r
-               last = res->last;\r
-               res->children = NULL;\r
-               res->last = NULL;\r
-                res->intSubset = xmlCreateIntSubset(res, doctype,\r
-                                                    doctypePublic,\r
-                                                    doctypeSystem);\r
-               if (res->children != NULL) {\r
-                   res->children->next = node;\r
-                   node->prev = res->children;\r
-                   res->last = last;\r
-               } else {\r
-                   res->children = node;\r
-                   res->last = last;\r
-               }\r
-           }\r
-        }\r
-    }\r
-    xmlXPathFreeNodeSet(ctxt->nodeList);\r
-    if (profile != NULL) {\r
-        xsltSaveProfiling(ctxt, profile);\r
-    }\r
-\r
-    /*\r
-     * Be pedantic.\r
-     */\r
-    if ((ctxt != NULL) && (ctxt->state == XSLT_STATE_ERROR)) {\r
-       xmlFreeDoc(res);\r
-       res = NULL;\r
-    }\r
-    if ((res != NULL) && (ctxt != NULL) && (output != NULL)) {\r
-       int ret;\r
-\r
-       ret = xsltCheckWrite(ctxt->sec, ctxt, (const xmlChar *) output);\r
-       if (ret == 0) {\r
-           xsltTransformError(ctxt, NULL, NULL,\r
-                    "xsltApplyStylesheet: forbidden to save to %s\n",\r
-                              output);\r
-       } else if (ret < 0) {\r
-           xsltTransformError(ctxt, NULL, NULL,\r
-                    "xsltApplyStylesheet: saving to %s may not be possible\n",\r
-                              output);\r
-       }\r
-    }\r
-\r
-#ifdef XSLT_DEBUG_PROFILE_CACHE\r
-    printf("# Cache:\n");\r
-    printf("# Reused tree fragments: %d\n", ctxt->cache->dbgReusedRVTs);\r
-    printf("# Reused variables     : %d\n", ctxt->cache->dbgReusedVars);\r
-#endif\r
-\r
-    if ((ctxt != NULL) && (userCtxt == NULL))\r
-       xsltFreeTransformContext(ctxt);\r
-\r
-    return (res);\r
-\r
-error:\r
-    if (res != NULL)\r
-        xmlFreeDoc(res);\r
-\r
-#ifdef XSLT_DEBUG_PROFILE_CACHE\r
-    printf("# Cache:\n");\r
-    printf("# Reused tree fragments: %d\n", ctxt->cache->dbgReusedRVTs);\r
-    printf("# Reused variables     : %d\n", ctxt->cache->dbgReusedVars);\r
-#endif\r
-\r
-    if ((ctxt != NULL) && (userCtxt == NULL))\r
-        xsltFreeTransformContext(ctxt);\r
-    return (NULL);\r
-}\r
-\r
-/**\r
- * xsltApplyStylesheet:\r
- * @style:  a parsed XSLT stylesheet\r
- * @doc:  a parsed XML document\r
- * @params:  a NULL terminated arry of parameters names/values tuples\r
- *\r
- * Apply the stylesheet to the document\r
- * NOTE: This may lead to a non-wellformed output XML wise !\r
- *\r
- * Returns the result document or NULL in case of error\r
- */\r
-xmlDocPtr\r
-xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc,\r
-                    const char **params)\r
-{\r
-    return (xsltApplyStylesheetInternal(style, doc, params, NULL, NULL, NULL));\r
-}\r
-\r
-/**\r
- * xsltProfileStylesheet:\r
- * @style:  a parsed XSLT stylesheet\r
- * @doc:  a parsed XML document\r
- * @params:  a NULL terminated arry of parameters names/values tuples\r
- * @output:  a FILE * for the profiling output\r
- *\r
- * Apply the stylesheet to the document and dump the profiling to\r
- * the given output.\r
- *\r
- * Returns the result document or NULL in case of error\r
- */\r
-xmlDocPtr\r
-xsltProfileStylesheet(xsltStylesheetPtr style, xmlDocPtr doc,\r
-                      const char **params, FILE * output)\r
-{\r
-    xmlDocPtr res;\r
-\r
-    res = xsltApplyStylesheetInternal(style, doc, params, NULL, output, NULL);\r
-    return (res);\r
-}\r
-\r
-/**\r
- * xsltApplyStylesheetUser:\r
- * @style:  a parsed XSLT stylesheet\r
- * @doc:  a parsed XML document\r
- * @params:  a NULL terminated array of parameters names/values tuples\r
- * @output:  the targetted output\r
- * @profile:  profile FILE * output or NULL\r
- * @userCtxt:  user provided transform context\r
- *\r
- * Apply the stylesheet to the document and allow the user to provide\r
- * its own transformation context.\r
- *\r
- * Returns the result document or NULL in case of error\r
- */\r
-xmlDocPtr\r
-xsltApplyStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc,\r
-                            const char **params, const char *output,\r
-                            FILE * profile, xsltTransformContextPtr userCtxt)\r
-{\r
-    xmlDocPtr res;\r
-\r
-    res = xsltApplyStylesheetInternal(style, doc, params, output,\r
-                                     profile, userCtxt);\r
-    return (res);\r
-}\r
-\r
-/**\r
- * xsltRunStylesheetUser:\r
- * @style:  a parsed XSLT stylesheet\r
- * @doc:  a parsed XML document\r
- * @params:  a NULL terminated array of parameters names/values tuples\r
- * @output:  the URL/filename ot the generated resource if available\r
- * @SAX:  a SAX handler for progressive callback output (not implemented yet)\r
- * @IObuf:  an output buffer for progressive output (not implemented yet)\r
- * @profile:  profile FILE * output or NULL\r
- * @userCtxt:  user provided transform context\r
- *\r
- * Apply the stylesheet to the document and generate the output according\r
- * to @output @SAX and @IObuf. It's an error to specify both @SAX and @IObuf.\r
- *\r
- * NOTE: This may lead to a non-wellformed output XML wise !\r
- * NOTE: This may also result in multiple files being generated\r
- * NOTE: using IObuf, the result encoding used will be the one used for\r
- *       creating the output buffer, use the following macro to read it\r
- *       from the stylesheet\r
- *       XSLT_GET_IMPORT_PTR(encoding, style, encoding)\r
- * NOTE: using SAX, any encoding specified in the stylesheet will be lost\r
- *       since the interface uses only UTF8\r
- *\r
- * Returns the number of by written to the main resource or -1 in case of\r
- *         error.\r
- */\r
-int\r
-xsltRunStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc,\r
-                  const char **params, const char *output,\r
-                  xmlSAXHandlerPtr SAX, xmlOutputBufferPtr IObuf,\r
-                 FILE * profile, xsltTransformContextPtr userCtxt)\r
-{\r
-    xmlDocPtr tmp;\r
-    int ret;\r
-\r
-    if ((output == NULL) && (SAX == NULL) && (IObuf == NULL))\r
-        return (-1);\r
-    if ((SAX != NULL) && (IObuf != NULL))\r
-        return (-1);\r
-\r
-    /* unsupported yet */\r
-    if (SAX != NULL) {\r
-        XSLT_TODO   /* xsltRunStylesheet xmlSAXHandlerPtr SAX */\r
-       return (-1);\r
-    }\r
-\r
-    tmp = xsltApplyStylesheetInternal(style, doc, params, output, profile,\r
-                                     userCtxt);\r
-    if (tmp == NULL) {\r
-       xsltTransformError(NULL, NULL, (xmlNodePtr) doc,\r
-                         "xsltRunStylesheet : run failed\n");\r
-        return (-1);\r
-    }\r
-    if (IObuf != NULL) {\r
-        /* TODO: incomplete, IObuf output not progressive */\r
-        ret = xsltSaveResultTo(IObuf, tmp, style);\r
-    } else {\r
-        ret = xsltSaveResultToFilename(output, tmp, style, 0);\r
-    }\r
-    xmlFreeDoc(tmp);\r
-    return (ret);\r
-}\r
-\r
-/**\r
- * xsltRunStylesheet:\r
- * @style:  a parsed XSLT stylesheet\r
- * @doc:  a parsed XML document\r
- * @params:  a NULL terminated array of parameters names/values tuples\r
- * @output:  the URL/filename ot the generated resource if available\r
- * @SAX:  a SAX handler for progressive callback output (not implemented yet)\r
- * @IObuf:  an output buffer for progressive output (not implemented yet)\r
- *\r
- * Apply the stylesheet to the document and generate the output according\r
- * to @output @SAX and @IObuf. It's an error to specify both @SAX and @IObuf.\r
- *\r
- * NOTE: This may lead to a non-wellformed output XML wise !\r
- * NOTE: This may also result in multiple files being generated\r
- * NOTE: using IObuf, the result encoding used will be the one used for\r
- *       creating the output buffer, use the following macro to read it\r
- *       from the stylesheet\r
- *       XSLT_GET_IMPORT_PTR(encoding, style, encoding)\r
- * NOTE: using SAX, any encoding specified in the stylesheet will be lost\r
- *       since the interface uses only UTF8\r
- *\r
- * Returns the number of bytes written to the main resource or -1 in case of\r
- *         error.\r
- */\r
-int\r
-xsltRunStylesheet(xsltStylesheetPtr style, xmlDocPtr doc,\r
-                  const char **params, const char *output,\r
-                  xmlSAXHandlerPtr SAX, xmlOutputBufferPtr IObuf)\r
-{\r
-    return(xsltRunStylesheetUser(style, doc, params, output, SAX, IObuf,\r
-                                NULL, NULL));\r
-}\r
-\r
-/**\r
- * xsltRegisterAllElement:\r
- * @ctxt:  the XPath context\r
- *\r
- * Registers all default XSLT elements in this context\r
- */\r
-void\r
-xsltRegisterAllElement(xsltTransformContextPtr ctxt)\r
-{\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "apply-templates",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltApplyTemplates);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "apply-imports",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltApplyImports);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "call-template",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltCallTemplate);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "element",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltElement);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "attribute",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltAttribute);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "text",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltText);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "processing-instruction",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltProcessingInstruction);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "comment",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltComment);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "copy",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltCopy);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "value-of",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltValueOf);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "number",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltNumber);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "for-each",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltForEach);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "if",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltIf);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "choose",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltChoose);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "sort",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltSort);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "copy-of",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltCopyOf);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "message",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltMessage);\r
-\r
-    /*\r
-     * Those don't have callable entry points but are registered anyway\r
-     */\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "variable",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltDebug);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "param",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltDebug);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "with-param",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltDebug);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "decimal-format",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltDebug);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "when",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltDebug);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "otherwise",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltDebug);\r
-    xsltRegisterExtElement(ctxt, (const xmlChar *) "fallback",\r
-                           XSLT_NAMESPACE,\r
-                          (xsltTransformFunction) xsltDebug);\r
-\r
-}\r
+/*
+ * transform.c: Implementation of the XSL Transformation 1.0 engine
+ *              transform part, i.e. applying a Stylesheet to a document
+ *
+ * References:
+ *   http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ *   Michael Kay "XSLT Programmer's Reference" pp 637-643
+ *   Writing Multiple Output Files
+ *
+ *   XSLT-1.1 Working Draft
+ *   http://www.w3.org/TR/xslt11#multiple-output
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/valid.h>
+#include <libxml/hash.h>
+#include <libxml/encoding.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xpath.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/debugXML.h>
+#include <libxml/uri.h>
+#include "xslt.h"
+#include "xsltInternals.h"
+#include "xsltutils.h"
+#include "pattern.h"
+#include "transform.h"
+#include "variables.h"
+#include "numbersInternals.h"
+#include "namespaces.h"
+#include "attributes.h"
+#include "templates.h"
+#include "imports.h"
+#include "keys.h"
+#include "documents.h"
+#include "extensions.h"
+#include "extra.h"
+#include "preproc.h"
+#include "security.h"
+
+#ifdef WITH_XSLT_DEBUG
+#define WITH_XSLT_DEBUG_EXTRA
+#define WITH_XSLT_DEBUG_PROCESS
+#endif
+
+#define XSLT_GENERATE_HTML_DOCTYPE
+#ifdef XSLT_GENERATE_HTML_DOCTYPE
+static int xsltGetHTMLIDs(const xmlChar *version, const xmlChar **publicID,
+                         const xmlChar **systemID);
+#endif
+
+int xsltMaxDepth = 3000;
+
+/*
+ * Useful macros
+ */
+
+#ifndef FALSE
+# define FALSE (0 == 1)
+# define TRUE (!FALSE)
+#endif
+
+#define IS_BLANK_NODE(n)                                               \
+    (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
+
+
+/*
+* Forward declarations
+*/
+
+static xmlNsPtr
+xsltCopyNamespaceListInternal(xmlNodePtr node, xmlNsPtr cur);
+
+static xmlNodePtr
+xsltCopyTreeInternal(xsltTransformContextPtr ctxt,
+                    xmlNodePtr invocNode,
+                    xmlNodePtr node,
+                    xmlNodePtr insert, int isLRE, int topElemVisited);
+
+static void
+xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
+                            xmlNodePtr contextNode, xmlNodePtr list,
+                            xsltTemplatePtr templ);
+
+static void
+xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
+                     xmlNodePtr contextNode,
+                     xmlNodePtr list,
+                     xsltTemplatePtr templ,
+                     xsltStackElemPtr withParams);
+
+/**
+ * templPush:
+ * @ctxt: the transformation context
+ * @value:  the template to push on the stack
+ *
+ * Push a template on the stack
+ *
+ * Returns the new index in the stack or 0 in case of error
+ */
+static int
+templPush(xsltTransformContextPtr ctxt, xsltTemplatePtr value)
+{
+    if (ctxt->templMax == 0) {
+        ctxt->templMax = 4;
+        ctxt->templTab =
+            (xsltTemplatePtr *) xmlMalloc(ctxt->templMax *
+                                          sizeof(ctxt->templTab[0]));
+        if (ctxt->templTab == NULL) {
+            xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
+            return (0);
+        }
+    }
+    if (ctxt->templNr >= ctxt->templMax) {
+        ctxt->templMax *= 2;
+        ctxt->templTab =
+            (xsltTemplatePtr *) xmlRealloc(ctxt->templTab,
+                                           ctxt->templMax *
+                                           sizeof(ctxt->templTab[0]));
+        if (ctxt->templTab == NULL) {
+            xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
+            return (0);
+        }
+    }
+    ctxt->templTab[ctxt->templNr] = value;
+    ctxt->templ = value;
+    return (ctxt->templNr++);
+}
+/**
+ * templPop:
+ * @ctxt: the transformation context
+ *
+ * Pop a template value from the stack
+ *
+ * Returns the stored template value
+ */
+static xsltTemplatePtr
+templPop(xsltTransformContextPtr ctxt)
+{
+    xsltTemplatePtr ret;
+
+    if (ctxt->templNr <= 0)
+        return (0);
+    ctxt->templNr--;
+    if (ctxt->templNr > 0)
+        ctxt->templ = ctxt->templTab[ctxt->templNr - 1];
+    else
+        ctxt->templ = (xsltTemplatePtr) 0;
+    ret = ctxt->templTab[ctxt->templNr];
+    ctxt->templTab[ctxt->templNr] = 0;
+    return (ret);
+}
+
+/**
+ * xsltVariablePop:
+ * @ctxt: the transformation context
+ * @depth:  the depth in the xsl:template's tree
+ *
+ * Pops all variable values at the given @depth from the stack.
+ *
+ * Returns the stored variable value
+ */
+static void
+xsltLocalVariablePop(xsltTransformContextPtr ctxt, int limitNr, int level)
+{
+    xsltStackElemPtr variable;
+
+    if (ctxt->varsNr <= 0)
+        return;
+
+    do {
+       if (ctxt->varsNr <= limitNr)
+           break;
+       variable = ctxt->varsTab[ctxt->varsNr - 1];
+       if (variable->level <= level)
+           break;      
+       if (variable->level >= 0)
+           xsltFreeStackElemList(variable);
+       ctxt->varsNr--;
+    } while (ctxt->varsNr != 0);
+    if (ctxt->varsNr > 0)
+        ctxt->vars = ctxt->varsTab[ctxt->varsNr - 1];
+    else
+        ctxt->vars = NULL;
+}
+
+/**
+ * xsltTemplateParamsCleanup:
+ *
+ * Removes xsl:param and xsl:with-param items from the
+ * variable-stack. Only xsl:with-param items are not freed. 
+ */
+static void
+xsltTemplateParamsCleanup(xsltTransformContextPtr ctxt)
+{
+    xsltStackElemPtr param;    
+
+    for (; ctxt->varsNr > ctxt->varsBase; ctxt->varsNr--) {
+       param = ctxt->varsTab[ctxt->varsNr -1];
+       /*
+       * Free xsl:param items.
+       * xsl:with-param items will have a level of -1 or -2.
+       */
+       if (param->level >= 0) {            
+           xsltFreeStackElemList(param);
+       }           
+    }    
+    if (ctxt->varsNr > 0)
+        ctxt->vars = ctxt->varsTab[ctxt->varsNr - 1];
+    else
+        ctxt->vars = NULL;
+}
+
+/**
+ * profPush:
+ * @ctxt: the transformation context
+ * @value:  the profiling value to push on the stack
+ *
+ * Push a profiling value on the stack
+ *
+ * Returns the new index in the stack or 0 in case of error
+ */
+static int
+profPush(xsltTransformContextPtr ctxt, long value)
+{
+    if (ctxt->profMax == 0) {
+        ctxt->profMax = 4;
+        ctxt->profTab =
+            (long *) xmlMalloc(ctxt->profMax * sizeof(ctxt->profTab[0]));
+        if (ctxt->profTab == NULL) {
+            xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
+            return (0);
+        }
+    }
+    if (ctxt->profNr >= ctxt->profMax) {
+        ctxt->profMax *= 2;
+        ctxt->profTab =
+            (long *) xmlRealloc(ctxt->profTab,
+                                ctxt->profMax * sizeof(ctxt->profTab[0]));
+        if (ctxt->profTab == NULL) {
+            xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
+            return (0);
+        }
+    }
+    ctxt->profTab[ctxt->profNr] = value;
+    ctxt->prof = value;
+    return (ctxt->profNr++);
+}
+/**
+ * profPop:
+ * @ctxt: the transformation context
+ *
+ * Pop a profiling value from the stack
+ *
+ * Returns the stored profiling value
+ */
+static long
+profPop(xsltTransformContextPtr ctxt)
+{
+    long ret;
+
+    if (ctxt->profNr <= 0)
+        return (0);
+    ctxt->profNr--;
+    if (ctxt->profNr > 0)
+        ctxt->prof = ctxt->profTab[ctxt->profNr - 1];
+    else
+        ctxt->prof = (long) 0;
+    ret = ctxt->profTab[ctxt->profNr];
+    ctxt->profTab[ctxt->profNr] = 0;
+    return (ret);
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     XInclude default settings                       *
+ *                                                                     *
+ ************************************************************************/
+
+static int xsltDoXIncludeDefault = 0;
+
+/**
+ * xsltSetXIncludeDefault:
+ * @xinclude: whether to do XInclude processing
+ *
+ * Set whether XInclude should be processed on document being loaded by default
+ */
+void
+xsltSetXIncludeDefault(int xinclude) {
+    xsltDoXIncludeDefault = (xinclude != 0);
+}
+
+/**
+ * xsltGetXIncludeDefault:
+ *
+ * Provides the default state for XInclude processing
+ *
+ * Returns 0 if there is no processing 1 otherwise
+ */
+int
+xsltGetXIncludeDefault(void) {
+    return(xsltDoXIncludeDefault);
+}
+
+unsigned long xsltDefaultTrace = (unsigned long) XSLT_TRACE_ALL;
+
+/**
+ * xsltDebugSetDefaultTrace:
+ * @val: tracing level mask
+ *
+ * Set the default debug tracing level mask
+ */
+void xsltDebugSetDefaultTrace(xsltDebugTraceCodes val) {
+       xsltDefaultTrace = val;
+}
+
+/**
+ * xsltDebugGetDefaultTrace:
+ *
+ * Get the current default debug tracing level mask
+ *
+ * Returns the current default debug tracing level mask
+ */
+xsltDebugTraceCodes xsltDebugGetDefaultTrace() {
+       return xsltDefaultTrace;
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Handling of Transformation Contexts             *
+ *                                                                     *
+ ************************************************************************/
+
+static xsltTransformCachePtr
+xsltTransformCacheCreate(void)
+{
+    xsltTransformCachePtr ret;
+    
+    ret = (xsltTransformCachePtr) xmlMalloc(sizeof(xsltTransformCache));
+    if (ret == NULL) {
+       xsltTransformError(NULL, NULL, NULL,
+           "xsltTransformCacheCreate : malloc failed\n");
+       return(NULL);
+    }
+    memset(ret, 0, sizeof(xsltTransformCache));
+    return(ret);
+}
+
+static void
+xsltTransformCacheFree(xsltTransformCachePtr cache)
+{    
+    if (cache == NULL)
+       return;    
+    /*
+    * Free tree fragments.
+    */
+    if (cache->RVT) {
+       xmlDocPtr tmp, cur = cache->RVT;
+       while (cur) {
+           tmp = cur;
+           cur = (xmlDocPtr) cur->next;
+           if (tmp->_private != NULL) {
+               /*
+               * Tree the document info.
+               */
+               xsltFreeDocumentKeys((xsltDocumentPtr) tmp->_private);
+               xmlFree(tmp->_private);
+           }
+           xmlFreeDoc(tmp);
+       }
+    }
+    /*
+    * Free vars/params.
+    */
+    if (cache->stackItems) {
+       xsltStackElemPtr tmp, cur = cache->stackItems;
+       while (cur) {
+           tmp = cur;
+           cur = cur->next;
+           /*
+           * REVISIT TODO: Should be call a destruction-function
+           * instead?
+           */
+           xmlFree(tmp);
+       }
+    }
+    xmlFree(cache);
+}
+
+/**
+ * xsltNewTransformContext:
+ * @style:  a parsed XSLT stylesheet
+ * @doc:  the input document
+ *
+ * Create a new XSLT TransformContext
+ *
+ * Returns the newly allocated xsltTransformContextPtr or NULL in case of error
+ */
+xsltTransformContextPtr
+xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) {
+    xsltTransformContextPtr cur;
+    xsltDocumentPtr docu;
+    int i;
+
+    cur = (xsltTransformContextPtr) xmlMalloc(sizeof(xsltTransformContext));
+    if (cur == NULL) {
+       xsltTransformError(NULL, NULL, (xmlNodePtr)doc,
+               "xsltNewTransformContext : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltTransformContext));
+
+    cur->cache = xsltTransformCacheCreate();
+    if (cur->cache == NULL)
+       goto internal_err;
+    /*
+     * setup of the dictionnary must be done early as some of the
+     * processing later like key handling may need it.
+     */
+    cur->dict = xmlDictCreateSub(style->dict);
+    cur->internalized = ((style->internalized) && (cur->dict != NULL));
+#ifdef WITH_XSLT_DEBUG
+    xsltGenericDebug(xsltGenericDebugContext,
+            "Creating sub-dictionary from stylesheet for transformation\n");
+#endif
+
+    /*
+     * initialize the template stack
+     */
+    cur->templTab = (xsltTemplatePtr *)
+               xmlMalloc(10 * sizeof(xsltTemplatePtr));
+    if (cur->templTab == NULL) {
+       xsltTransformError(NULL, NULL, (xmlNodePtr) doc,
+               "xsltNewTransformContext: out of memory\n");
+       goto internal_err;
+    }
+    cur->templNr = 0;
+    cur->templMax = 5;
+    cur->templ = NULL;
+
+    /*
+     * initialize the variables stack
+     */
+    cur->varsTab = (xsltStackElemPtr *)
+               xmlMalloc(10 * sizeof(xsltStackElemPtr));
+    if (cur->varsTab == NULL) {
+        xmlGenericError(xmlGenericErrorContext,
+               "xsltNewTransformContext: out of memory\n");
+       goto internal_err;
+    }
+    cur->varsNr = 0;
+    cur->varsMax = 10;
+    cur->vars = NULL;
+    cur->varsBase = 0;
+
+    /*
+     * the profiling stack is not initialized by default
+     */
+    cur->profTab = NULL;
+    cur->profNr = 0;
+    cur->profMax = 0;
+    cur->prof = 0;
+
+    cur->style = style;
+    xmlXPathInit();
+    cur->xpathCtxt = xmlXPathNewContext(doc);
+    if (cur->xpathCtxt == NULL) {
+       xsltTransformError(NULL, NULL, (xmlNodePtr) doc,
+               "xsltNewTransformContext : xmlXPathNewContext failed\n");
+       goto internal_err;
+    }
+    /*
+    * Create an XPath cache.
+    */
+    if (xmlXPathContextSetCache(cur->xpathCtxt, 1, -1, 0) == -1)
+       goto internal_err;
+    /*
+     * Initialize the extras array
+     */
+    if (style->extrasNr != 0) {
+       cur->extrasMax = style->extrasNr + 20;
+       cur->extras = (xsltRuntimeExtraPtr) 
+           xmlMalloc(cur->extrasMax * sizeof(xsltRuntimeExtra));
+       if (cur->extras == NULL) {
+           xmlGenericError(xmlGenericErrorContext,
+                   "xsltNewTransformContext: out of memory\n");
+           goto internal_err;
+       }
+       cur->extrasNr = style->extrasNr;
+       for (i = 0;i < cur->extrasMax;i++) {
+           cur->extras[i].info = NULL;
+           cur->extras[i].deallocate = NULL;
+           cur->extras[i].val.ptr = NULL;
+       }
+    } else {
+       cur->extras = NULL;
+       cur->extrasNr = 0;
+       cur->extrasMax = 0;
+    }
+
+    XSLT_REGISTER_VARIABLE_LOOKUP(cur);
+    XSLT_REGISTER_FUNCTION_LOOKUP(cur);
+    cur->xpathCtxt->nsHash = style->nsHash;
+    /*
+     * Initialize the registered external modules
+     */
+    xsltInitCtxtExts(cur);
+    /*
+     * Setup document element ordering for later efficiencies
+     * (bug 133289)
+     */
+    if (xslDebugStatus == XSLT_DEBUG_NONE)
+        xmlXPathOrderDocElems(doc);
+    /*
+     * Must set parserOptions before calling xsltNewDocument
+     * (bug 164530)
+     */
+    cur->parserOptions = XSLT_PARSE_OPTIONS;
+    docu = xsltNewDocument(cur, doc);
+    if (docu == NULL) {
+       xsltTransformError(cur, NULL, (xmlNodePtr)doc,
+               "xsltNewTransformContext : xsltNewDocument failed\n");
+       goto internal_err;
+    }
+    docu->main = 1;
+    cur->document = docu;    
+    cur->inst = NULL;
+    cur->outputFile = NULL;
+    cur->sec = xsltGetDefaultSecurityPrefs();
+    cur->debugStatus = xslDebugStatus;
+    cur->traceCode = (unsigned long*) &xsltDefaultTrace;
+    cur->xinclude = xsltGetXIncludeDefault();
+
+    return(cur);
+
+internal_err:
+    if (cur != NULL)
+       xsltFreeTransformContext(cur);
+    return(NULL);
+}
+
+/**
+ * xsltFreeTransformContext:
+ * @ctxt:  an XSLT parser context
+ *
+ * Free up the memory allocated by @ctxt
+ */
+void
+xsltFreeTransformContext(xsltTransformContextPtr ctxt) {
+    if (ctxt == NULL)
+       return;
+
+    /*
+     * Shutdown the extension modules associated to the stylesheet
+     * used if needed.
+     */
+    xsltShutdownCtxtExts(ctxt);
+
+    if (ctxt->xpathCtxt != NULL) {
+       ctxt->xpathCtxt->nsHash = NULL;
+       xmlXPathFreeContext(ctxt->xpathCtxt);
+    }
+    if (ctxt->templTab != NULL)
+       xmlFree(ctxt->templTab);
+    if (ctxt->varsTab != NULL)
+       xmlFree(ctxt->varsTab);
+    if (ctxt->profTab != NULL)
+       xmlFree(ctxt->profTab);
+    if ((ctxt->extrasNr > 0) && (ctxt->extras != NULL)) {
+       int i;
+
+       for (i = 0;i < ctxt->extrasNr;i++) {
+           if ((ctxt->extras[i].deallocate != NULL) &&
+               (ctxt->extras[i].info != NULL))
+               ctxt->extras[i].deallocate(ctxt->extras[i].info);
+       }
+       xmlFree(ctxt->extras);
+    }
+    xsltFreeGlobalVariables(ctxt);
+    xsltFreeDocuments(ctxt);
+    xsltFreeCtxtExts(ctxt);
+    xsltFreeRVTs(ctxt);
+    xsltTransformCacheFree(ctxt->cache);
+    xmlDictFree(ctxt->dict);
+#ifdef WITH_XSLT_DEBUG
+    xsltGenericDebug(xsltGenericDebugContext,
+                     "freeing transformation dictionnary\n");
+#endif
+    memset(ctxt, -1, sizeof(xsltTransformContext));
+    xmlFree(ctxt);
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Copy of Nodes in an XSLT fashion                *
+ *                                                                     *
+ ************************************************************************/
+
+xmlNodePtr xsltCopyTree(xsltTransformContextPtr ctxt,
+                        xmlNodePtr node, xmlNodePtr insert, int literal);
+
+/**
+ * xsltAddTextString:
+ * @ctxt:  a XSLT process context
+ * @target:  the text node where the text will be attached
+ * @string:  the text string
+ * @len:  the string length in byte
+ *
+ * Extend the current text node with the new string, it handles coalescing
+ *
+ * Returns: the text node
+ */
+static xmlNodePtr
+xsltAddTextString(xsltTransformContextPtr ctxt, xmlNodePtr target,
+                 const xmlChar *string, int len) {
+    /*
+     * optimization
+     */
+    if ((len <= 0) || (string == NULL) || (target == NULL))
+        return(target);
+
+    if (ctxt->lasttext == target->content) {
+
+       if (ctxt->lasttuse + len >= ctxt->lasttsize) {
+           xmlChar *newbuf;
+           int size;
+
+           size = ctxt->lasttsize + len + 100;
+           size *= 2;
+           newbuf = (xmlChar *) xmlRealloc(target->content,size);
+           if (newbuf == NULL) {
+               xsltTransformError(ctxt, NULL, target,
+                "xsltCopyText: text allocation failed\n");
+               return(NULL);
+           }
+           ctxt->lasttsize = size;
+           ctxt->lasttext = newbuf;
+           target->content = newbuf;
+       }
+       memcpy(&(target->content[ctxt->lasttuse]), string, len);
+       ctxt->lasttuse += len;
+       target->content[ctxt->lasttuse] = 0;
+    } else {
+       xmlNodeAddContent(target, string);
+       ctxt->lasttext = target->content;
+       len = xmlStrlen(target->content);
+       ctxt->lasttsize = len;
+       ctxt->lasttuse = len;
+    }
+    return(target);
+}
+
+/**
+ * xsltCopyTextString:
+ * @ctxt:  a XSLT process context
+ * @target:  the element where the text will be attached
+ * @string:  the text string
+ * @noescape:  should disable-escaping be activated for this text node.
+ *
+ * Adds @string to a newly created or an existent text node child of
+ * @target.
+ *
+ * Returns: the text node, where the text content of @cur is copied to.
+ *          NULL in case of API or internal errors.
+ */
+xmlNodePtr
+xsltCopyTextString(xsltTransformContextPtr ctxt, xmlNodePtr target,
+                  const xmlChar *string, int noescape)
+{
+    xmlNodePtr copy;
+    int len;
+
+    if (string == NULL)
+       return(NULL);
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    XSLT_TRACE(ctxt,XSLT_TRACE_COPY_TEXT,xsltGenericDebug(xsltGenericDebugContext,
+                    "xsltCopyTextString: copy text %s\n",
+                    string));
+#endif
+
+    /*
+    * Play save and reset the merging mechanism for every new
+    * target node.
+    */
+    if ((target == NULL) || (target->children == NULL)) {
+       ctxt->lasttext = NULL;
+    }
+
+    /* handle coalescing of text nodes here */
+    len = xmlStrlen(string);
+    if ((ctxt->type == XSLT_OUTPUT_XML) &&
+       (ctxt->style->cdataSection != NULL) &&
+       (target != NULL) && 
+       (target->type == XML_ELEMENT_NODE) &&
+       (((target->ns == NULL) && 
+         (xmlHashLookup2(ctxt->style->cdataSection,
+                         target->name, NULL) != NULL)) ||
+        ((target->ns != NULL) &&
+         (xmlHashLookup2(ctxt->style->cdataSection,
+                         target->name, target->ns->href) != NULL))))
+    {
+       /*
+       * Process "cdata-section-elements".
+       */
+       if ((target->last != NULL) &&
+           (target->last->type == XML_CDATA_SECTION_NODE))
+       {
+           return(xsltAddTextString(ctxt, target->last, string, len));
+       }
+       copy = xmlNewCDataBlock(ctxt->output, string, len);
+    } else if (noescape) {
+       /*
+       * Process "disable-output-escaping".
+       */
+       if ((target != NULL) && (target->last != NULL) &&
+           (target->last->type == XML_TEXT_NODE) &&
+           (target->last->name == xmlStringTextNoenc))
+       {
+           return(xsltAddTextString(ctxt, target->last, string, len));
+       }
+       copy = xmlNewTextLen(string, len);
+       if (copy != NULL)
+           copy->name = xmlStringTextNoenc;
+    } else {
+       /*
+       * Default processing.
+       */
+       if ((target != NULL) && (target->last != NULL) &&
+           (target->last->type == XML_TEXT_NODE) &&
+           (target->last->name == xmlStringText)) {
+           return(xsltAddTextString(ctxt, target->last, string, len));
+       }
+       copy = xmlNewTextLen(string, len);
+    }
+    if (copy != NULL) {
+       if (target != NULL)
+           xmlAddChild(target, copy);
+       ctxt->lasttext = copy->content;
+       ctxt->lasttsize = len;
+       ctxt->lasttuse = len;
+    } else {
+       xsltTransformError(ctxt, NULL, target,
+                        "xsltCopyTextString: text copy failed\n");
+       ctxt->lasttext = NULL;
+    }
+    return(copy);
+}
+
+/**
+ * xsltCopyText:
+ * @ctxt:  a XSLT process context
+ * @target:  the element where the text will be attached
+ * @cur:  the text or CDATA node
+ * @interned:  the string is in the target doc dictionnary
+ *
+ * Copy the text content of @cur and append it to @target's children.
+ *
+ * Returns: the text node, where the text content of @cur is copied to.
+ *          NULL in case of API or internal errors.
+ */
+static xmlNodePtr
+xsltCopyText(xsltTransformContextPtr ctxt, xmlNodePtr target,
+            xmlNodePtr cur, int interned)
+{
+    xmlNodePtr copy;
+
+    if ((cur->type != XML_TEXT_NODE) &&
+       (cur->type != XML_CDATA_SECTION_NODE))
+       return(NULL);
+    if (cur->content == NULL) 
+       return(NULL);
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    if (cur->type == XML_CDATA_SECTION_NODE) {
+       XSLT_TRACE(ctxt,XSLT_TRACE_COPY_TEXT,xsltGenericDebug(xsltGenericDebugContext,
+                        "xsltCopyText: copy CDATA text %s\n",
+                        cur->content));
+    } else if (cur->name == xmlStringTextNoenc) {
+       XSLT_TRACE(ctxt,XSLT_TRACE_COPY_TEXT,xsltGenericDebug(xsltGenericDebugContext,
+                    "xsltCopyText: copy unescaped text %s\n",
+                        cur->content));
+    } else {
+       XSLT_TRACE(ctxt,XSLT_TRACE_COPY_TEXT,xsltGenericDebug(xsltGenericDebugContext,
+                        "xsltCopyText: copy text %s\n",
+                        cur->content));
+    }
+#endif
+
+    /*
+    * Play save and reset the merging mechanism for every new
+    * target node.
+    */
+    if ((target == NULL) || (target->children == NULL)) {
+       ctxt->lasttext = NULL;
+    }
+
+    if ((ctxt->style->cdataSection != NULL) &&
+       (ctxt->type == XSLT_OUTPUT_XML) &&      
+       (target != NULL) &&
+       (target->type == XML_ELEMENT_NODE) &&
+       (((target->ns == NULL) && 
+         (xmlHashLookup2(ctxt->style->cdataSection,
+                         target->name, NULL) != NULL)) ||
+        ((target->ns != NULL) &&
+         (xmlHashLookup2(ctxt->style->cdataSection,
+                         target->name, target->ns->href) != NULL))))
+    {
+       /*
+       * Process "cdata-section-elements".
+       */
+       /* 
+       * OPTIMIZE TODO: xsltCopyText() is also used for attribute content.     
+       */
+       /*
+       * TODO: Since this doesn't merge adjacent CDATA-section nodes,
+       * we'll get: <![CDATA[x]]><!CDATA[y]]>.
+       * TODO: Reported in #321505.
+       */
+       if ((target->last != NULL) &&
+            (target->last->type == XML_CDATA_SECTION_NODE))
+       {
+           /*
+           * Append to existing CDATA-section node.
+           */
+           copy = xsltAddTextString(ctxt, target->last, cur->content,
+               xmlStrlen(cur->content));
+           goto exit;
+       } else {
+           unsigned int len;
+
+           len = xmlStrlen(cur->content);          
+           copy = xmlNewCDataBlock(ctxt->output, cur->content, len);
+           if (copy == NULL)
+               goto exit;
+           ctxt->lasttext = copy->content;
+           ctxt->lasttsize = len;
+           ctxt->lasttuse = len;
+       }
+    } else if ((target != NULL) &&
+       (target->last != NULL) &&
+       /* both escaped or both non-escaped text-nodes */
+       (((target->last->type == XML_TEXT_NODE) &&
+       (target->last->name == cur->name)) ||
+        /* non-escaped text nodes and CDATA-section nodes */
+       (((target->last->type == XML_CDATA_SECTION_NODE) &&
+       (cur->name == xmlStringTextNoenc)))))
+    {
+       /*
+        * we are appending to an existing text node
+        */
+       copy = xsltAddTextString(ctxt, target->last, cur->content,
+           xmlStrlen(cur->content));
+       goto exit;
+    } else if ((interned) && (target != NULL) &&
+       (target->doc != NULL) &&
+       (target->doc->dict == ctxt->dict))
+    {        
+       /*
+       * TODO: DO we want to use this also for "text" output?
+       */
+        copy = xmlNewTextLen(NULL, 0);
+       if (copy == NULL)
+           goto exit;  
+       if (cur->name == xmlStringTextNoenc)
+           copy->name = xmlStringTextNoenc;
+       
+       /*
+        * Must confirm that content is in dict (bug 302821)
+        * TODO: This check should be not needed for text coming
+        * from the stylesheets 
+        */
+       if (xmlDictOwns(ctxt->dict, cur->content))
+           copy->content = cur->content;
+       else {
+           if ((copy->content = xmlStrdup(cur->content)) == NULL)
+               return NULL;
+       }
+    } else {
+        /*
+        * normal processing. keep counters to extend the text node
+        * in xsltAddTextString if needed.
+        */
+        unsigned int len;
+
+       len = xmlStrlen(cur->content);
+       copy = xmlNewTextLen(cur->content, len);
+       if (copy == NULL)
+           goto exit;
+       if (cur->name == xmlStringTextNoenc)
+           copy->name = xmlStringTextNoenc;
+       ctxt->lasttext = copy->content;
+       ctxt->lasttsize = len;
+       ctxt->lasttuse = len;
+    }
+    if (copy != NULL) {
+       if (target != NULL) {
+           copy->doc = target->doc;
+           /*
+           * MAYBE TODO: Maybe we should reset the ctxt->lasttext here
+           *  to ensure that the optimized text-merging mechanism
+           *  won't interfere with normal node-merging in any case.
+           */
+           xmlAddChild(target, copy);
+       }
+    } else {
+       xsltTransformError(ctxt, NULL, target,
+                        "xsltCopyText: text copy failed\n");
+    }
+
+exit:
+    if ((copy == NULL) || (copy->content == NULL)) {
+       xsltTransformError(ctxt, NULL, target,
+           "Internal error in xsltCopyText(): "
+           "Failed to copy the string.\n");
+       ctxt->state = XSLT_STATE_STOPPED;
+    }
+    return(copy);
+}
+
+/**
+ * xsltShallowCopyAttr:
+ * @ctxt:  a XSLT process context
+ * @invocNode: responsible node in the stylesheet; used for error reports
+ * @target:  the element where the attribute will be grafted
+ * @attr: the attribute to be copied
+ *
+ * Do a copy of an attribute.
+ * Called by:
+ *  - xsltCopyTreeInternal()
+ *  - xsltCopyOf()
+ *  - xsltCopy()
+ *
+ * Returns: a new xmlAttrPtr, or NULL in case of error.
+ */
+static xmlAttrPtr
+xsltShallowCopyAttr(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
+            xmlNodePtr target, xmlAttrPtr attr)
+{
+    xmlAttrPtr copy;
+    xmlChar *value;
+
+    if (attr == NULL)
+       return(NULL);
+
+    if (target->type != XML_ELEMENT_NODE) {
+       xsltTransformError(ctxt, NULL, invocNode,
+           "Cannot add an attribute node to a non-element node.\n");
+       return(NULL);
+    }
+    
+    if (target->children != NULL) {
+       xsltTransformError(ctxt, NULL, invocNode,
+           "Attribute nodes must be added before "
+           "any child nodes to an element.\n");
+       return(NULL);
+    }
+
+    value = xmlNodeListGetString(attr->doc, attr->children, 1);
+    if (attr->ns != NULL) {
+       xmlNsPtr ns; 
+
+       ns = xsltGetSpecialNamespace(ctxt, invocNode,
+           attr->ns->href, attr->ns->prefix, target);
+       if (ns == NULL) {
+           xsltTransformError(ctxt, NULL, invocNode,
+               "Namespace fixup error: Failed to acquire an in-scope "
+               "namespace binding of the copied attribute '{%s}%s'.\n",
+               attr->ns->href, attr->name);
+           /*
+           * TODO: Should we just stop here?
+           */
+       }
+       /*
+       * Note that xmlSetNsProp() will take care of duplicates
+       * and assigns the new namespace even to a duplicate.
+       */
+       copy = xmlSetNsProp(target, ns, attr->name, value);
+    } else {
+       copy = xmlSetNsProp(target, NULL, attr->name, value);
+    }
+    if (value != NULL)
+       xmlFree(value);
+
+    if (copy == NULL)
+       return(NULL);
+
+#if 0
+    /*
+    * NOTE: This was optimized according to bug #342695.
+    * TODO: Can this further be optimized, if source and target
+    *  share the same dict and attr->children is just 1 text node
+    *  which is in the dict? How probable is such a case?
+    */
+    /*
+    * TODO: Do we need to create an empty text node if the value
+    *  is the empty string?
+    */
+    value = xmlNodeListGetString(attr->doc, attr->children, 1);
+    if (value != NULL) {
+       txtNode = xmlNewDocText(target->doc, NULL);
+       if (txtNode == NULL)
+           return(NULL);
+       if ((target->doc != NULL) &&
+           (target->doc->dict != NULL))
+       {
+           txtNode->content =
+               (xmlChar *) xmlDictLookup(target->doc->dict,
+                   BAD_CAST value, -1);
+           xmlFree(value);
+       } else
+           txtNode->content = value;
+       copy->children = txtNode;
+    }
+#endif
+
+    return(copy);
+}
+
+/**
+ * xsltCopyAttrListNoOverwrite:
+ * @ctxt:  a XSLT process context
+ * @invocNode: responsible node in the stylesheet; used for error reports
+ * @target:  the element where the new attributes will be grafted
+ * @attr:  the first attribute in the list to be copied
+ *
+ * Copies a list of attribute nodes, starting with @attr, over to the
+ * @target element node.
+ *
+ * Called by:
+ *  - xsltCopyTreeInternal()
+ *
+ * Returns 0 on success and -1 on errors and internal errors.
+ */
+static int
+xsltCopyAttrListNoOverwrite(xsltTransformContextPtr ctxt,
+                           xmlNodePtr invocNode,
+                           xmlNodePtr target, xmlAttrPtr attr)
+{
+    xmlAttrPtr last = NULL, copy;
+    xmlNsPtr origNs = NULL, copyNs = NULL;
+    xmlChar *value = NULL;
+
+    /*
+    * Don't use xmlCopyProp() here, since it will try to
+    * reconciliate namespaces.
+    */
+    while (attr != NULL) {
+       /*
+       * Find a namespace node in the tree of @target.
+       * Avoid searching for the same ns.
+       */
+       if (attr->ns != origNs) {
+           origNs = attr->ns;
+           if (attr->ns != NULL) {
+               copyNs = xsltGetSpecialNamespace(ctxt, invocNode,
+                   attr->ns->href, attr->ns->prefix, target);
+               if (copyNs == NULL)
+                   return(-1);
+           } else
+               copyNs = NULL;
+       }
+       if (attr->children)
+           value = xmlNodeListGetString(attr->doc, attr->children, 1);
+       /*
+       * REVISIT: I think xmlNewDocProp() is the only attr function
+       * which does not eval if the attr is of type ID. This is good,
+       * since we don't need this.
+       */
+       copy = xmlNewDocProp(target->doc, attr->name, BAD_CAST value);
+       if (copy == NULL)
+           return(-1);
+       copy->parent = target;
+       copy->ns = copyNs;
+       
+       if (last == NULL) {
+           target->properties = copy;
+           last = copy;
+       } else {
+           last->next = copy;
+           copy->prev = last;
+           last = copy;
+       }
+       /*
+       * OPTIMIZE TODO: How to avoid this intermediate string?
+       */
+       if (value != NULL) {
+           xmlFree(value);
+           value = NULL;
+       }
+       attr = attr->next;
+    }    
+    return(0);
+}
+
+/**
+ * xsltShallowCopyElem:
+ * @ctxt:  the XSLT process context
+ * @node:  the element node in the source tree
+ *         or the Literal Result Element
+ * @insert:  the parent in the result tree
+ * @isLRE: if @node is a Literal Result Element
+ *
+ * Make a copy of the element node @node
+ * and insert it as last child of @insert.
+ *
+ * URGENT TODO: The problem with this one (for the non-refactored code)
+ * is that it is used for both, Literal Result Elements *and*
+ * copying input nodes.
+ *
+ * BIG NOTE: This is only called for XML_ELEMENT_NODEs.
+ *
+ * Called from:
+ *   xsltApplySequenceConstructor()
+ *    (for Literal Result Elements - which is a problem)
+ *   xsltCopy() (for shallow-copying elements via xsl:copy)
+ *
+ * Returns a pointer to the new node, or NULL in case of error
+ */
+static xmlNodePtr
+xsltShallowCopyElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                   xmlNodePtr insert, int isLRE)
+{
+    xmlNodePtr copy;
+
+    if ((node->type == XML_DTD_NODE) || (insert == NULL))
+       return(NULL);
+    if ((node->type == XML_TEXT_NODE) ||
+       (node->type == XML_CDATA_SECTION_NODE))
+       return(xsltCopyText(ctxt, insert, node, 0));
+
+    copy = xmlDocCopyNode(node, insert->doc, 0);
+    if (copy != NULL) {
+       copy->doc = ctxt->output;
+       xmlAddChild(insert, copy);
+
+       if (node->type == XML_ELEMENT_NODE) {
+           /*
+            * Add namespaces as they are needed
+            */
+           if (node->nsDef != NULL) {
+               /*
+               * TODO: Remove the LRE case in the refactored code
+               * gets enabled.
+               */
+               if (isLRE)
+                   xsltCopyNamespaceList(ctxt, copy, node->nsDef);
+               else
+                   xsltCopyNamespaceListInternal(copy, node->nsDef);
+           }
+
+           /*
+           * URGENT TODO: The problem with this is that it does not
+           *  copy over all namespace nodes in scope.
+           *  The damn thing about this is, that we would need to
+           *  use the xmlGetNsList(), for every single node; this is
+           *  also done in xsltCopyTreeInternal(), but only for the top node.
+           */
+           if (node->ns != NULL) {
+               if (isLRE) {
+                   /*
+                   * REVISIT TODO: Since the non-refactored code still does
+                   *  ns-aliasing, we need to call xsltGetNamespace() here.
+                   *  Remove this when ready.
+                   */
+                   copy->ns = xsltGetNamespace(ctxt, node, node->ns, copy);
+               } else {
+                   copy->ns = xsltGetSpecialNamespace(ctxt,
+                       node, node->ns->href, node->ns->prefix, copy);
+                   
+               }
+           } else if ((insert->type == XML_ELEMENT_NODE) &&
+                      (insert->ns != NULL))
+           {
+               /*
+               * "Undeclare" the default namespace.
+               */
+               xsltGetSpecialNamespace(ctxt, node, NULL, NULL, copy);
+           }
+       }
+    } else {
+       xsltTransformError(ctxt, NULL, node,
+               "xsltShallowCopyElem: copy %s failed\n", node->name);
+    }
+    return(copy);
+}
+
+/**
+ * xsltCopyTreeList:
+ * @ctxt:  a XSLT process context
+ * @invocNode: responsible node in the stylesheet; used for error reports
+ * @list:  the list of element nodes in the source tree.
+ * @insert:  the parent in the result tree.
+ * @literal:  is this a literal result element list
+ *
+ * Make a copy of the full list of tree @list
+ * and insert it as last children of @insert
+ *
+ * NOTE: Not to be used for Literal Result Elements.
+ *
+ * Used by:
+ *  - xsltCopyOf()
+ *
+ * Returns a pointer to the new list, or NULL in case of error
+ */
+static xmlNodePtr
+xsltCopyTreeList(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
+                xmlNodePtr list,
+                xmlNodePtr insert, int isLRE, int topElemVisited)
+{
+    xmlNodePtr copy, ret = NULL;
+
+    while (list != NULL) {
+       copy = xsltCopyTreeInternal(ctxt, invocNode,
+           list, insert, isLRE, topElemVisited);
+       if (copy != NULL) {
+           if (ret == NULL) {
+               ret = copy;
+           }
+       }
+       list = list->next;
+    }
+    return(ret);
+}
+
+/**
+ * xsltCopyNamespaceListInternal:
+ * @node:  the target node
+ * @cur:  the first namespace
+ *
+ * Do a copy of a namespace list. If @node is non-NULL the
+ * new namespaces are added automatically.
+ * Called by:
+ *   xsltCopyTreeInternal()
+ *
+ * QUESTION: What is the exact difference between this function
+ *  and xsltCopyNamespaceList() in "namespaces.c"?
+ * ANSWER: xsltCopyNamespaceList() tries to apply ns-aliases.
+ *
+ * Returns: a new xmlNsPtr, or NULL in case of error.
+ */
+static xmlNsPtr
+xsltCopyNamespaceListInternal(xmlNodePtr elem, xmlNsPtr ns) {
+    xmlNsPtr ret = NULL;
+    xmlNsPtr p = NULL, q, luNs;
+
+    if (ns == NULL)
+       return(NULL);
+    /*
+     * One can add namespaces only on element nodes
+     */
+    if ((elem != NULL) && (elem->type != XML_ELEMENT_NODE))
+       elem = NULL;
+
+    do {
+       if (ns->type != XML_NAMESPACE_DECL)
+           break;
+       /*
+        * Avoid duplicating namespace declarations on the tree.
+        */
+       if (elem != NULL) {         
+           if ((elem->ns != NULL) &&
+               xmlStrEqual(elem->ns->prefix, ns->prefix) &&
+               xmlStrEqual(elem->ns->href, ns->href))
+           {
+               ns = ns->next;
+               continue;
+           }
+           luNs = xmlSearchNs(elem->doc, elem, ns->prefix);
+           if ((luNs != NULL) && (xmlStrEqual(luNs->href, ns->href)))
+           {
+               ns = ns->next;
+               continue;
+           }
+       }               
+       q = xmlNewNs(elem, ns->href, ns->prefix);
+       if (p == NULL) {
+           ret = p = q;
+       } else if (q != NULL) {
+           p->next = q;
+           p = q;
+       }
+       ns = ns->next;  
+    } while (ns != NULL);
+    return(ret);
+}
+
+/**
+ * xsltShallowCopyNsNode:
+ * @ctxt:  the XSLT transformation context
+ * @invocNode: responsible node in the stylesheet; used for error reports
+ * @insert:  the target element node in the result tree
+ * @ns: the namespace node
+ *
+ * This is used for copying ns-nodes with xsl:copy-of and xsl:copy.
+ *
+ * Returns a new/existing ns-node, or NULL.
+ */
+static int
+xsltShallowCopyNsNode(xsltTransformContextPtr ctxt,
+                     xmlNodePtr invocNode,
+                     xmlNodePtr insert,
+                     xmlNsPtr ns)
+{
+    xmlNsPtr tmpns;
+
+    if ((insert == NULL) || (insert->type != XML_ELEMENT_NODE))
+       return(-1);
+    
+    if (insert->children != NULL) {
+       xsltTransformError(ctxt, NULL, invocNode,
+           "Namespace nodes must be added before "
+           "any child nodes are added to an element.\n");
+       return(1);
+    }
+    /*    
+    *
+    * BIG NOTE: Xalan-J simply overwrites any ns-decls with
+    * an equal prefix. We definitively won't do that.
+    *
+    * MSXML 4.0 and the .NET ignores ns-decls for which an
+    * equal prefix is already in use.
+    *
+    * Saxon raises an error like:
+    * "net.sf.saxon.xpath.DynamicError: Cannot create two namespace
+    * nodes with the same name".
+    *
+    * NOTE: We'll currently follow MSXML here.
+    * REVISIT TODO: Check if it's better to follow Saxon here.
+    */
+    if (ns->prefix == NULL) {
+       /*
+       * If we are adding ns-nodes to an element using e.g.
+       * <xsl:copy-of select="/foo/namespace::*">, then we need
+       * to ensure that we don't incorrectly declare a default
+       * namespace on an element in no namespace, which otherwise
+       * would move the element incorrectly into a namespace, if
+       * the node tree is serialized.
+       */
+       if (insert->ns == NULL)
+           goto occupied;
+    } else if ((ns->prefix[0] == 'x') &&
+       xmlStrEqual(ns->prefix, BAD_CAST "xml"))
+    {
+       return(0);
+    }
+
+    if (insert->nsDef != NULL) {
+       tmpns = insert->nsDef;
+       do {
+           if ((tmpns->prefix == NULL) == (ns->prefix == NULL)) {              
+               if ((tmpns->prefix == ns->prefix) ||
+                   xmlStrEqual(tmpns->prefix, ns->prefix))
+               {
+                   /*
+                   * Same prefix.
+                   */
+                   if (xmlStrEqual(tmpns->href, ns->href))
+                       return(0);
+                   goto occupied;
+               }
+           }
+           tmpns = tmpns->next;
+       } while (tmpns != NULL);
+    }
+    tmpns = xmlSearchNs(insert->doc, insert, ns->prefix);
+    if ((tmpns != NULL) && xmlStrEqual(tmpns->href, ns->href))
+       return(0);
+    /*
+    * Declare a new namespace.
+    * TODO: The problem (wrt efficiency) with this xmlNewNs() is
+    * that it will again search the already declared namespaces
+    * for a duplicate :-/
+    */
+    xmlNewNs(insert, ns->href, ns->prefix);
+    return(0);    
+
+occupied:
+    /*
+    * TODO: We could as well raise an error here (like Saxon does),
+    * or at least generate a warning.
+    */
+    return(0);
+}
+
+/**
+ * xsltCopyTreeInternal:
+ * @ctxt:  the XSLT transformation context
+ * @invocNode: responsible node in the stylesheet; used for error reports
+ * @node:  the element node in the source tree
+ * @insert:  the parent in the result tree
+ * @isLRE:  indicates if @node is a Literal Result Element
+ * @topElemVisited: indicates if a top-most element was already processed
+ *
+ * Make a copy of the full tree under the element node @node
+ * and insert it as last child of @insert
+ *
+ * NOTE: Not to be used for Literal Result Elements.
+ *
+ * Used by:
+ *  - xsltCopyOf()
+ *
+ * Returns a pointer to the new tree, or NULL in case of error
+ */
+static xmlNodePtr
+xsltCopyTreeInternal(xsltTransformContextPtr ctxt,
+                    xmlNodePtr invocNode,
+                    xmlNodePtr node,
+                    xmlNodePtr insert, int isLRE, int topElemVisited)
+{
+    xmlNodePtr copy;
+
+    if (node == NULL)
+       return(NULL);
+    switch (node->type) {
+        case XML_ELEMENT_NODE:
+        case XML_ENTITY_REF_NODE:
+        case XML_ENTITY_NODE:
+        case XML_PI_NODE:
+        case XML_COMMENT_NODE:
+        case XML_DOCUMENT_NODE:
+        case XML_HTML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+        case XML_DOCB_DOCUMENT_NODE:
+#endif
+           break;
+        case XML_TEXT_NODE: {
+           int noenc = (node->name == xmlStringTextNoenc);
+           return(xsltCopyTextString(ctxt, insert, node->content, noenc));
+           }
+        case XML_CDATA_SECTION_NODE:
+           return(xsltCopyTextString(ctxt, insert, node->content, 0));
+        case XML_ATTRIBUTE_NODE:
+           return((xmlNodePtr)
+               xsltShallowCopyAttr(ctxt, invocNode, insert, (xmlAttrPtr) node));
+        case XML_NAMESPACE_DECL:
+           return((xmlNodePtr) xsltShallowCopyNsNode(ctxt, invocNode,
+               insert, (xmlNsPtr) node));
+           
+        case XML_DOCUMENT_TYPE_NODE:
+        case XML_DOCUMENT_FRAG_NODE:
+        case XML_NOTATION_NODE:
+        case XML_DTD_NODE:
+        case XML_ELEMENT_DECL:
+        case XML_ATTRIBUTE_DECL:
+        case XML_ENTITY_DECL:
+        case XML_XINCLUDE_START:
+        case XML_XINCLUDE_END:
+            return(NULL);
+    }    
+    if (XSLT_IS_RES_TREE_FRAG(node)) {
+       if (node->children != NULL)
+           copy = xsltCopyTreeList(ctxt, invocNode,
+               node->children, insert, 0, 0);
+       else
+           copy = NULL;
+       return(copy);
+    }
+    copy = xmlDocCopyNode(node, insert->doc, 0);
+    if (copy != NULL) {
+       copy->doc = ctxt->output;
+       xmlAddChild(insert, copy);
+       /*
+        * The node may have been coalesced into another text node.
+        */
+       if (insert->last != copy)
+           return(insert->last);
+       copy->next = NULL;
+
+       if (node->type == XML_ELEMENT_NODE) {       
+           /*
+           * Copy in-scope namespace nodes.
+           *
+           * REVISIT: Since we try to reuse existing in-scope ns-decls by
+           *  using xmlSearchNsByHref(), this will eventually change
+           *  the prefix of an original ns-binding; thus it might
+           *  break QNames in element/attribute content.
+           * OPTIMIZE TODO: If we had a xmlNsPtr * on the transformation
+           *  context, plus a ns-lookup function, which writes directly
+           *  to a given list, then we wouldn't need to create/free the
+           *  nsList every time.
+           */
+           if ((topElemVisited == 0) &&
+               (node->parent != NULL) &&
+               (node->parent->type != XML_DOCUMENT_NODE) &&
+               (node->parent->type != XML_HTML_DOCUMENT_NODE))
+           {
+               xmlNsPtr *nsList, *curns, ns;
+               
+               /*
+               * If this is a top-most element in a tree to be
+               * copied, then we need to ensure that all in-scope
+               * namespaces are copied over. For nodes deeper in the
+               * tree, it is sufficient to reconcile only the ns-decls
+               * (node->nsDef entries).
+               */
+               
+               nsList = xmlGetNsList(node->doc, node);
+               if (nsList != NULL) {
+                   curns = nsList;
+                   do {
+                       /*
+                       * Search by prefix first in order to break as less
+                       * QNames in element/attribute content as possible.
+                       */
+                       ns = xmlSearchNs(insert->doc, insert,
+                           (*curns)->prefix);
+                       
+                       if ((ns == NULL) ||
+                           (! xmlStrEqual(ns->href, (*curns)->href)))
+                       {
+                           ns = NULL;
+                           /*
+                           * Search by namespace name.
+                           * REVISIT TODO: Currently disabled.
+                           */
+#if 0
+                           ns = xmlSearchNsByHref(insert->doc,
+                               insert, (*curns)->href);
+#endif
+                       }
+                       if (ns == NULL) {
+                           /*
+                           * Declare a new namespace on the copied element.
+                           */
+                           ns = xmlNewNs(copy, (*curns)->href,
+                               (*curns)->prefix);
+                           /* TODO: Handle errors */
+                       }
+                       if (node->ns == *curns) {
+                           /*
+                           * If this was the original's namespace then set
+                           * the generated counterpart on the copy.
+                           */
+                           copy->ns = ns;
+                       }
+                       curns++;
+                   } while (*curns != NULL);
+                   xmlFree(nsList);
+               }
+           } else if (node->nsDef != NULL) {           
+               /*
+               * Copy over all namespace declaration attributes.               
+               */
+               if (node->nsDef != NULL) {
+                   if (isLRE)
+                       xsltCopyNamespaceList(ctxt, copy, node->nsDef);
+                   else
+                       xsltCopyNamespaceListInternal(copy, node->nsDef);
+               }
+           }
+           /*
+           * Set the namespace.
+           */
+           if (node->ns != NULL) {
+               if (copy->ns == NULL) {
+                   /*
+                   * This will map copy->ns to one of the newly created
+                   * in-scope ns-decls, OR create a new ns-decl on @copy.
+                   */
+                   copy->ns = xsltGetSpecialNamespace(ctxt, invocNode,
+                       node->ns->href, node->ns->prefix, copy);
+               }
+           } else if ((insert->type == XML_ELEMENT_NODE) &&
+               (insert->ns != NULL))
+           {
+               /*
+               * "Undeclare" the default namespace on @copy with xmlns="".
+               */
+               xsltGetSpecialNamespace(ctxt, invocNode, NULL, NULL, copy);
+           }
+           /*
+           * Copy attribute nodes.
+           */
+           if (node->properties != NULL) {
+               xsltCopyAttrListNoOverwrite(ctxt, invocNode,
+                   copy, node->properties);
+           }
+           if (topElemVisited == 0)
+               topElemVisited = 1;
+       }
+       /*
+       * Copy the subtree.
+       */
+       if (node->children != NULL) {
+           xsltCopyTreeList(ctxt, invocNode,
+               node->children, copy, isLRE, topElemVisited);
+       }
+    } else {
+       xsltTransformError(ctxt, NULL, invocNode,
+           "xsltCopyTreeInternal: Copying of '%s' failed.\n", node->name);
+    }
+    return(copy);
+}
+
+/**
+ * xsltCopyTree:
+ * @ctxt:  the XSLT transformation context
+ * @node:  the element node in the source tree
+ * @insert:  the parent in the result tree
+ * @literal:  indicates if @node is a Literal Result Element
+ *
+ * Make a copy of the full tree under the element node @node
+ * and insert it as last child of @insert
+ * For literal result element, some of the namespaces may not be copied
+ * over according to section 7.1.
+ * TODO: Why is this a public function?
+ *
+ * Returns a pointer to the new tree, or NULL in case of error
+ */
+xmlNodePtr
+xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr node,
+            xmlNodePtr insert, int literal)
+{
+    return(xsltCopyTreeInternal(ctxt, node, node, insert, literal, 0));
+    
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Error/fallback processing                               *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltApplyFallbacks:
+ * @ctxt:  a XSLT process context
+ * @node:  the node in the source tree.
+ * @inst:  the node generating the error
+ *
+ * Process possible xsl:fallback nodes present under @inst
+ *
+ * Returns the number of xsl:fallback element found and processed
+ */
+static int
+xsltApplyFallbacks(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                  xmlNodePtr inst) {
+
+    xmlNodePtr child;
+    int ret = 0;
+    
+    if ((ctxt == NULL) || (node == NULL) || (inst == NULL) ||
+       (inst->children == NULL))
+       return(0);
+
+    child = inst->children;
+    while (child != NULL) {
+        if ((IS_XSLT_ELEM(child)) &&
+            (xmlStrEqual(child->name, BAD_CAST "fallback"))) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+           xsltGenericDebug(xsltGenericDebugContext,
+                            "applying xsl:fallback\n");
+#endif
+           ret++;
+           xsltApplySequenceConstructor(ctxt, node, child->children,
+               NULL);
+       }
+       child = child->next;
+    }
+    return(ret);
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Default processing                              *
+ *                                                                     *
+ ************************************************************************/
+
+void xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                       xsltStackElemPtr params);
+/**
+ * xsltDefaultProcessOneNode:
+ * @ctxt:  a XSLT process context
+ * @node:  the node in the source tree.
+ * @params: extra parameters passed to the template if any
+ *
+ * Process the source node with the default built-in template rule:
+ * <xsl:template match="*|/">
+ *   <xsl:apply-templates/>
+ * </xsl:template>
+ *
+ * and
+ *
+ * <xsl:template match="text()|@*">
+ *   <xsl:value-of select="."/>
+ * </xsl:template>
+ *
+ * Note also that namespace declarations are copied directly:
+ *
+ * the built-in template rule is the only template rule that is applied
+ * for namespace nodes.
+ */
+static void
+xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                         xsltStackElemPtr params) {
+    xmlNodePtr copy;
+    xmlNodePtr delete = NULL, cur;
+    int nbchild = 0, oldSize;
+    int childno = 0, oldPos;
+    xsltTemplatePtr template;
+
+    CHECK_STOPPED;
+    /*
+     * Handling of leaves
+     */
+    switch (node->type) {
+       case XML_DOCUMENT_NODE:
+       case XML_HTML_DOCUMENT_NODE:
+       case XML_ELEMENT_NODE:
+           break;
+       case XML_CDATA_SECTION_NODE:
+#ifdef WITH_XSLT_DEBUG_PROCESS
+           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltDefaultProcessOneNode: copy CDATA %s\n",
+               node->content));
+#endif
+           copy = xsltCopyText(ctxt, ctxt->insert, node, 0);
+           if (copy == NULL) {
+               xsltTransformError(ctxt, NULL, node,
+                "xsltDefaultProcessOneNode: cdata copy failed\n");
+           }
+           return;
+       case XML_TEXT_NODE:
+#ifdef WITH_XSLT_DEBUG_PROCESS
+           if (node->content == NULL) {
+               XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+                "xsltDefaultProcessOneNode: copy empty text\n"));
+           } else {
+               XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+                "xsltDefaultProcessOneNode: copy text %s\n",
+                       node->content));
+            }
+#endif
+           copy = xsltCopyText(ctxt, ctxt->insert, node, 0);
+           if (copy == NULL) {
+               xsltTransformError(ctxt, NULL, node,
+                "xsltDefaultProcessOneNode: text copy failed\n");
+           }
+           return;
+       case XML_ATTRIBUTE_NODE:
+           cur = node->children;
+           while ((cur != NULL) && (cur->type != XML_TEXT_NODE))
+               cur = cur->next;
+           if (cur == NULL) {
+               xsltTransformError(ctxt, NULL, node,
+                "xsltDefaultProcessOneNode: no text for attribute\n");
+           } else {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               if (cur->content == NULL) {
+                   XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+                    "xsltDefaultProcessOneNode: copy empty text\n"));
+               } else {
+                   XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+                    "xsltDefaultProcessOneNode: copy text %s\n",
+                       cur->content));
+                }
+#endif
+               copy = xsltCopyText(ctxt, ctxt->insert, cur, 0);
+               if (copy == NULL) {
+                   xsltTransformError(ctxt, NULL, node,
+                    "xsltDefaultProcessOneNode: text copy failed\n");
+               }
+           }
+           return;
+       default:
+           return;
+    }
+    /*
+     * Handling of Elements: first pass, cleanup and counting
+     */
+    cur = node->children;
+    while (cur != NULL) {
+       switch (cur->type) {
+           case XML_TEXT_NODE:
+           case XML_CDATA_SECTION_NODE:
+           case XML_DOCUMENT_NODE:
+           case XML_HTML_DOCUMENT_NODE:
+           case XML_ELEMENT_NODE:
+           case XML_PI_NODE:
+           case XML_COMMENT_NODE:
+               nbchild++;
+               break;
+            case XML_DTD_NODE:
+               /* Unlink the DTD, it's still reachable using doc->intSubset */
+               if (cur->next != NULL)
+                   cur->next->prev = cur->prev;
+               if (cur->prev != NULL)
+                   cur->prev->next = cur->next;
+               break;
+           default:
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+                "xsltDefaultProcessOneNode: skipping node type %d\n",
+                                cur->type));
+#endif
+               delete = cur;
+       }
+       cur = cur->next;
+       if (delete != NULL) {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+                "xsltDefaultProcessOneNode: removing ignorable blank node\n"));
+#endif
+           xmlUnlinkNode(delete);
+           xmlFreeNode(delete);
+           delete = NULL;
+       }
+    }
+    if (delete != NULL) {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltDefaultProcessOneNode: removing ignorable blank node\n"));
+#endif
+       xmlUnlinkNode(delete);
+       xmlFreeNode(delete);
+       delete = NULL;
+    }
+
+    /*
+     * Handling of Elements: second pass, actual processing
+     */
+    oldSize = ctxt->xpathCtxt->contextSize;
+    oldPos = ctxt->xpathCtxt->proximityPosition;
+    cur = node->children;
+    while (cur != NULL) {
+       childno++;
+       switch (cur->type) {
+           case XML_DOCUMENT_NODE:
+           case XML_HTML_DOCUMENT_NODE:
+           case XML_ELEMENT_NODE:
+               ctxt->xpathCtxt->contextSize = nbchild;
+               ctxt->xpathCtxt->proximityPosition = childno;
+               xsltProcessOneNode(ctxt, cur, params);
+               break;
+           case XML_CDATA_SECTION_NODE:
+               template = xsltGetTemplate(ctxt, cur, NULL);
+               if (template) {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+                "xsltDefaultProcessOneNode: applying template for CDATA %s\n",
+                                    cur->content));
+#endif
+                   /*
+                   * Instantiate the xsl:template.
+                   */
+                   xsltApplyXSLTTemplate(ctxt, cur, template->content,
+                       template, params);
+               } else /* if (ctxt->mode == NULL) */ {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+                    "xsltDefaultProcessOneNode: copy CDATA %s\n",
+                                    cur->content));
+#endif
+                   copy = xsltCopyText(ctxt, ctxt->insert, cur, 0);
+                   if (copy == NULL) {
+                       xsltTransformError(ctxt, NULL, cur,
+                           "xsltDefaultProcessOneNode: cdata copy failed\n");
+                   }
+               }
+               break;
+           case XML_TEXT_NODE:
+               template = xsltGetTemplate(ctxt, cur, NULL);
+               if (template) {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltDefaultProcessOneNode: applying template for text %s\n",
+                                    cur->content));
+#endif
+                   ctxt->xpathCtxt->contextSize = nbchild;
+                   ctxt->xpathCtxt->proximityPosition = childno;
+                   /*
+                   * Instantiate the xsl:template.
+                   */
+                   xsltApplyXSLTTemplate(ctxt, cur, template->content,
+                       template, params);
+               } else /* if (ctxt->mode == NULL) */ {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   if (cur->content == NULL) {
+                       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+                        "xsltDefaultProcessOneNode: copy empty text\n"));
+                   } else {
+                       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+                    "xsltDefaultProcessOneNode: copy text %s\n",
+                                        cur->content));
+                    }
+#endif
+                   copy = xsltCopyText(ctxt, ctxt->insert, cur, 0);
+                   if (copy == NULL) {
+                       xsltTransformError(ctxt, NULL, cur,
+                           "xsltDefaultProcessOneNode: text copy failed\n");
+                   }
+               }
+               break;
+           case XML_PI_NODE:
+           case XML_COMMENT_NODE:
+               template = xsltGetTemplate(ctxt, cur, NULL);
+               if (template) {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   if (cur->type == XML_PI_NODE) {
+                       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+                    "xsltDefaultProcessOneNode: template found for PI %s\n",
+                                        cur->name));
+                   } else if (cur->type == XML_COMMENT_NODE) {
+                       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+                    "xsltDefaultProcessOneNode: template found for comment\n"));
+                    }
+#endif
+                   ctxt->xpathCtxt->contextSize = nbchild;
+                   ctxt->xpathCtxt->proximityPosition = childno;
+                   /*
+                   * Instantiate the xsl:template.
+                   */
+                   xsltApplyXSLTTemplate(ctxt, cur, template->content,
+                       template, params);
+               }
+               break;
+           default:
+               break;
+       }
+       cur = cur->next;
+    }
+    ctxt->xpathCtxt->contextSize = oldSize;
+    ctxt->xpathCtxt->proximityPosition = oldPos;
+}
+
+/**
+ * xsltProcessOneNode:
+ * @ctxt:  a XSLT process context
+ * @contextNode:  the "current node" in the source tree
+ * @withParams:  extra parameters (e.g. xsl:with-param) passed to the
+ *               template if any
+ *
+ * Process the source node.
+ */
+void
+xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
+                  xsltStackElemPtr withParams)
+{
+    xsltTemplatePtr templ;
+    xmlNodePtr oldNode;
+    
+    templ = xsltGetTemplate(ctxt, contextNode, NULL);
+    /*
+     * If no template is found, apply the default rule.
+     */
+    if (templ == NULL) {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+       if (contextNode->type == XML_DOCUMENT_NODE) {
+           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltProcessOneNode: no template found for /\n"));
+       } else if (contextNode->type == XML_CDATA_SECTION_NODE) {
+           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltProcessOneNode: no template found for CDATA\n"));
+       } else if (contextNode->type == XML_ATTRIBUTE_NODE) {
+           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltProcessOneNode: no template found for attribute %s\n",
+                            ((xmlAttrPtr) contextNode)->name));
+       } else  {
+           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltProcessOneNode: no template found for %s\n", contextNode->name));
+        }
+#endif
+       oldNode = ctxt->node;
+       ctxt->node = contextNode;
+       xsltDefaultProcessOneNode(ctxt, contextNode, withParams);
+       ctxt->node = oldNode;
+       return;
+    }
+
+    if (contextNode->type == XML_ATTRIBUTE_NODE) {
+       xsltTemplatePtr oldCurTempRule = ctxt->currentTemplateRule; 
+       /*
+       * Set the "current template rule".
+       */
+       ctxt->currentTemplateRule = templ;
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltProcessOneNode: applying template '%s' for attribute %s\n",
+                        templ->match, contextNode->name));
+#endif
+       xsltApplyXSLTTemplate(ctxt, contextNode, templ->content, templ, withParams);
+
+       ctxt->currentTemplateRule = oldCurTempRule;
+    } else {
+       xsltTemplatePtr oldCurTempRule = ctxt->currentTemplateRule; 
+       /*
+       * Set the "current template rule".
+       */
+       ctxt->currentTemplateRule = templ;
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+       if (contextNode->type == XML_DOCUMENT_NODE) {
+           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltProcessOneNode: applying template '%s' for /\n",
+                            templ->match));
+       } else {
+           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltProcessOneNode: applying template '%s' for %s\n",
+                            templ->match, contextNode->name));
+        }
+#endif
+       xsltApplyXSLTTemplate(ctxt, contextNode, templ->content, templ, withParams);
+
+       ctxt->currentTemplateRule = oldCurTempRule;
+    }
+}
+
+static xmlNodePtr
+xsltDebuggerStartSequenceConstructor(xsltTransformContextPtr ctxt,
+                                    xmlNodePtr contextNode,
+                                    xmlNodePtr list,
+                                    xsltTemplatePtr templ,
+                                    int *addCallResult)
+{
+    xmlNodePtr debugedNode = NULL;    
+
+    if (ctxt->debugStatus != XSLT_DEBUG_NONE) {
+        if (templ) {
+            *addCallResult = xslAddCall(templ, templ->elem);
+        } else {
+            *addCallResult = xslAddCall(NULL, list);
+        }
+        switch (ctxt->debugStatus) {
+            case XSLT_DEBUG_RUN_RESTART:
+            case XSLT_DEBUG_QUIT:
+                if (*addCallResult)
+                    xslDropCall();
+                return(NULL);
+        }
+        if (templ) {
+            xslHandleDebugger(templ->elem, contextNode, templ, ctxt);
+            debugedNode = templ->elem;
+        } else if (list) {
+            xslHandleDebugger(list, contextNode, templ, ctxt);
+            debugedNode = list;
+        } else if (ctxt->inst) {
+            xslHandleDebugger(ctxt->inst, contextNode, templ, ctxt);
+            debugedNode = ctxt->inst;
+        }
+    }
+    return(debugedNode);
+}
+
+static int
+xsltLocalVariablePush(xsltTransformContextPtr ctxt,
+                     xsltStackElemPtr variable,
+                     int level)
+{
+    if (ctxt->varsMax == 0) {
+       ctxt->varsMax = 10;
+       ctxt->varsTab =
+           (xsltStackElemPtr *) xmlMalloc(ctxt->varsMax *
+           sizeof(ctxt->varsTab[0]));
+       if (ctxt->varsTab == NULL) {
+           xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
+           return (-1);
+       }
+    }
+    if (ctxt->varsNr >= ctxt->varsMax) {
+       ctxt->varsMax *= 2;
+       ctxt->varsTab =
+           (xsltStackElemPtr *) xmlRealloc(ctxt->varsTab,
+           ctxt->varsMax *
+           sizeof(ctxt->varsTab[0]));
+       if (ctxt->varsTab == NULL) {
+           xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
+           return (-1);
+       }
+    }
+    ctxt->varsTab[ctxt->varsNr++] = variable;
+    ctxt->vars = variable;
+    variable->level = level;
+    return(0);
+}
+
+/**
+ * xsltReleaseLocalRVTs:
+ *
+ * Fragments which are results of extension instructions
+ * are preserved; all other fragments are freed/cached.
+ */
+static void
+xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base)
+{
+    xmlDocPtr cur = ctxt->localRVT, tmp;
+    
+    while ((cur != NULL) && (cur != base)) {
+       if (cur->psvi == (void *) ((long) 1)) {
+           cur = (xmlDocPtr) cur->next;
+       } else {
+           tmp = cur;
+           cur = (xmlDocPtr) cur->next;
+
+           if (tmp == ctxt->localRVT)
+               ctxt->localRVT = (xmlDocPtr) tmp->next;
+
+           /*
+           * We need ctxt->localRVTBase for extension instructions
+           * which return values (like EXSLT's function).
+           */
+           if (tmp == ctxt->localRVTBase)
+               ctxt->localRVTBase = (xmlDocPtr) tmp->next;
+
+           if (tmp->prev)
+               tmp->prev->next = (xmlNodePtr) cur;
+           if (cur)
+               cur->prev = tmp->prev;
+           xsltReleaseRVT(ctxt, tmp);
+       }
+    }
+}
+
+/**
+ * xsltApplySequenceConstructor:
+ * @ctxt:  a XSLT process context
+ * @contextNode:  the "current node" in the source tree
+ * @list:  the nodes of a sequence constructor;
+ *         (plus leading xsl:param elements)
+ * @templ: the compiled xsl:template (optional)
+ *
+ * Processes a sequence constructor.
+ * 
+ * NOTE: ctxt->currentTemplateRule was introduced to reflect the
+ * semantics of "current template rule". I.e. the field ctxt->templ
+ * is not intended to reflect this, thus always pushed onto the
+ * template stack.
+ */
+static void
+xsltApplySequenceConstructor(xsltTransformContextPtr ctxt,
+                            xmlNodePtr contextNode, xmlNodePtr list,
+                            xsltTemplatePtr templ)
+{
+    xmlNodePtr oldInsert, oldInst, oldCurInst, oldContextNode;
+    xmlNodePtr cur, insert, copy = NULL;
+    int level = 0, oldVarsNr;
+    xmlDocPtr oldLocalFragmentTop, oldLocalFragmentBase;
+
+#ifdef XSLT_REFACTORED
+    xsltStylePreCompPtr info;
+#endif
+
+#ifdef WITH_DEBUGGER
+    int addCallResult = 0;
+    xmlNodePtr debuggedNode = NULL;
+#endif
+
+    if (ctxt == NULL)
+       return;
+
+#ifdef WITH_DEBUGGER 
+    if (ctxt->debugStatus != XSLT_DEBUG_NONE) {
+       debuggedNode =
+           xsltDebuggerStartSequenceConstructor(ctxt, contextNode,
+               list, templ, &addCallResult);
+       if (debuggedNode == NULL)
+           return;
+    }
+#endif
+
+    if (list == NULL)
+        return;
+    CHECK_STOPPED;
+
+    oldLocalFragmentTop = ctxt->localRVT;
+    oldInsert = insert = ctxt->insert;
+    oldInst = oldCurInst = ctxt->inst;
+    oldContextNode = ctxt->node;
+    /*
+    * Save current number of variables on the stack; new vars are popped when
+    * exiting.
+    */
+    oldVarsNr = ctxt->varsNr;
+    /*
+    * Process the sequence constructor.
+    */
+    cur = list;
+    while (cur != NULL) {
+        ctxt->inst = cur;
+
+#ifdef WITH_DEBUGGER
+        switch (ctxt->debugStatus) {
+            case XSLT_DEBUG_RUN_RESTART:
+            case XSLT_DEBUG_QUIT:
+                break;
+
+        }
+#endif
+        /*
+         * Test; we must have a valid insertion point.
+         */
+        if (insert == NULL) {
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+            XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
+               "xsltApplySequenceConstructor: insert == NULL !\n"));
+#endif
+            goto error;
+        }
+
+#ifdef WITH_DEBUGGER
+        if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (debuggedNode != cur))
+            xslHandleDebugger(cur, contextNode, templ, ctxt);
+#endif
+
+#ifdef XSLT_REFACTORED
+       if (cur->type == XML_ELEMENT_NODE) {
+           info = (xsltStylePreCompPtr) cur->psvi;
+           /*
+           * We expect a compiled representation on:
+           * 1) XSLT instructions of this XSLT version (1.0)
+           *    (with a few exceptions)
+           * 2) Literal result elements
+           * 3) Extension instructions
+           * 4) XSLT instructions of future XSLT versions
+           *    (forwards-compatible mode).
+           */
+           if (info == NULL) {
+               /*
+               * Handle the rare cases where we don't expect a compiled
+               * representation on an XSLT element.
+               */
+               if (IS_XSLT_ELEM_FAST(cur) && IS_XSLT_NAME(cur, "message")) {
+                   xsltMessage(ctxt, contextNode, cur);
+                   goto skip_children;
+               }                                
+               /*
+               * Something really went wrong:
+               */
+               xsltTransformError(ctxt, NULL, cur,
+                   "Internal error in xsltApplySequenceConstructor(): "
+                   "The element '%s' in the stylesheet has no compiled "
+                   "representation.\n",
+                   cur->name);
+                goto skip_children;
+            }
+
+           if (info->type == XSLT_FUNC_LITERAL_RESULT_ELEMENT) {
+               xsltStyleItemLRElementInfoPtr lrInfo =
+                   (xsltStyleItemLRElementInfoPtr) info;
+               /*
+               * Literal result elements
+               * --------------------------------------------------------
+               */
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,
+                   xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltApplySequenceConstructor: copy literal result "
+                   "element '%s'\n", cur->name));
+#endif
+               /*
+               * Copy the raw element-node.
+               * OLD: if ((copy = xsltShallowCopyElem(ctxt, cur, insert))
+               *     == NULL)
+               *   goto error;
+               */              
+               copy = xmlDocCopyNode(cur, insert->doc, 0);
+               if (copy == NULL) {
+                   xsltTransformError(ctxt, NULL, cur,
+                       "Internal error in xsltApplySequenceConstructor(): "
+                       "Failed to copy literal result element '%s'.\n",
+                       cur->name);
+                   goto error;
+               } else {
+                   /*
+                   * Add the element-node to the result tree.
+                   */
+                   copy->doc = ctxt->output;
+                   xmlAddChild(insert, copy);
+                   /*
+                   * Create effective namespaces declarations.
+                   * OLD: xsltCopyNamespaceList(ctxt, copy, cur->nsDef);
+                   */
+                   if (lrInfo->effectiveNs != NULL) {
+                       xsltEffectiveNsPtr effNs = lrInfo->effectiveNs;
+                       xmlNsPtr ns, lastns = NULL;
+
+                       while (effNs != NULL) {
+                           /*
+                           * Avoid generating redundant namespace
+                           * declarations; thus lookup if there is already
+                           * such a ns-decl in the result.
+                           */                      
+                           ns = xmlSearchNs(copy->doc, copy, effNs->prefix);
+                           if ((ns != NULL) &&
+                               (xmlStrEqual(ns->href, effNs->nsName)))
+                           {
+                               effNs = effNs->next;
+                               continue;                           
+                           }
+                           ns = xmlNewNs(copy, effNs->nsName, effNs->prefix);
+                           if (ns == NULL) {
+                               xsltTransformError(ctxt, NULL, cur,
+                                   "Internal error in "
+                                   "xsltApplySequenceConstructor(): "
+                                   "Failed to copy a namespace "
+                                   "declaration.\n");
+                               goto error;
+                           }
+                                                               
+                           if (lastns == NULL)
+                               copy->nsDef = ns;
+                           else
+                               lastns->next =ns;
+                           lastns = ns;
+
+                           effNs = effNs->next;
+                       }
+                       
+                   }
+                   /*
+                   * NOTE that we don't need to apply ns-alising: this was
+                   *  already done at compile-time.
+                   */
+                   if (cur->ns != NULL) {
+                       /*
+                       * If there's no such ns-decl in the result tree,
+                       * then xsltGetSpecialNamespace() will
+                       * create a ns-decl on the copied node.
+                       */                      
+                       copy->ns = xsltGetSpecialNamespace(ctxt, cur,
+                           cur->ns->href, cur->ns->prefix, copy);                          
+                   } else {
+                       /*
+                       * Undeclare the default namespace if needed.
+                       * This can be skipped, if the result element has
+                       *  no ns-decls, in which case the result element
+                       *  obviously does not declare a default namespace;
+                       *  AND there's either no parent, or the parent
+                       *  element is in no namespace; this means there's no
+                       *  default namespace is scope to care about.
+                       *
+                       * REVISIT: This might result in massive
+                       *  generation of ns-decls if nodes in a default
+                       *  namespaces are mixed with nodes in no namespace.
+                       *  
+                       */
+                       if (copy->nsDef ||
+                           ((insert != NULL) &&
+                            (insert->type == XML_ELEMENT_NODE) &&
+                            (insert->ns != NULL)))
+                       {
+                           xsltGetSpecialNamespace(ctxt, cur,
+                               NULL, NULL, copy);
+                       }
+                   }
+               }
+               /*
+               * SPEC XSLT 2.0 "Each attribute of the literal result
+               *  element, other than an attribute in the XSLT namespace,
+               *  is processed to produce an attribute for the element in
+               *  the result tree."
+               * NOTE: See bug #341325.
+               */
+               if (cur->properties != NULL) {
+                   xsltAttrListTemplateProcess(ctxt, copy, cur->properties);
+               }
+           } else if (IS_XSLT_ELEM_FAST(cur)) {
+               /*
+               * XSLT instructions
+               * --------------------------------------------------------
+               */
+               if (info->type == XSLT_FUNC_UNKOWN_FORWARDS_COMPAT) {
+                   /*
+                   * We hit an unknown XSLT element.
+                   * Try to apply one of the fallback cases.
+                   */          
+                   ctxt->insert = insert;
+                   if (!xsltApplyFallbacks(ctxt, contextNode, cur)) {
+                       xsltTransformError(ctxt, NULL, cur,
+                           "The is no fallback behaviour defined for "
+                           "the unknown XSLT element '%s'.\n",
+                           cur->name);
+                   }                   
+                   ctxt->insert = oldInsert;
+               } else if (info->func != NULL) {
+                   /*
+                   * Execute the XSLT instruction.
+                   */
+                   ctxt->insert = insert;
+
+                   info->func(ctxt, contextNode, cur,
+                       (xsltElemPreCompPtr) info);
+
+                   /*
+                   * Cleanup temporary tree fragments.
+                   */
+                   if (oldLocalFragmentTop != ctxt->localRVT)
+                       xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
+
+                   ctxt->insert = oldInsert;
+               } else if (info->type == XSLT_FUNC_VARIABLE) {          
+                   xsltStackElemPtr tmpvar = ctxt->vars;
+               
+                   xsltParseStylesheetVariable(ctxt, cur);
+                   
+                   if (tmpvar != ctxt->vars) {
+                       /*
+                       * TODO: Using a @tmpvar is an annoying workaround, but
+                       *  the current mechanisms do not provide any other way
+                       *  of knowing if the var was really pushed onto the
+                       *  stack.
+                       */
+                       ctxt->vars->level = level;
+                   }
+               } else if (info->type == XSLT_FUNC_MESSAGE) {
+                   /*
+                   * TODO: Won't be hit, since we don't compile xsl:message.
+                   */
+                   xsltMessage(ctxt, contextNode, cur);
+               } else {
+                   xsltTransformError(ctxt, NULL, cur,
+                       "Unexpected XSLT element '%s'.\n", cur->name);                  
+               }
+               goto skip_children;
+
+           } else {
+               xsltTransformFunction func;
+               /*
+               * Extension intructions (elements)
+               * --------------------------------------------------------
+               */                              
+               if (cur->psvi == xsltExtMarker) {
+                   /*
+                   * The xsltExtMarker was set during the compilation
+                   * of extension instructions if there was no registered
+                   * handler for this specific extension function at
+                   * compile-time.
+                   * Libxslt will now lookup if a handler is
+                   * registered in the context of this transformation.
+                   */
+                   func = (xsltTransformFunction)
+                       xsltExtElementLookup(ctxt, cur->name, cur->ns->href);
+               } else
+                   func = ((xsltElemPreCompPtr) cur->psvi)->func;
+               
+               if (func == NULL) {
+                   /*
+                   * No handler available.
+                   * Try to execute fallback behaviour via xsl:fallback.
+                   */
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,
+                       xsltGenericDebug(xsltGenericDebugContext,
+                           "xsltApplySequenceConstructor: unknown extension %s\n",
+                           cur->name));
+#endif
+                   ctxt->insert = insert;
+                   if (!xsltApplyFallbacks(ctxt, contextNode, cur)) {
+                       xsltTransformError(ctxt, NULL, cur,
+                           "Unknown extension instruction '{%s}%s'.\n",
+                           cur->ns->href, cur->name);
+                   }                   
+                   ctxt->insert = oldInsert;               
+               } else {
+                   /*
+                   * Execute the handler-callback.
+                   */
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
+                       "xsltApplySequenceConstructor: extension construct %s\n",
+                       cur->name));
+#endif             
+                   ctxt->insert = insert;
+                   /*
+                   * We need the fragment base for extension instructions
+                   * which return values (like EXSLT's function).
+                   */
+                   oldLocalFragmentBase = ctxt->localRVTBase;
+                   ctxt->localRVTBase = NULL;
+
+                   func(ctxt, contextNode, cur, cur->psvi);
+
+                   ctxt->localRVTBase = oldLocalFragmentBase;
+                   /*
+                   * Cleanup temporary tree fragments.
+                   */
+                   if (oldLocalFragmentTop != ctxt->localRVT)
+                       xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
+
+                   ctxt->insert = oldInsert;
+               }
+               goto skip_children;
+           }
+
+       } else if (XSLT_IS_TEXT_NODE(cur)) {
+           /*
+           * Text
+           * ------------------------------------------------------------
+           */
+#ifdef WITH_XSLT_DEBUG_PROCESS
+            if (cur->name == xmlStringTextNoenc) {
+                XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,
+                   xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltApplySequenceConstructor: copy unescaped text '%s'\n",
+                   cur->content));
+            } else {
+                XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,
+                   xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltApplySequenceConstructor: copy text '%s'\n",
+                   cur->content));
+            }
+#endif
+            if (xsltCopyText(ctxt, insert, cur, ctxt->internalized) == NULL)
+               goto error;         
+       }
+
+#else /* XSLT_REFACTORED */
+
+        if (IS_XSLT_ELEM(cur)) {
+            /*
+             * This is an XSLT node
+             */
+            xsltStylePreCompPtr info = (xsltStylePreCompPtr) cur->psvi;
+
+            if (info == NULL) {
+                if (IS_XSLT_NAME(cur, "message")) {
+                    xsltMessage(ctxt, contextNode, cur);
+                } else {                   
+                    /*
+                     * That's an error try to apply one of the fallback cases
+                     */
+                    ctxt->insert = insert;
+                    if (!xsltApplyFallbacks(ctxt, contextNode, cur)) {
+                        xsltGenericError(xsltGenericErrorContext,
+                           "xsltApplySequenceConstructor: %s was not compiled\n",
+                           cur->name);
+                    }
+                    ctxt->insert = oldInsert;
+                }
+                goto skip_children;
+            }      
+
+            if (info->func != NULL) {
+               oldCurInst = ctxt->inst;
+               ctxt->inst = cur;
+                ctxt->insert = insert;
+
+                info->func(ctxt, contextNode, cur, (xsltElemPreCompPtr) info);
+
+               /*
+               * Cleanup temporary tree fragments.
+               */
+               if (oldLocalFragmentTop != ctxt->localRVT)
+                   xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
+
+                ctxt->insert = oldInsert;
+               ctxt->inst = oldCurInst;
+                goto skip_children;
+            }
+
+            if (IS_XSLT_NAME(cur, "variable")) {
+               xsltStackElemPtr tmpvar = ctxt->vars;
+               
+               oldCurInst = ctxt->inst;
+               ctxt->inst = cur;
+
+               xsltParseStylesheetVariable(ctxt, cur);
+
+               ctxt->inst = oldCurInst;
+               
+               if (tmpvar != ctxt->vars) {
+                   /*
+                   * TODO: Using a @tmpvar is an annoying workaround, but
+                   *  the current mechanisms do not provide any other way
+                   *  of knowing if the var was really pushed onto the
+                   *  stack.
+                   */
+                   ctxt->vars->level = level;
+               }
+            } else if (IS_XSLT_NAME(cur, "message")) {
+                xsltMessage(ctxt, contextNode, cur);
+            } else {
+               xsltTransformError(ctxt, NULL, cur,
+                   "Unexpected XSLT element '%s'.\n", cur->name);
+            }
+            goto skip_children;
+        } else if ((cur->type == XML_TEXT_NODE) ||
+                   (cur->type == XML_CDATA_SECTION_NODE)) {
+
+            /*
+             * This text comes from the stylesheet
+             * For stylesheets, the set of whitespace-preserving
+             * element names consists of just xsl:text.
+             */
+#ifdef WITH_XSLT_DEBUG_PROCESS
+            if (cur->type == XML_CDATA_SECTION_NODE) {
+                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
+                                 "xsltApplySequenceConstructor: copy CDATA text %s\n",
+                                 cur->content));
+            } else if (cur->name == xmlStringTextNoenc) {
+                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
+                                 "xsltApplySequenceConstructor: copy unescaped text %s\n",
+                                 cur->content));
+            } else {
+                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
+                                 "xsltApplySequenceConstructor: copy text %s\n",
+                                 cur->content));
+            }
+#endif
+            if (xsltCopyText(ctxt, insert, cur, ctxt->internalized) == NULL)
+               goto error;
+        } else if ((cur->type == XML_ELEMENT_NODE) &&
+                   (cur->ns != NULL) && (cur->psvi != NULL)) {
+            xsltTransformFunction function;
+
+           oldCurInst = ctxt->inst;
+           ctxt->inst = cur;
+            /*
+             * Flagged as an extension element
+             */
+            if (cur->psvi == xsltExtMarker)
+                function = (xsltTransformFunction)
+                    xsltExtElementLookup(ctxt, cur->name, cur->ns->href);
+            else
+                function = ((xsltElemPreCompPtr) cur->psvi)->func;
+
+            if (function == NULL) {
+                xmlNodePtr child;
+                int found = 0;
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltApplySequenceConstructor: unknown extension %s\n",
+                    cur->name));
+#endif
+                /*
+                 * Search if there are fallbacks
+                 */
+                child = cur->children;
+                while (child != NULL) {
+                    if ((IS_XSLT_ELEM(child)) &&
+                        (IS_XSLT_NAME(child, "fallback")))
+                   {
+                        found = 1;
+                        xsltApplySequenceConstructor(ctxt, contextNode,
+                           child->children, NULL);
+                    }
+                    child = child->next;
+                }
+
+                if (!found) {
+                    xsltTransformError(ctxt, NULL, cur,
+                       "xsltApplySequenceConstructor: failed to find extension %s\n",
+                       cur->name);
+                }
+            } else {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltApplySequenceConstructor: extension construct %s\n",
+                    cur->name));
+#endif
+
+                ctxt->insert = insert;
+               /*
+               * We need the fragment base for extension instructions
+               * which return values (like EXSLT's function).
+               */
+               oldLocalFragmentBase = ctxt->localRVTBase;
+               ctxt->localRVTBase = NULL;
+
+                function(ctxt, contextNode, cur, cur->psvi);
+               /*
+               * Cleanup temporary tree fragments.
+               */
+               if (oldLocalFragmentTop != ctxt->localRVT)
+                   xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
+
+               ctxt->localRVTBase = oldLocalFragmentBase;
+                ctxt->insert = oldInsert;
+
+            }
+           ctxt->inst = oldCurInst;
+            goto skip_children;
+        } else if (cur->type == XML_ELEMENT_NODE) {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+            XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
+               "xsltApplySequenceConstructor: copy node %s\n",
+                cur->name));
+#endif
+           oldCurInst = ctxt->inst;
+           ctxt->inst = cur;
+
+            if ((copy = xsltShallowCopyElem(ctxt, cur, insert, 1)) == NULL)
+               goto error;            
+            /*
+             * Add extra namespaces inherited from the current template
+             * if we are in the first level children and this is a
+            * "real" template.      
+             */
+            if ((templ != NULL) && (oldInsert == insert) &&
+                (ctxt->templ != NULL) && (ctxt->templ->inheritedNs != NULL)) {
+                int i;
+                xmlNsPtr ns, ret;
+
+                for (i = 0; i < ctxt->templ->inheritedNsNr; i++) {
+                   const xmlChar *URI = NULL;
+                   xsltStylesheetPtr style;
+                    ns = ctxt->templ->inheritedNs[i];              
+                   
+                   /* Note that the XSLT namespace was already excluded
+                   * in xsltGetInheritedNsList().
+                   */
+#if 0
+                   if (xmlStrEqual(ns->href, XSLT_NAMESPACE))
+                       continue;
+#endif
+                   style = ctxt->style;
+                   while (style != NULL) {
+                       if (style->nsAliases != NULL)
+                           URI = (const xmlChar *) 
+                               xmlHashLookup(style->nsAliases, ns->href);
+                       if (URI != NULL)
+                           break;
+                       
+                       style = xsltNextImport(style);
+                   }
+                   if (URI == UNDEFINED_DEFAULT_NS)
+                       continue;
+                   if (URI == NULL)
+                       URI = ns->href;
+                   /*
+                   * TODO: The following will still be buggy for the
+                   * non-refactored code.
+                   */
+                   ret = xmlSearchNs(copy->doc, copy, ns->prefix);
+                   if ((ret == NULL) || (!xmlStrEqual(ret->href, URI)))
+                   {
+                       xmlNewNs(copy, URI, ns->prefix);
+                   }
+                }
+               if (copy->ns != NULL) {
+                   /*
+                    * Fix the node namespace if needed
+                    */
+                   copy->ns = xsltGetNamespace(ctxt, cur, copy->ns, copy);
+               }
+            }
+           /*
+             * all the attributes are directly inherited
+             */
+            if (cur->properties != NULL) {
+                xsltAttrListTemplateProcess(ctxt, copy, cur->properties);
+            }
+           ctxt->inst = oldCurInst;
+        }
+#endif /* else of XSLT_REFACTORED */
+
+        /*
+         * Descend into content in document order.
+         */
+        if (cur->children != NULL) {
+            if (cur->children->type != XML_ENTITY_DECL) {
+                cur = cur->children;
+               level++;
+                if (copy != NULL)
+                    insert = copy;
+                continue;
+            }
+        }
+
+skip_children:
+       /*
+       * If xslt:message was just processed, we might have hit a
+       * terminate='yes'; if so, then break the loop and clean up.
+       * TODO: Do we need to check this also before trying to descend
+       *  into the content?
+       */
+       if (ctxt->state == XSLT_STATE_STOPPED)
+           break;
+        if (cur->next != NULL) {
+            cur = cur->next;
+            continue;
+        }
+
+        do {
+            cur = cur->parent;
+           level--;
+           /*
+           * Pop variables/params (xsl:variable and xsl:param).
+           */
+           if ((ctxt->varsNr > oldVarsNr) && (ctxt->vars->level > level)) {
+               xsltLocalVariablePop(ctxt, oldVarsNr, level);           
+           }
+
+            insert = insert->parent;
+            if (cur == NULL)
+                break;
+            if (cur == list->parent) {
+                cur = NULL;
+                break;
+            }
+            if (cur->next != NULL) {
+                cur = cur->next;
+                break;
+            }
+        } while (cur != NULL);
+    }
+
+error:
+    /*
+    * In case of errors: pop remaining variables.
+    */
+    if (ctxt->varsNr > oldVarsNr)
+       xsltLocalVariablePop(ctxt, oldVarsNr, -1);     
+
+    ctxt->node = oldContextNode;
+    ctxt->inst = oldInst;
+    ctxt->insert = oldInsert;
+    
+#ifdef WITH_DEBUGGER
+    if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (addCallResult)) {
+        xslDropCall();
+    }
+#endif
+}
+
+/*
+* xsltApplyXSLTTemplate:
+* @ctxt:  a XSLT transformation context
+* @contextNode:  the node in the source tree.
+* @list:  the nodes of a sequence constructor;
+*         (plus leading xsl:param elements)
+* @templ: the compiled xsl:template declaration;
+*         NULL if a sequence constructor
+* @withParams:  a set of caller-parameters (xsl:with-param) or NULL
+*
+* Called by:
+* - xsltApplyImports()
+* - xsltCallTemplate()
+* - xsltDefaultProcessOneNode()
+* - xsltProcessOneNode()
+*/
+static void
+xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt,
+                     xmlNodePtr contextNode,
+                     xmlNodePtr list,
+                     xsltTemplatePtr templ,
+                     xsltStackElemPtr withParams)
+{
+    int oldVarsBase = 0;
+    long start = 0;
+    xmlNodePtr cur;
+    xsltStackElemPtr tmpParam = NULL;
+    xmlDocPtr oldUserFragmentTop, oldLocalFragmentTop;
+
+#ifdef XSLT_REFACTORED
+    xsltStyleItemParamPtr iparam;
+#else
+    xsltStylePreCompPtr iparam;
+#endif
+
+#ifdef WITH_DEBUGGER
+    int addCallResult = 0;
+#endif 
+
+    if (ctxt == NULL)
+       return;    
+    if (templ == NULL) {
+       xsltTransformError(ctxt, NULL, list,
+           "xsltApplyXSLTTemplate: Bad arguments; @templ is mandatory.\n");
+       return;
+    }
+
+#ifdef WITH_DEBUGGER
+    if (ctxt->debugStatus != XSLT_DEBUG_NONE) {
+       if (xsltDebuggerStartSequenceConstructor(ctxt, contextNode,
+               list, templ, &addCallResult) == NULL)
+           return;
+    }
+#endif
+
+    if (list == NULL)
+        return;
+    CHECK_STOPPED;
+
+    /*
+    * Check for infinite recursion: stop if the maximum of nested templates
+    * is excceeded. Adjust xsltMaxDepth if you need more.
+    */
+    if (((ctxt->templNr >= xsltMaxDepth) ||
+        (ctxt->varsNr >= 5 * xsltMaxDepth)))
+    {
+        xsltTransformError(ctxt, NULL, list,
+           "xsltApplyXSLTTemplate: A potential infinite template recursion "
+           "was detected.\n"
+           "You can adjust xsltMaxDepth (--maxdepth) in order to "
+           "raise the maximum number of nested template calls and "
+           "variables/params (currently set to %d).\n",
+           xsltMaxDepth);
+        xsltDebug(ctxt, contextNode, list, NULL);
+        return;
+    }
+    
+    oldUserFragmentTop = ctxt->tmpRVT;
+    ctxt->tmpRVT = NULL;
+    oldLocalFragmentTop = ctxt->localRVT;
+       
+    /*
+    * Initiate a distinct scope of local params/variables.
+    */
+    oldVarsBase = ctxt->varsBase;
+    ctxt->varsBase = ctxt->varsNr;
+    
+    ctxt->node = contextNode;
+    if (ctxt->profile) {
+       templ->nbCalls++;
+       start = xsltTimestamp();
+       profPush(ctxt, 0);
+    }
+    /*
+    * Push the xsl:template declaration onto the stack.
+    */
+    templPush(ctxt, templ);
+    
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    if (templ->name != NULL)
+       XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
+       "applying xsl:template '%s'\n", templ->name));
+#endif
+    /*
+    * Process xsl:param instructions and skip those elements for
+    * further processing.
+    */
+    cur = list;
+    do {
+       if (cur->type == XML_TEXT_NODE) {
+           cur = cur->next;
+           continue;
+       }
+       if ((cur->type != XML_ELEMENT_NODE) ||
+           (cur->name[0] != 'p') ||
+           (cur->psvi == NULL) ||
+           (! xmlStrEqual(cur->name, BAD_CAST "param")) ||
+           (! IS_XSLT_ELEM(cur)))
+       {
+           break;
+       }
+
+       list = cur->next;
+
+#ifdef XSLT_REFACTORED
+       iparam = (xsltStyleItemParamPtr) cur->psvi;
+#else
+       iparam = (xsltStylePreCompPtr) cur->psvi;
+#endif
+       
+       /*
+       * Substitute xsl:param for a given xsl:with-param.
+       * Since the XPath expression will reference the params/vars
+       * by index, we need to slot the xsl:with-params in the
+       * order of encountered xsl:params to keep the sequence of
+       * params/variables in the stack exactly as it was at
+       * compile time,
+       */
+       tmpParam = NULL;
+       if (withParams) {
+           tmpParam = withParams;
+           do {
+               if ((tmpParam->name == (iparam->name)) &&
+                   (tmpParam->nameURI == (iparam->ns)))
+               {
+                   /*
+                   * Push the caller-parameter.
+                   */              
+                   xsltLocalVariablePush(ctxt, tmpParam, -1);
+                   break;
+               }
+               tmpParam = tmpParam->next;
+           } while (tmpParam != NULL);
+       }
+       /*
+       * Push the xsl:param.
+       */
+       if (tmpParam == NULL) {
+           /*
+           * Note that we must assume that the added parameter
+           * has a @depth of 0.
+           */
+           xsltParseStylesheetParam(ctxt, cur);
+       }
+       cur = cur->next;
+    } while (cur != NULL);    
+    /*
+    * Process the sequence constructor.
+    */
+    xsltApplySequenceConstructor(ctxt, contextNode, list, templ);
+    
+    /*
+    * Remove remaining xsl:param and xsl:with-param items from
+    * the stack. Don't free xsl:with-param items.
+    */
+    if (ctxt->varsNr > ctxt->varsBase)
+       xsltTemplateParamsCleanup(ctxt);    
+    ctxt->varsBase = oldVarsBase;
+    
+    /*
+    * Clean up remaining local tree fragments.
+    * This also frees fragments which are the result of
+    * extension instructions. Should normally not be hit; but
+    * just for the case xsltExtensionInstructionResultFinalize()
+    * was not called by the extension author.
+    */
+    if (oldLocalFragmentTop != ctxt->localRVT) {
+       xmlDocPtr cur = ctxt->localRVT, tmp;
+
+       do {
+           tmp = cur;
+           cur = (xmlDocPtr) cur->next;
+           xsltReleaseRVT(ctxt, tmp);
+       } while (cur != oldLocalFragmentTop);
+    }
+    ctxt->localRVT = oldLocalFragmentTop;
+
+    /*
+    * Release user-created fragments stored in the scope
+    * of xsl:template. Note that this mechanism is deprecated:
+    * user code should now use xsltRegisterLocalRVT() instead
+    * of the obsolete xsltRegisterTmpRVT().    
+    */
+    if (ctxt->tmpRVT) {
+       xmlDocPtr cur = ctxt->tmpRVT, tmp;
+
+       while (cur != NULL) {
+           tmp = cur;
+           cur = (xmlDocPtr) cur->next;
+           xsltReleaseRVT(ctxt, tmp);
+       }       
+    }
+    ctxt->tmpRVT = oldUserFragmentTop;    
+    
+    /*
+    * Pop the xsl:template declaration from the stack.
+    */
+    templPop(ctxt);    
+    if (ctxt->profile) {
+       long spent, child, total, end;
+       
+       end = xsltTimestamp();
+       child = profPop(ctxt);
+       total = end - start;
+       spent = total - child;
+       if (spent <= 0) {
+           /*
+           * Not possible unless the original calibration failed
+           * we can try to correct it on the fly.
+           */
+           xsltCalibrateAdjust(spent);
+           spent = 0;
+       }
+       
+       templ->time += spent;
+       if (ctxt->profNr > 0)
+           ctxt->profTab[ctxt->profNr - 1] += total;
+    }
+    
+#ifdef WITH_DEBUGGER
+    if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (addCallResult)) {
+        xslDropCall();
+    }
+#endif
+}
+
+
+/**
+ * xsltApplyOneTemplate:
+ * @ctxt:  a XSLT process context
+ * @contextNode:  the node in the source tree.
+ * @list:  the nodes of a sequence constructor
+ * @templ: not used
+ * @params:  a set of parameters (xsl:param) or NULL
+ *
+ * Processes a sequence constructor on the current node in the source tree.
+ *
+ * @params are the already computed variable stack items; this function
+ * pushes them on the variable stack, and pops them before exiting; it's
+ * left to the caller to free or reuse @params afterwards. The initial
+ * states of the variable stack will always be restored before this
+ * function exits.
+ * NOTE that this does *not* initiate a new distinct variable scope; i.e.
+ * variables already on the stack are visible to the process. The caller's
+ * side needs to start a new variable scope if needed (e.g. in exsl:function).
+ *
+ * @templ is obsolete and not used anymore (e.g. <exslt:function> does not
+ * provide a @templ); a non-NULL @templ might raise an error in the future.
+ *
+ * BIG NOTE: This function is not intended to process the content of an
+ * xsl:template; it does not expect xsl:param instructions in @list and
+ * will report errors if found.
+ *
+ * Called by:
+ *  - xsltEvalVariable() (variables.c)
+ *  - exsltFuncFunctionFunction() (libexsl/functions.c)
+ */
+void
+xsltApplyOneTemplate(xsltTransformContextPtr ctxt,
+                    xmlNodePtr contextNode,
+                     xmlNodePtr list,
+                    xsltTemplatePtr templ ATTRIBUTE_UNUSED,
+                     xsltStackElemPtr params)
+{
+    if ((ctxt == NULL) || (list == NULL))
+       return;
+    CHECK_STOPPED;
+
+    if (params) {
+       int oldVarsNr = ctxt->varsNr;
+
+       /*
+       * Push the given xsl:param(s) onto the variable stack.
+       */
+       while (params != NULL) {
+           xsltLocalVariablePush(ctxt, params, -1);
+           params = params->next;
+       }
+       xsltApplySequenceConstructor(ctxt, contextNode, list, templ);
+       /*
+       * Pop the given xsl:param(s) from the stack but don't free them.
+       */
+       xsltLocalVariablePop(ctxt, oldVarsNr, -2);
+    } else
+       xsltApplySequenceConstructor(ctxt, contextNode, list, templ);    
+}
+
+/************************************************************************
+ *                                                                     *
+ *                 XSLT-1.1 extensions                                 *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltDocumentElem:
+ * @ctxt:  an XSLT processing context
+ * @node:  The current node
+ * @inst:  the instruction in the stylesheet
+ * @comp:  precomputed information
+ *
+ * Process an EXSLT/XSLT-1.1 document element
+ */
+void
+xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                 xmlNodePtr inst, xsltStylePreCompPtr castedComp)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemDocumentPtr comp = (xsltStyleItemDocumentPtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif
+    xsltStylesheetPtr style = NULL;
+    int ret;
+    xmlChar *filename = NULL, *prop, *elements;
+    xmlChar *element, *end;
+    xmlDocPtr res = NULL;
+    xmlDocPtr oldOutput;
+    xmlNodePtr oldInsert, root;
+    const char *oldOutputFile;
+    xsltOutputType oldType;
+    xmlChar *URL = NULL;
+    const xmlChar *method;
+    const xmlChar *doctypePublic;
+    const xmlChar *doctypeSystem;
+    const xmlChar *version;
+
+    if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL))
+        return;
+
+    if (comp->filename == NULL) {
+
+        if (xmlStrEqual(inst->name, (const xmlChar *) "output")) {
+           /*
+           * The element "output" is in the namespace XSLT_SAXON_NAMESPACE
+           *   (http://icl.com/saxon)
+           * The @file is in no namespace.
+           */
+#ifdef WITH_XSLT_DEBUG_EXTRA
+            xsltGenericDebug(xsltGenericDebugContext,
+                             "Found saxon:output extension\n");
+#endif
+            URL = xsltEvalAttrValueTemplate(ctxt, inst,
+                                                 (const xmlChar *) "file",
+                                                 XSLT_SAXON_NAMESPACE);
+            
+           if (URL == NULL)
+               URL = xsltEvalAttrValueTemplate(ctxt, inst,
+                                                 (const xmlChar *) "href",
+                                                 XSLT_SAXON_NAMESPACE);
+        } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) {
+#ifdef WITH_XSLT_DEBUG_EXTRA
+            xsltGenericDebug(xsltGenericDebugContext,
+                             "Found xalan:write extension\n");
+#endif
+            URL = xsltEvalAttrValueTemplate(ctxt, inst,
+                                                 (const xmlChar *)
+                                                 "select",
+                                                 XSLT_XALAN_NAMESPACE);
+           if (URL != NULL) {
+               xmlXPathCompExprPtr cmp;
+               xmlChar *val;
+
+               /*
+                * Trying to handle bug #59212
+                * The value of the "select" attribute is an
+                * XPath expression.
+                * (see http://xml.apache.org/xalan-j/extensionslib.html#redirect) 
+                */
+               cmp = xmlXPathCompile(URL);
+                val = xsltEvalXPathString(ctxt, cmp);
+               xmlXPathFreeCompExpr(cmp);
+               xmlFree(URL);
+               URL = val;
+           }
+           if (URL == NULL)
+               URL = xsltEvalAttrValueTemplate(ctxt, inst,
+                                                    (const xmlChar *)
+                                                    "file",
+                                                    XSLT_XALAN_NAMESPACE);
+           if (URL == NULL)
+               URL = xsltEvalAttrValueTemplate(ctxt, inst,
+                                                    (const xmlChar *)
+                                                    "href",
+                                                    XSLT_XALAN_NAMESPACE);
+        } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) {
+            URL = xsltEvalAttrValueTemplate(ctxt, inst,
+                                                 (const xmlChar *) "href",
+                                                 NULL);
+        }
+
+    } else {
+        URL = xmlStrdup(comp->filename);
+    }
+
+    if (URL == NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+                        "xsltDocumentElem: href/URI-Reference not found\n");
+       return;
+    }
+
+    /*
+     * If the computation failed, it's likely that the URL wasn't escaped
+     */
+    filename = xmlBuildURI(URL, (const xmlChar *) ctxt->outputFile);
+    if (filename == NULL) {
+       xmlChar *escURL;
+
+       escURL=xmlURIEscapeStr(URL, BAD_CAST ":/.?,");
+       if (escURL != NULL) {
+           filename = xmlBuildURI(escURL, (const xmlChar *) ctxt->outputFile);
+           xmlFree(escURL);
+       }
+    }
+
+    if (filename == NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+                        "xsltDocumentElem: URL computation failed for %s\n",
+                        URL);
+       xmlFree(URL);
+       return;
+    }
+
+    /*
+     * Security checking: can we write to this resource
+     */
+    if (ctxt->sec != NULL) {
+       ret = xsltCheckWrite(ctxt->sec, ctxt, filename);
+       if (ret == 0) {
+           xsltTransformError(ctxt, NULL, inst,
+                "xsltDocumentElem: write rights for %s denied\n",
+                            filename);
+           xmlFree(URL);
+           xmlFree(filename);
+           return;
+       }
+    }
+
+    oldOutputFile = ctxt->outputFile;
+    oldOutput = ctxt->output;
+    oldInsert = ctxt->insert;
+    oldType = ctxt->type;
+    ctxt->outputFile = (const char *) filename;
+
+    style = xsltNewStylesheet();
+    if (style == NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+                         "xsltDocumentElem: out of memory\n");
+        goto error;
+    }
+
+    /*
+     * Version described in 1.1 draft allows full parameterization
+     * of the output.
+     */
+    prop = xsltEvalAttrValueTemplate(ctxt, inst,
+                                    (const xmlChar *) "version",
+                                    NULL);
+    if (prop != NULL) {
+       if (style->version != NULL)
+           xmlFree(style->version);
+       style->version = prop;
+    }
+    prop = xsltEvalAttrValueTemplate(ctxt, inst,
+                                    (const xmlChar *) "encoding",
+                                    NULL);
+    if (prop != NULL) {
+       if (style->encoding != NULL)
+           xmlFree(style->encoding);
+       style->encoding = prop;
+    }
+    prop = xsltEvalAttrValueTemplate(ctxt, inst,
+                                    (const xmlChar *) "method",
+                                    NULL);
+    if (prop != NULL) {
+       const xmlChar *URI;
+
+       if (style->method != NULL)
+           xmlFree(style->method);
+       style->method = NULL;
+       if (style->methodURI != NULL)
+           xmlFree(style->methodURI);
+       style->methodURI = NULL;
+
+       URI = xsltGetQNameURI(inst, &prop);
+       if (prop == NULL) {
+           if (style != NULL) style->errors++;
+       } else if (URI == NULL) {
+           if ((xmlStrEqual(prop, (const xmlChar *) "xml")) ||
+               (xmlStrEqual(prop, (const xmlChar *) "html")) ||
+               (xmlStrEqual(prop, (const xmlChar *) "text"))) {
+               style->method = prop;
+           } else {
+               xsltTransformError(ctxt, NULL, inst,
+                                "invalid value for method: %s\n", prop);
+               if (style != NULL) style->warnings++;
+           }
+       } else {
+           style->method = prop;
+           style->methodURI = xmlStrdup(URI);
+       }
+    }
+    prop = xsltEvalAttrValueTemplate(ctxt, inst,
+                                    (const xmlChar *)
+                                    "doctype-system", NULL);
+    if (prop != NULL) {
+       if (style->doctypeSystem != NULL)
+           xmlFree(style->doctypeSystem);
+       style->doctypeSystem = prop;
+    }
+    prop = xsltEvalAttrValueTemplate(ctxt, inst,
+                                    (const xmlChar *)
+                                    "doctype-public", NULL);
+    if (prop != NULL) {
+       if (style->doctypePublic != NULL)
+           xmlFree(style->doctypePublic);
+       style->doctypePublic = prop;
+    }
+    prop = xsltEvalAttrValueTemplate(ctxt, inst,
+                                    (const xmlChar *) "standalone",
+                                    NULL);
+    if (prop != NULL) {
+       if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
+           style->standalone = 1;
+       } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
+           style->standalone = 0;
+       } else {
+           xsltTransformError(ctxt, NULL, inst,
+                            "invalid value for standalone: %s\n",
+                            prop);
+           if (style != NULL) style->warnings++;
+       }
+       xmlFree(prop);
+    }
+
+    prop = xsltEvalAttrValueTemplate(ctxt, inst,
+                                    (const xmlChar *) "indent",
+                                    NULL);
+    if (prop != NULL) {
+       if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
+           style->indent = 1;
+       } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
+           style->indent = 0;
+       } else {
+           xsltTransformError(ctxt, NULL, inst,
+                            "invalid value for indent: %s\n", prop);
+           if (style != NULL) style->warnings++;
+       }
+       xmlFree(prop);
+    }
+
+    prop = xsltEvalAttrValueTemplate(ctxt, inst,
+                                    (const xmlChar *)
+                                    "omit-xml-declaration",
+                                    NULL);
+    if (prop != NULL) {
+       if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
+           style->omitXmlDeclaration = 1;
+       } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
+           style->omitXmlDeclaration = 0;
+       } else {
+           xsltTransformError(ctxt, NULL, inst,
+                            "invalid value for omit-xml-declaration: %s\n",
+                            prop);
+           if (style != NULL) style->warnings++;
+       }
+       xmlFree(prop);
+    }
+
+    elements = xsltEvalAttrValueTemplate(ctxt, inst,
+                                        (const xmlChar *)
+                                        "cdata-section-elements",
+                                        NULL);
+    if (elements != NULL) {
+       if (style->stripSpaces == NULL)
+           style->stripSpaces = xmlHashCreate(10);
+       if (style->stripSpaces == NULL)
+           return;
+
+       element = elements;
+       while (*element != 0) {
+           while (IS_BLANK_CH(*element))
+               element++;
+           if (*element == 0)
+               break;
+           end = element;
+           while ((*end != 0) && (!IS_BLANK_CH(*end)))
+               end++;
+           element = xmlStrndup(element, end - element);
+           if (element) {
+               const xmlChar *URI;
+
+#ifdef WITH_XSLT_DEBUG_PARSING
+               xsltGenericDebug(xsltGenericDebugContext,
+                                "add cdata section output element %s\n",
+                                element);
+#endif
+                URI = xsltGetQNameURI(inst, &element);
+
+               xmlHashAddEntry2(style->stripSpaces, element, URI,
+                               (xmlChar *) "cdata");
+               xmlFree(element);
+           }
+           element = end;
+       }
+       xmlFree(elements);
+    }
+
+    /*
+     * Create a new document tree and process the element template
+     */
+    XSLT_GET_IMPORT_PTR(method, style, method)
+    XSLT_GET_IMPORT_PTR(doctypePublic, style, doctypePublic)
+    XSLT_GET_IMPORT_PTR(doctypeSystem, style, doctypeSystem)
+    XSLT_GET_IMPORT_PTR(version, style, version)
+
+    if ((method != NULL) &&
+       (!xmlStrEqual(method, (const xmlChar *) "xml"))) {
+       if (xmlStrEqual(method, (const xmlChar *) "html")) {
+           ctxt->type = XSLT_OUTPUT_HTML;
+           if (((doctypePublic != NULL) || (doctypeSystem != NULL)))
+               res = htmlNewDoc(doctypeSystem, doctypePublic);
+           else {
+               if (version != NULL) {
+#ifdef XSLT_GENERATE_HTML_DOCTYPE
+                   xsltGetHTMLIDs(version, &doctypePublic, &doctypeSystem);
+#endif
+                }
+               res = htmlNewDocNoDtD(doctypeSystem, doctypePublic);
+           }
+           if (res == NULL)
+               goto error;
+           res->dict = ctxt->dict;
+           xmlDictReference(res->dict);
+       } else if (xmlStrEqual(method, (const xmlChar *) "xhtml")) {
+           xsltTransformError(ctxt, NULL, inst,
+            "xsltDocumentElem: unsupported method xhtml\n",
+                            style->method);
+           ctxt->type = XSLT_OUTPUT_HTML;
+           res = htmlNewDocNoDtD(doctypeSystem, doctypePublic);
+           if (res == NULL)
+               goto error;
+           res->dict = ctxt->dict;
+           xmlDictReference(res->dict);
+       } else if (xmlStrEqual(method, (const xmlChar *) "text")) {
+           ctxt->type = XSLT_OUTPUT_TEXT;
+           res = xmlNewDoc(style->version);
+           if (res == NULL)
+               goto error;
+           res->dict = ctxt->dict;
+           xmlDictReference(res->dict);
+#ifdef WITH_XSLT_DEBUG
+           xsltGenericDebug(xsltGenericDebugContext,
+                     "reusing transformation dict for output\n");
+#endif
+       } else {
+           xsltTransformError(ctxt, NULL, inst,
+                            "xsltDocumentElem: unsupported method %s\n",
+                            style->method);
+           goto error;
+       }
+    } else {
+       ctxt->type = XSLT_OUTPUT_XML;
+       res = xmlNewDoc(style->version);
+       if (res == NULL)
+           goto error;
+       res->dict = ctxt->dict;
+       xmlDictReference(res->dict);
+#ifdef WITH_XSLT_DEBUG
+       xsltGenericDebug(xsltGenericDebugContext,
+                     "reusing transformation dict for output\n");
+#endif
+    }
+    res->charset = XML_CHAR_ENCODING_UTF8;
+    if (style->encoding != NULL)
+       res->encoding = xmlStrdup(style->encoding);
+    ctxt->output = res;
+    ctxt->insert = (xmlNodePtr) res;
+    xsltApplySequenceConstructor(ctxt, node, inst->children, NULL);
+
+    /*
+     * Do some post processing work depending on the generated output
+     */
+    root = xmlDocGetRootElement(res);
+    if (root != NULL) {
+        const xmlChar *doctype = NULL;
+
+        if ((root->ns != NULL) && (root->ns->prefix != NULL))
+           doctype = xmlDictQLookup(ctxt->dict, root->ns->prefix, root->name);
+       if (doctype == NULL)
+           doctype = root->name;
+
+        /*
+         * Apply the default selection of the method
+         */
+        if ((method == NULL) &&
+            (root->ns == NULL) &&
+            (!xmlStrcasecmp(root->name, (const xmlChar *) "html"))) {
+            xmlNodePtr tmp;
+
+            tmp = res->children;
+            while ((tmp != NULL) && (tmp != root)) {
+                if (tmp->type == XML_ELEMENT_NODE)
+                    break;
+                if ((tmp->type == XML_TEXT_NODE) && (!xmlIsBlankNode(tmp)))
+                    break;
+               tmp = tmp->next;
+            }
+            if (tmp == root) {
+                ctxt->type = XSLT_OUTPUT_HTML;
+                res->type = XML_HTML_DOCUMENT_NODE;
+                if (((doctypePublic != NULL) || (doctypeSystem != NULL))) {
+                    res->intSubset = xmlCreateIntSubset(res, doctype,
+                                                        doctypePublic,
+                                                        doctypeSystem);
+#ifdef XSLT_GENERATE_HTML_DOCTYPE
+               } else if (version != NULL) {
+                    xsltGetHTMLIDs(version, &doctypePublic,
+                                   &doctypeSystem);
+                    if (((doctypePublic != NULL) || (doctypeSystem != NULL)))
+                        res->intSubset =
+                            xmlCreateIntSubset(res, doctype,
+                                               doctypePublic,
+                                               doctypeSystem);
+#endif
+                }
+            }
+
+        }
+        if (ctxt->type == XSLT_OUTPUT_XML) {
+            XSLT_GET_IMPORT_PTR(doctypePublic, style, doctypePublic)
+                XSLT_GET_IMPORT_PTR(doctypeSystem, style, doctypeSystem)
+                if (((doctypePublic != NULL) || (doctypeSystem != NULL)))
+                res->intSubset = xmlCreateIntSubset(res, doctype,
+                                                    doctypePublic,
+                                                    doctypeSystem);
+        }
+    }
+
+    /*
+     * Save the result
+     */
+    ret = xsltSaveResultToFilename((const char *) filename,
+                                   res, style, 0);
+    if (ret < 0) {
+       xsltTransformError(ctxt, NULL, inst,
+                         "xsltDocumentElem: unable to save to %s\n",
+                         filename);
+       ctxt->state = XSLT_STATE_ERROR;
+#ifdef WITH_XSLT_DEBUG_EXTRA
+    } else {
+        xsltGenericDebug(xsltGenericDebugContext,
+                         "Wrote %d bytes to %s\n", ret, filename);
+#endif
+    }
+
+  error:
+    ctxt->output = oldOutput;
+    ctxt->insert = oldInsert;
+    ctxt->type = oldType;
+    ctxt->outputFile = oldOutputFile;
+    if (URL != NULL)
+        xmlFree(URL);
+    if (filename != NULL)
+        xmlFree(filename);
+    if (style != NULL)
+        xsltFreeStylesheet(style);
+    if (res != NULL)
+        xmlFreeDoc(res);
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Most of the XSLT-1.0 transformations                    *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltSort:
+ * @ctxt:  a XSLT process context
+ * @node:  the node in the source tree.
+ * @inst:  the xslt sort node
+ * @comp:  precomputed information
+ *
+ * function attached to xsl:sort nodes, but this should not be
+ * called directly
+ */
+void
+xsltSort(xsltTransformContextPtr ctxt,
+       xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst,
+       xsltStylePreCompPtr comp) {
+    if (comp == NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+            "xsl:sort : compilation failed\n");
+       return;
+    }
+    xsltTransformError(ctxt, NULL, inst,
+        "xsl:sort : improper use this should not be reached\n");
+}
+
+/**
+ * xsltCopy:
+ * @ctxt:  an XSLT process context
+ * @node:  the node in the source tree
+ * @inst:  the element node of the XSLT-copy instruction
+ * @comp:  computed information of the XSLT-copy instruction
+ *
+ * Execute the XSLT-copy instruction on the source node.
+ */
+void
+xsltCopy(xsltTransformContextPtr ctxt, xmlNodePtr node,
+        xmlNodePtr inst, xsltStylePreCompPtr castedComp)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemCopyPtr comp = (xsltStyleItemCopyPtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif
+    xmlNodePtr copy, oldInsert;
+   
+    oldInsert = ctxt->insert;
+    if (ctxt->insert != NULL) {
+       switch (node->type) {
+           case XML_TEXT_NODE:
+           case XML_CDATA_SECTION_NODE:
+               /*
+                * This text comes from the stylesheet
+                * For stylesheets, the set of whitespace-preserving
+                * element names consists of just xsl:text.
+                */
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               if (node->type == XML_CDATA_SECTION_NODE) {
+                   XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,
+                        "xsltCopy: CDATA text %s\n", node->content));
+               } else {
+                   XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,
+                        "xsltCopy: text %s\n", node->content));
+                }
+#endif
+               xsltCopyText(ctxt, ctxt->insert, node, 0);
+               break;
+           case XML_DOCUMENT_NODE:
+           case XML_HTML_DOCUMENT_NODE:
+               break;
+           case XML_ELEMENT_NODE:
+               /*
+               * REVISIT NOTE: The "fake" is a doc-node, not an element node.
+               * REMOVED:
+               *   if (xmlStrEqual(node->name, BAD_CAST " fake node libxslt"))
+               *    return;
+               */              
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,
+                                "xsltCopy: node %s\n", node->name));
+#endif
+               copy = xsltShallowCopyElem(ctxt, node, ctxt->insert, 0);
+               ctxt->insert = copy;
+               if (comp->use != NULL) {
+                   xsltApplyAttributeSet(ctxt, node, inst, comp->use);
+               }
+               break;
+           case XML_ATTRIBUTE_NODE: {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,
+                                "xsltCopy: attribute %s\n", node->name));
+#endif
+               /*
+               * REVISIT: We could also raise an error if the parent is not
+               * an element node.
+               * OPTIMIZE TODO: Can we set the value/children of the
+               * attribute without an intermediate copy of the string value?
+               */
+               xsltShallowCopyAttr(ctxt, inst, ctxt->insert, (xmlAttrPtr) node);               
+               break;
+           }
+           case XML_PI_NODE:
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,
+                                "xsltCopy: PI %s\n", node->name));
+#endif
+               copy = xmlNewDocPI(ctxt->insert->doc, node->name,
+                                  node->content);
+               xmlAddChild(ctxt->insert, copy);
+               break;
+           case XML_COMMENT_NODE:
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,
+                                "xsltCopy: comment\n"));
+#endif
+               copy = xmlNewComment(node->content);
+               xmlAddChild(ctxt->insert, copy);
+               break;
+           case XML_NAMESPACE_DECL:
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               XSLT_TRACE(ctxt,XSLT_TRACE_COPY,xsltGenericDebug(xsltGenericDebugContext,
+                                "xsltCopy: namespace declaration\n"));
+#endif         
+               xsltShallowCopyNsNode(ctxt, inst, ctxt->insert, (xmlNsPtr)node);                     
+               break;
+           default:
+               break;
+
+       }
+    }
+
+    switch (node->type) {
+       case XML_DOCUMENT_NODE:
+       case XML_HTML_DOCUMENT_NODE:
+       case XML_ELEMENT_NODE:
+           xsltApplySequenceConstructor(ctxt, ctxt->node, inst->children,
+               NULL);
+           break;
+       default:
+           break;
+    }
+    ctxt->insert = oldInsert;
+}
+
+/**
+ * xsltText:
+ * @ctxt:  a XSLT process context
+ * @node:  the node in the source tree.
+ * @inst:  the xslt text node
+ * @comp:  precomputed information
+ *
+ * Process the xslt text node on the source node
+ */
+void
+xsltText(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED,
+           xmlNodePtr inst, xsltStylePreCompPtr comp ATTRIBUTE_UNUSED) {
+    if ((inst->children != NULL) && (comp != NULL)) {
+       xmlNodePtr text = inst->children;
+       xmlNodePtr copy;
+
+       while (text != NULL) {
+           if ((text->type != XML_TEXT_NODE) &&
+                (text->type != XML_CDATA_SECTION_NODE)) {
+               xsltTransformError(ctxt, NULL, inst,
+                                "xsl:text content problem\n");
+               break;
+           }
+           copy = xmlNewDocText(ctxt->output, text->content);
+           if (text->type != XML_CDATA_SECTION_NODE) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+               xsltGenericDebug(xsltGenericDebugContext,
+                    "Disable escaping: %s\n", text->content);
+#endif
+               copy->name = xmlStringTextNoenc;
+           }
+           xmlAddChild(ctxt->insert, copy);
+           text = text->next;
+       }
+    }
+}
+
+/**
+ * xsltElement:
+ * @ctxt:  a XSLT process context
+ * @node:  the node in the source tree.
+ * @inst:  the xslt element node
+ * @comp:  precomputed information
+ *
+ * Process the xslt element node on the source node
+ */
+void
+xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
+           xmlNodePtr inst, xsltStylePreCompPtr castedComp) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemElementPtr comp = (xsltStyleItemElementPtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif
+    xmlChar *prop = NULL;
+    const xmlChar *name, *prefix = NULL, *nsName = NULL;    
+    xmlNodePtr copy;
+    xmlNodePtr oldInsert;
+
+    if (ctxt->insert == NULL)
+       return;
+
+    /* 
+    * A comp->has_name == 0 indicates that we need to skip this instruction,
+    * since it was evaluated to be invalid already during compilation.
+    */
+    if (!comp->has_name)
+        return;
+
+    /*
+     * stack and saves
+     */
+    oldInsert = ctxt->insert;
+
+    if (comp->name == NULL) {
+       /* TODO: fix attr acquisition wrt to the XSLT namespace */
+        prop = xsltEvalAttrValueTemplate(ctxt, inst,
+           (const xmlChar *) "name", XSLT_NAMESPACE);
+        if (prop == NULL) {
+            xsltTransformError(ctxt, NULL, inst,
+               "xsl:element: The attribute 'name' is missing.\n");
+            goto error;
+        }
+       if (xmlValidateQName(prop, 0)) {
+           xsltTransformError(ctxt, NULL, inst,
+               "xsl:element: The effective name '%s' is not a "
+               "valid QName.\n", prop);
+           /* we fall through to catch any further errors, if possible */
+       }
+       name = xsltSplitQName(ctxt->dict, prop, &prefix);
+       xmlFree(prop);
+       if ((prefix != NULL) &&
+           (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)))
+       {
+           /*
+           * TODO: Should we really disallow an "xml" prefix?
+           */
+           goto error;
+       }
+    } else {
+       /*
+       * The "name" value was static.
+       */
+#ifdef XSLT_REFACTORED
+       prefix = comp->nsPrefix;
+       name = comp->name;
+#else  
+       name = xsltSplitQName(ctxt->dict, comp->name, &prefix);
+#endif
+    }
+    
+    /*
+     * Create the new element
+     */
+    if (ctxt->output->dict == ctxt->dict) {
+       copy = xmlNewDocNodeEatName(ctxt->output, NULL, (xmlChar *)name, NULL);
+    } else {
+       copy = xmlNewDocNode(ctxt->output, NULL, (xmlChar *)name, NULL);
+    }
+    if (copy == NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+           "xsl:element : creation of %s failed\n", name);
+       return;
+    }
+    xmlAddChild(ctxt->insert, copy);    
+
+    /*
+    * Namespace
+    * ---------
+    */
+    if (comp->has_ns) {         
+       if (comp->ns != NULL) {
+           /*
+           * No AVT; just plain text for the namespace name.
+           */
+           if (comp->ns[0] != 0)
+               nsName = comp->ns;
+       } else {
+           xmlChar *tmpNsName;
+           /*
+           * Eval the AVT.
+           */
+           /* TODO: check attr acquisition wrt to the XSLT namespace */
+           tmpNsName = xsltEvalAttrValueTemplate(ctxt, inst,
+               (const xmlChar *) "namespace", XSLT_NAMESPACE); 
+           /*
+           * SPEC XSLT 1.0:
+           *  "If the string is empty, then the expanded-name of the
+           *  attribute has a null namespace URI."
+           */
+           if ((tmpNsName != NULL) && (tmpNsName[0] != 0))
+               nsName = xmlDictLookup(ctxt->dict, BAD_CAST tmpNsName, -1);
+           xmlFree(tmpNsName);         
+       };          
+    } else {
+       xmlNsPtr ns;
+       /*
+       * SPEC XSLT 1.0:
+       *  "If the namespace attribute is not present, then the QName is
+       *  expanded into an expanded-name using the namespace declarations
+       *  in effect for the xsl:element element, including any default
+       *  namespace declaration.
+       */      
+       ns = xmlSearchNs(inst->doc, inst, prefix);
+       if (ns == NULL) {
+           /*
+           * TODO: Check this in the compilation layer in case it's a
+           * static value.
+           */
+           if (prefix != NULL) {
+               xsltTransformError(ctxt, NULL, inst,
+                   "xsl:element: The QName '%s:%s' has no "
+                   "namespace binding in scope in the stylesheet; "
+                   "this is an error, since the namespace was not "
+                   "specified by the instruction itself.\n", prefix, name);
+           }
+       } else
+           nsName = ns->href;  
+    }
+    /*
+    * Find/create a matching ns-decl in the result tree.
+    */
+    if (nsName != NULL) {
+       copy->ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix, copy);
+    } else if ((copy->parent != NULL) &&
+       (copy->parent->type == XML_ELEMENT_NODE) &&
+       (copy->parent->ns != NULL))
+    {
+       /*
+       * "Undeclare" the default namespace.
+       */
+       xsltGetSpecialNamespace(ctxt, inst, NULL, NULL, copy);
+    }
+
+    ctxt->insert = copy;
+
+    if (comp->has_use) {
+       if (comp->use != NULL) {
+           xsltApplyAttributeSet(ctxt, node, inst, comp->use);
+       } else {
+           xmlChar *attrSets = NULL;
+           /*
+           * BUG TODO: use-attribute-sets is not a value template.
+           *  use-attribute-sets = qnames
+           */
+           attrSets = xsltEvalAttrValueTemplate(ctxt, inst,
+               (const xmlChar *)"use-attribute-sets", NULL);
+           if (attrSets != NULL) {
+               xsltApplyAttributeSet(ctxt, node, inst, attrSets);
+               xmlFree(attrSets);
+           }
+       }
+    }
+    /*
+    * Instantiate the sequence constructor.
+    */
+    if (inst->children != NULL)
+       xsltApplySequenceConstructor(ctxt, ctxt->node, inst->children,
+           NULL);
+
+error:
+    ctxt->insert = oldInsert;
+    return;    
+}
+
+
+/**
+ * xsltComment:
+ * @ctxt:  a XSLT process context
+ * @node:  the node in the source tree.
+ * @inst:  the xslt comment node
+ * @comp:  precomputed information
+ *
+ * Process the xslt comment node on the source node
+ */
+void
+xsltComment(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                  xmlNodePtr inst, xsltStylePreCompPtr comp ATTRIBUTE_UNUSED) {
+    xmlChar *value = NULL;
+    xmlNodePtr commentNode;
+    int len;
+    
+    value = xsltEvalTemplateString(ctxt, node, inst);
+    /* TODO: use or generate the compiled form */
+    len = xmlStrlen(value);
+    if (len > 0) {
+        if ((value[len-1] == '-') || 
+           (xmlStrstr(value, BAD_CAST "--"))) {
+           xsltTransformError(ctxt, NULL, inst,
+                   "xsl:comment : '--' or ending '-' not allowed in comment\n");
+           /* fall through to try to catch further errors */
+       }
+    }
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    if (value == NULL) {
+       XSLT_TRACE(ctxt,XSLT_TRACE_COMMENT,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltComment: empty\n"));
+    } else {
+       XSLT_TRACE(ctxt,XSLT_TRACE_COMMENT,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltComment: content %s\n", value));
+    }
+#endif
+
+    commentNode = xmlNewComment(value);
+    xmlAddChild(ctxt->insert, commentNode);
+
+    if (value != NULL)
+       xmlFree(value);
+}
+
+/**
+ * xsltProcessingInstruction:
+ * @ctxt:  a XSLT process context
+ * @node:  the node in the source tree.
+ * @inst:  the xslt processing-instruction node
+ * @comp:  precomputed information
+ *
+ * Process the xslt processing-instruction node on the source node
+ */
+void
+xsltProcessingInstruction(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                  xmlNodePtr inst, xsltStylePreCompPtr castedComp) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemPIPtr comp = (xsltStyleItemPIPtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif
+    const xmlChar *name;
+    xmlChar *value = NULL;
+    xmlNodePtr pi;
+
+
+    if (ctxt->insert == NULL)
+       return;
+    if (comp->has_name == 0)
+       return;
+    if (comp->name == NULL) {
+       name = xsltEvalAttrValueTemplate(ctxt, inst,
+                           (const xmlChar *)"name", NULL);
+       if (name == NULL) {
+           xsltTransformError(ctxt, NULL, inst,
+                "xsl:processing-instruction : name is missing\n");
+           goto error;
+       }
+    } else {
+       name = comp->name;
+    }
+    /* TODO: check that it's both an an NCName and a PITarget. */
+
+
+    value = xsltEvalTemplateString(ctxt, node, inst);
+    if (xmlStrstr(value, BAD_CAST "?>") != NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+            "xsl:processing-instruction: '?>' not allowed within PI content\n");
+       goto error;
+    }
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    if (value == NULL) {
+       XSLT_TRACE(ctxt,XSLT_TRACE_PI,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltProcessingInstruction: %s empty\n", name));
+    } else {
+       XSLT_TRACE(ctxt,XSLT_TRACE_PI,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltProcessingInstruction: %s content %s\n", name, value));
+    }
+#endif
+
+    pi = xmlNewDocPI(ctxt->insert->doc, name, value);
+    xmlAddChild(ctxt->insert, pi);
+
+error:
+    if ((name != NULL) && (name != comp->name))
+        xmlFree((xmlChar *) name);
+    if (value != NULL)
+       xmlFree(value);
+}
+
+/**
+ * xsltCopyOf:
+ * @ctxt:  an XSLT transformation context
+ * @node:  the current node in the source tree
+ * @inst:  the element node of the XSLT copy-of instruction 
+ * @comp:  precomputed information of the XSLT copy-of instruction
+ *
+ * Process the XSLT copy-of instruction.
+ */
+void
+xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                  xmlNodePtr inst, xsltStylePreCompPtr castedComp) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemCopyOfPtr comp = (xsltStyleItemCopyOfPtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif
+    xmlXPathObjectPtr res = NULL;
+    xmlNodeSetPtr list = NULL;
+    int i;
+    xmlDocPtr oldXPContextDoc;
+    xmlNsPtr *oldXPNamespaces;
+    xmlNodePtr oldXPContextNode;
+    int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
+    xmlXPathContextPtr xpctxt;
+
+    if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
+       return;
+    if ((comp == NULL) || (comp->select == NULL) || (comp->comp == NULL)) {
+       xsltTransformError(ctxt, NULL, inst,
+            "xsl:copy-of : compilation failed\n");
+       return;
+    }
+
+     /*
+    * SPEC XSLT 1.0:
+    *  "The xsl:copy-of element can be used to insert a result tree
+    *  fragment into the result tree, without first converting it to
+    *  a string as xsl:value-of does (see [7.6.1 Generating Text with
+    *  xsl:value-of]). The required select attribute contains an
+    *  expression. When the result of evaluating the expression is a
+    *  result tree fragment, the complete fragment is copied into the
+    *  result tree. When the result is a node-set, all the nodes in the
+    *  set are copied in document order into the result tree; copying
+    *  an element node copies the attribute nodes, namespace nodes and
+    *  children of the element node as well as the element node itself;
+    *  a root node is copied by copying its children. When the result
+    *  is neither a node-set nor a result tree fragment, the result is
+    *  converted to a string and then inserted into the result tree,
+    *  as with xsl:value-of.
+    */
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    XSLT_TRACE(ctxt,XSLT_TRACE_COPY_OF,xsltGenericDebug(xsltGenericDebugContext,
+        "xsltCopyOf: select %s\n", comp->select));
+#endif
+
+    /*
+    * Evaluate the "select" expression.
+    */
+    xpctxt = ctxt->xpathCtxt;
+    oldXPContextDoc = xpctxt->doc;
+    oldXPContextNode = xpctxt->node;
+    oldXPProximityPosition = xpctxt->proximityPosition;
+    oldXPContextSize = xpctxt->contextSize;
+    oldXPNsNr = xpctxt->nsNr;
+    oldXPNamespaces = xpctxt->namespaces;
+    
+    xpctxt->node = node;
+    if (comp != NULL) {
+
+#ifdef XSLT_REFACTORED
+       if (comp->inScopeNs != NULL) {
+           xpctxt->namespaces = comp->inScopeNs->list;
+           xpctxt->nsNr = comp->inScopeNs->xpathNumber;
+       } else {
+           xpctxt->namespaces = NULL;
+           xpctxt->nsNr = 0;
+       }
+#else
+       xpctxt->namespaces = comp->nsList;
+       xpctxt->nsNr = comp->nsNr;
+#endif
+    } else {
+       xpctxt->namespaces = NULL;
+       xpctxt->nsNr = 0;
+    }
+
+    res = xmlXPathCompiledEval(comp->comp, xpctxt);
+
+    xpctxt->doc = oldXPContextDoc;
+    xpctxt->node = oldXPContextNode;
+    xpctxt->contextSize = oldXPContextSize;
+    xpctxt->proximityPosition = oldXPProximityPosition;        
+    xpctxt->nsNr = oldXPNsNr;
+    xpctxt->namespaces = oldXPNamespaces;
+
+    if (res != NULL) {
+       if (res->type == XPATH_NODESET) {
+           /*
+           * Node-set
+           * --------
+           */
+#ifdef WITH_XSLT_DEBUG_PROCESS
+           XSLT_TRACE(ctxt,XSLT_TRACE_COPY_OF,xsltGenericDebug(xsltGenericDebugContext,
+                "xsltCopyOf: result is a node set\n"));
+#endif
+           list = res->nodesetval;
+           if (list != NULL) {
+               xmlNodePtr cur;
+               /*
+               * The list is already sorted in document order by XPath.
+               * Append everything in this order under ctxt->insert.
+               */
+               for (i = 0;i < list->nodeNr;i++) {
+                   cur = list->nodeTab[i];
+                   if (cur == NULL)
+                       continue;
+                   if ((cur->type == XML_DOCUMENT_NODE) ||
+                       (cur->type == XML_HTML_DOCUMENT_NODE))
+                   {
+                       xsltCopyTreeList(ctxt, inst,
+                           cur->children, ctxt->insert, 0, 0);
+                   } else if (cur->type == XML_ATTRIBUTE_NODE) {
+                       xsltShallowCopyAttr(ctxt, inst,
+                           ctxt->insert, (xmlAttrPtr) cur);
+                   } else {
+                       xsltCopyTreeInternal(ctxt, inst,
+                           cur, ctxt->insert, 0, 0);
+                   }
+               }
+           }
+       } else if (res->type == XPATH_XSLT_TREE) {
+           /*
+           * Result tree fragment
+           * --------------------
+           * E.g. via <xsl:variable ...><foo/></xsl:variable>
+           * Note that the root node of such trees is an xmlDocPtr in Libxslt.
+           */
+#ifdef WITH_XSLT_DEBUG_PROCESS
+           XSLT_TRACE(ctxt,XSLT_TRACE_COPY_OF,xsltGenericDebug(xsltGenericDebugContext,
+                "xsltCopyOf: result is a result tree fragment\n"));
+#endif     
+           list = res->nodesetval;
+           if ((list != NULL) && (list->nodeTab != NULL) &&
+               (list->nodeTab[0] != NULL) &&
+               (IS_XSLT_REAL_NODE(list->nodeTab[0])))
+           {
+               xsltCopyTreeList(ctxt, inst,
+                   list->nodeTab[0]->children, ctxt->insert, 0, 0);
+           }
+       } else {
+           xmlChar *value = NULL;
+           /*
+           * Convert to a string.
+           */
+           value = xmlXPathCastToString(res);
+           if (value == NULL) {
+               xsltTransformError(ctxt, NULL, inst,
+                   "Internal error in xsltCopyOf(): "
+                   "failed to cast an XPath object to string.\n");
+               ctxt->state = XSLT_STATE_STOPPED;
+           } else {
+               if (value[0] != 0) {
+                   /*
+                   * Append content as text node.
+                   */
+                   xsltCopyTextString(ctxt, ctxt->insert, value, 0);
+               }
+               
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               XSLT_TRACE(ctxt,XSLT_TRACE_COPY_OF,xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltCopyOf: result %s\n", res->stringval));
+#endif
+           }
+       }
+    } else {
+       ctxt->state = XSLT_STATE_STOPPED;
+    }
+
+    if (res != NULL)
+       xmlXPathFreeObject(res);
+}
+
+/**
+ * xsltValueOf:
+ * @ctxt:  a XSLT process context
+ * @node:  the node in the source tree.
+ * @inst:  the xslt value-of node
+ * @comp:  precomputed information
+ *
+ * Process the xslt value-of node on the source node
+ */
+void
+xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                  xmlNodePtr inst, xsltStylePreCompPtr castedComp)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemValueOfPtr comp = (xsltStyleItemValueOfPtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif
+    xmlXPathObjectPtr res = NULL;
+    xmlNodePtr copy = NULL;
+    xmlChar *value = NULL;
+    xmlDocPtr oldXPContextDoc;
+    xmlNsPtr *oldXPNamespaces;
+    xmlNodePtr oldXPContextNode;
+    int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
+    xmlXPathContextPtr xpctxt;
+
+    if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
+       return;
+
+    if ((comp == NULL) || (comp->select == NULL) || (comp->comp == NULL)) {
+       xsltTransformError(ctxt, NULL, inst,
+           "Internal error in xsltValueOf(): "
+           "The XSLT 'value-of' instruction was not compiled.\n");
+       return;
+    }
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    XSLT_TRACE(ctxt,XSLT_TRACE_VALUE_OF,xsltGenericDebug(xsltGenericDebugContext,
+        "xsltValueOf: select %s\n", comp->select));
+#endif
+
+    xpctxt = ctxt->xpathCtxt;
+    oldXPContextDoc = xpctxt->doc;
+    oldXPContextNode = xpctxt->node;
+    oldXPProximityPosition = xpctxt->proximityPosition;
+    oldXPContextSize = xpctxt->contextSize;
+    oldXPNsNr = xpctxt->nsNr;
+    oldXPNamespaces = xpctxt->namespaces;
+    
+    xpctxt->node = node;
+    if (comp != NULL) {
+
+#ifdef XSLT_REFACTORED
+       if (comp->inScopeNs != NULL) {
+           xpctxt->namespaces = comp->inScopeNs->list;
+           xpctxt->nsNr = comp->inScopeNs->xpathNumber;
+       } else {
+           xpctxt->namespaces = NULL;
+           xpctxt->nsNr = 0;
+       }
+#else
+       xpctxt->namespaces = comp->nsList;
+       xpctxt->nsNr = comp->nsNr;
+#endif
+    } else {
+       xpctxt->namespaces = NULL;
+       xpctxt->nsNr = 0;
+    }
+
+    res = xmlXPathCompiledEval(comp->comp, xpctxt);
+
+    xpctxt->doc = oldXPContextDoc;
+    xpctxt->node = oldXPContextNode;
+    xpctxt->contextSize = oldXPContextSize;
+    xpctxt->proximityPosition = oldXPProximityPosition;        
+    xpctxt->nsNr = oldXPNsNr;
+    xpctxt->namespaces = oldXPNamespaces;
+
+    /*
+    * Cast the XPath object to string.
+    */
+    if (res != NULL) {
+       value = xmlXPathCastToString(res);
+       if (value == NULL) {
+           xsltTransformError(ctxt, NULL, inst,
+               "Internal error in xsltValueOf(): "
+               "failed to cast an XPath object to string.\n");
+           ctxt->state = XSLT_STATE_STOPPED;
+           goto error;
+       }
+       if (value[0] != 0) {
+           copy = xsltCopyTextString(ctxt,
+               ctxt->insert, value, comp->noescape);
+       }
+    } else {
+       xsltTransformError(ctxt, NULL, inst,        
+           "XPath evaluation returned no result.\n");
+       ctxt->state = XSLT_STATE_STOPPED;
+       goto error;     
+    }
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    if (value) {    
+       XSLT_TRACE(ctxt,XSLT_TRACE_VALUE_OF,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltValueOf: result '%s'\n", value));
+    }
+#endif
+
+error:
+    if (value != NULL)
+       xmlFree(value);
+    if (res != NULL)
+       xmlXPathFreeObject(res);
+}
+
+/**
+ * xsltNumber:
+ * @ctxt:  a XSLT process context
+ * @node:  the node in the source tree.
+ * @inst:  the xslt number node
+ * @comp:  precomputed information
+ *
+ * Process the xslt number node on the source node
+ */
+void
+xsltNumber(xsltTransformContextPtr ctxt, xmlNodePtr node,
+          xmlNodePtr inst, xsltStylePreCompPtr castedComp)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemNumberPtr comp = (xsltStyleItemNumberPtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif
+    if (comp == NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+            "xsl:number : compilation failed\n");
+       return;
+    }
+
+    if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL))
+       return;
+
+    comp->numdata.doc = inst->doc;
+    comp->numdata.node = inst;
+    
+    xsltNumberFormat(ctxt, &comp->numdata, node);
+}
+
+/**
+ * xsltApplyImports:
+ * @ctxt:  an XSLT transformation context
+ * @contextNode:  the current node in the source tree.
+ * @inst:  the element node of the XSLT 'apply-imports' instruction
+ * @comp:  the compiled instruction
+ *
+ * Process the XSLT apply-imports element.
+ */
+void
+xsltApplyImports(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
+                xmlNodePtr inst,
+                xsltStylePreCompPtr comp ATTRIBUTE_UNUSED)
+{
+    xsltTemplatePtr templ;
+
+    if ((ctxt == NULL) || (inst == NULL))
+       return;
+
+    if (comp == NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+           "Internal error in xsltApplyImports(): "
+           "The XSLT 'apply-imports' instruction was not compiled.\n");
+       return;
+    }
+    /*
+    * NOTE that ctxt->currentTemplateRule and ctxt->templ is not the
+    * same; the former is the "Current Template Rule" as defined by the
+    * XSLT spec, the latter is simply the template struct being
+    * currently processed.
+    */
+    if (ctxt->currentTemplateRule == NULL) {
+       /*
+       * SPEC XSLT 2.0:
+       * "[ERR XTDE0560] It is a non-recoverable dynamic error if
+       *  xsl:apply-imports or xsl:next-match is evaluated when the
+       *  current template rule is null."
+       */
+       xsltTransformError(ctxt, NULL, inst,
+            "It is an error to call 'apply-imports' "
+            "when there's no current template rule.\n");
+       return;
+    }
+    /*
+    * TODO: Check if this is correct.
+    */
+    templ = xsltGetTemplate(ctxt, contextNode,
+       ctxt->currentTemplateRule->style);
+
+    if (templ != NULL) {
+       xsltTemplatePtr oldCurTemplRule = ctxt->currentTemplateRule;
+       /*
+       * Set the current template rule.
+       */
+       ctxt->currentTemplateRule = templ;
+       /*
+       * URGENT TODO: Need xsl:with-param be handled somehow here?
+       */
+       xsltApplyXSLTTemplate(ctxt, contextNode, templ->content,
+           templ, NULL);
+
+       ctxt->currentTemplateRule = oldCurTemplRule;
+    }
+}
+
+/**
+ * xsltCallTemplate:
+ * @ctxt:  a XSLT transformation context
+ * @node:  the "current node" in the source tree
+ * @inst:  the XSLT 'call-template' instruction
+ * @comp:  the compiled information of the instruction
+ *
+ * Processes the XSLT call-template instruction on the source node.
+ */
+void
+xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                  xmlNodePtr inst, xsltStylePreCompPtr castedComp)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemCallTemplatePtr comp =
+       (xsltStyleItemCallTemplatePtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif
+    xsltStackElemPtr withParams = NULL;
+
+    if (ctxt->insert == NULL)
+       return;
+    if (comp == NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+            "The XSLT 'call-template' instruction was not compiled.\n");
+       return;
+    }
+
+    /*
+     * The template must have been precomputed
+     */
+    if (comp->templ == NULL) {
+       comp->templ = xsltFindTemplate(ctxt, comp->name, comp->ns);
+       if (comp->templ == NULL) {
+           if (comp->ns != NULL) {
+               xsltTransformError(ctxt, NULL, inst,
+                       "The called template '{%s}%s' was not found.\n",
+                       comp->ns, comp->name);
+           } else {
+               xsltTransformError(ctxt, NULL, inst,
+                       "The called template '%s' was not found.\n",
+                       comp->name);
+           }
+           return;
+       }
+    }
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    if ((comp != NULL) && (comp->name != NULL))
+       XSLT_TRACE(ctxt,XSLT_TRACE_CALL_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
+                        "call-template: name %s\n", comp->name));
+#endif
+
+    if (inst->children) {
+       xmlNodePtr cur;
+       xsltStackElemPtr param;
+
+       cur = inst->children;
+       while (cur != NULL) {
+#ifdef WITH_DEBUGGER
+           if (ctxt->debugStatus != XSLT_DEBUG_NONE)
+               xslHandleDebugger(cur, node, comp->templ, ctxt);
+#endif
+           if (ctxt->state == XSLT_STATE_STOPPED) break;
+           /*
+           * TODO: The "with-param"s could be part of the "call-template"
+           *   structure. Avoid to "search" for params dynamically
+           *   in the XML tree every time.
+           */
+           if (IS_XSLT_ELEM(cur)) {
+               if (IS_XSLT_NAME(cur, "with-param")) {
+                   param = xsltParseStylesheetCallerParam(ctxt, cur);
+                   if (param != NULL) {
+                       param->next = withParams;
+                       withParams = param;
+                   }
+               } else {
+                   xsltGenericError(xsltGenericErrorContext,
+                       "xsl:call-template: misplaced xsl:%s\n", cur->name);
+               }
+           } else {
+               xsltGenericError(xsltGenericErrorContext,
+                   "xsl:call-template: misplaced %s element\n", cur->name);
+           }
+           cur = cur->next;
+       }
+    }
+    /*
+     * Create a new frame using the params first     
+     */
+    xsltApplyXSLTTemplate(ctxt, node, comp->templ->content, comp->templ,
+       withParams);
+    if (withParams != NULL)
+       xsltFreeStackElemList(withParams);
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    if ((comp != NULL) && (comp->name != NULL))
+       XSLT_TRACE(ctxt,XSLT_TRACE_CALL_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
+                        "call-template returned: name %s\n", comp->name));
+#endif
+}
+
+/**
+ * xsltApplyTemplates:
+ * @ctxt:  a XSLT transformation context
+ * @node:  the 'current node' in the source tree
+ * @inst:  the element node of an XSLT 'apply-templates' instruction
+ * @comp:  the compiled instruction
+ *
+ * Processes the XSLT 'apply-templates' instruction on the current node.
+ */
+void
+xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
+                  xmlNodePtr inst, xsltStylePreCompPtr castedComp)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemApplyTemplatesPtr comp =
+       (xsltStyleItemApplyTemplatesPtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif
+    int i;
+    xmlNodePtr cur, delNode = NULL, oldContextNode;    
+    xmlNodeSetPtr list = NULL, oldList;
+    xsltStackElemPtr withParams = NULL;
+    int oldXPProximityPosition, oldXPContextSize;
+    const xmlChar *oldMode, *oldModeURI;
+    xmlDocPtr oldDoc;
+    xsltDocumentPtr oldDocInfo;
+    xmlXPathContextPtr xpctxt;
+
+    if (comp == NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+            "xsl:apply-templates : compilation failed\n");
+       return;
+    }
+    if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL))
+       return;
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    if ((node != NULL) && (node->name != NULL))
+       XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltApplyTemplates: node: '%s'\n", node->name));
+#endif
+
+    xpctxt = ctxt->xpathCtxt;   
+    /*
+    * Save context states.
+    */
+    oldContextNode = ctxt->node;
+    oldMode = ctxt->mode;
+    oldModeURI = ctxt->modeURI;    
+    oldDocInfo = ctxt->document;
+    oldDoc = ctxt->tmpDoc;
+    oldList = ctxt->nodeList;    
+
+    /*
+     * The xpath context size and proximity position, as
+     * well as the xpath and context documents, may be changed
+     * so we save their initial state and will restore on exit
+     */    
+    oldXPContextSize = xpctxt->contextSize;
+    oldXPProximityPosition = xpctxt->proximityPosition;
+
+    /*
+    * Set up contexts.
+    */
+    ctxt->mode = comp->mode;
+    ctxt->modeURI = comp->modeURI;
+
+    if (comp->select != NULL) {        
+       xmlXPathObjectPtr res = NULL;
+
+       if (comp->comp == NULL) {
+           xsltTransformError(ctxt, NULL, inst,
+                "xsl:apply-templates : compilation failed\n");
+           goto error;
+       }
+#ifdef WITH_XSLT_DEBUG_PROCESS
+       XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltApplyTemplates: select %s\n", comp->select));
+#endif
+
+       /*
+       * Set up XPath.
+       */
+       xpctxt->node = node; /* Set the "context node" */
+#ifdef XSLT_REFACTORED
+       if (comp->inScopeNs != NULL) {
+           xpctxt->namespaces = comp->inScopeNs->list;
+           xpctxt->nsNr = comp->inScopeNs->xpathNumber;
+       } else {
+           xpctxt->namespaces = NULL;
+           xpctxt->nsNr = 0;
+       }
+#else
+       xpctxt->namespaces = comp->nsList;
+       xpctxt->nsNr = comp->nsNr;
+#endif
+       res = xmlXPathCompiledEval(comp->comp, xpctxt);
+
+       xpctxt->contextSize = oldXPContextSize;
+       xpctxt->proximityPosition = oldXPProximityPosition;
+       if (res != NULL) {
+           if (res->type == XPATH_NODESET) {
+               list = res->nodesetval; /* consume the node set */
+               res->nodesetval = NULL; 
+           } else {
+               xsltTransformError(ctxt, NULL, inst,
+                   "The 'select' expression did not evaluate to a "
+                   "node set.\n");
+               ctxt->state = XSLT_STATE_STOPPED;
+               xmlXPathFreeObject(res);
+               goto error;
+           }
+           xmlXPathFreeObject(res);
+           /*
+           * Note: An xsl:apply-templates with a 'select' attribute,
+           * can change the current source doc.
+           */      
+       } else {
+           xsltTransformError(ctxt, NULL, inst,
+               "Failed to evaluate the 'select' expression.\n");
+           ctxt->state = XSLT_STATE_STOPPED;
+           goto error;
+       }          
+       if (list == NULL) {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+           XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
+               "xsltApplyTemplates: select didn't evaluate to a node list\n"));
+#endif
+           goto exit;
+       }
+       /*
+       * 
+       * NOTE: Previously a document info (xsltDocument) was
+       * created and attached to the Result Tree Fragment.
+       * But such a document info is created on demand in
+       * xsltKeyFunction() (functions.c), so we need to create
+       * it here beforehand.
+       * In order to take care of potential keys we need to
+       * do some extra work for the case when a Result Tree Fragment
+       * is converted into a nodeset (e.g. exslt:node-set()) :
+       * We attach a "pseudo-doc" (xsltDocument) to _private.          
+       * This xsltDocument, together with the keyset, will be freed
+       * when the Result Tree Fragment is freed.
+       *               
+       */
+#if 0
+       if ((ctxt->nbKeys > 0) &&
+           (list->nodeNr != 0) &&                  
+           (list->nodeTab[0]->doc != NULL) &&
+           XSLT_IS_RES_TREE_FRAG(list->nodeTab[0]->doc))
+       {
+           /*
+           * NOTE that it's also OK if @effectiveDocInfo will be
+           * set to NULL.
+           */
+           isRTF = 1;
+           effectiveDocInfo = list->nodeTab[0]->doc->_private;
+       }
+#endif
+    } else {
+       /*
+        * Build an XPath node set with the children
+        */
+       list = xmlXPathNodeSetCreate(NULL);
+       if (list == NULL)
+           goto error;
+       cur = node->children;
+       while (cur != NULL) {
+           switch (cur->type) {
+               case XML_TEXT_NODE:
+                   if ((IS_BLANK_NODE(cur)) &&
+                       (cur->parent != NULL) &&
+                       (cur->parent->type == XML_ELEMENT_NODE) &&
+                       (ctxt->style->stripSpaces != NULL)) {
+                       const xmlChar *val;
+
+                       if (cur->parent->ns != NULL) {
+                           val = (const xmlChar *)
+                                 xmlHashLookup2(ctxt->style->stripSpaces,
+                                                cur->parent->name,
+                                                cur->parent->ns->href);
+                           if (val == NULL) {
+                               val = (const xmlChar *)
+                                 xmlHashLookup2(ctxt->style->stripSpaces,
+                                                BAD_CAST "*",
+                                                cur->parent->ns->href);
+                           }
+                       } else {
+                           val = (const xmlChar *)
+                                 xmlHashLookup2(ctxt->style->stripSpaces,
+                                                cur->parent->name, NULL);
+                       }
+                       if ((val != NULL) &&
+                           (xmlStrEqual(val, (xmlChar *) "strip"))) {
+                           delNode = cur;
+                           break;
+                       }
+                   }
+                   /* no break on purpose */
+               case XML_ELEMENT_NODE:
+               case XML_DOCUMENT_NODE:
+               case XML_HTML_DOCUMENT_NODE:
+               case XML_CDATA_SECTION_NODE:
+               case XML_PI_NODE:
+               case XML_COMMENT_NODE:
+                   xmlXPathNodeSetAddUnique(list, cur);
+                   break;
+               case XML_DTD_NODE:
+                   /* Unlink the DTD, it's still reachable
+                    * using doc->intSubset */
+                   if (cur->next != NULL)
+                       cur->next->prev = cur->prev;
+                   if (cur->prev != NULL)
+                       cur->prev->next = cur->next;
+                   break;
+               default:
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
+                    "xsltApplyTemplates: skipping cur type %d\n",
+                                    cur->type));
+#endif
+                   delNode = cur;
+           }
+           cur = cur->next;
+           if (delNode != NULL) {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
+                    "xsltApplyTemplates: removing ignorable blank cur\n"));
+#endif
+               xmlUnlinkNode(delNode);
+               xmlFreeNode(delNode);
+               delNode = NULL;
+           }
+       }
+    }
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    if (list != NULL)
+    XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
+       "xsltApplyTemplates: list of %d nodes\n", list->nodeNr));
+#endif
+
+    if ((list == NULL) || (list->nodeNr == 0))
+       goto exit;
+
+    /*
+    * Set the context's node set and size; this is also needed for
+    * for xsltDoSortFunction().
+    */
+    ctxt->nodeList = list;
+    /* 
+    * Process xsl:with-param and xsl:sort instructions.
+    * (The code became so verbose just to avoid the
+    *  xmlNodePtr sorts[XSLT_MAX_SORT] if there's no xsl:sort)
+    * BUG TODO: We are not using namespaced potentially defined on the
+    * xsl:sort or xsl:with-param elements; XPath expression might fail.
+    */
+    if (inst->children) {
+       xsltStackElemPtr param;
+
+       cur = inst->children;
+       while (cur) {
+
+#ifdef WITH_DEBUGGER
+           if (ctxt->debugStatus != XSLT_DEBUG_NONE)
+               xslHandleDebugger(cur, node, NULL, ctxt);
+#endif
+           if (ctxt->state == XSLT_STATE_STOPPED)
+               break;
+           if (cur->type == XML_TEXT_NODE) {
+               cur = cur->next;
+               continue;
+           }       
+           if (! IS_XSLT_ELEM(cur))
+               break;
+           if (IS_XSLT_NAME(cur, "with-param")) {
+               param = xsltParseStylesheetCallerParam(ctxt, cur);
+               if (param != NULL) {
+                   param->next = withParams;
+                   withParams = param;
+               }
+           }
+           if (IS_XSLT_NAME(cur, "sort")) {
+               xsltTemplatePtr oldCurTempRule =
+                   ctxt->currentTemplateRule;
+               int nbsorts = 0;
+               xmlNodePtr sorts[XSLT_MAX_SORT];                
+               
+               sorts[nbsorts++] = cur;
+               
+               while (cur) {
+                   
+#ifdef WITH_DEBUGGER
+                   if (ctxt->debugStatus != XSLT_DEBUG_NONE)
+                       xslHandleDebugger(cur, node, NULL, ctxt);
+#endif
+                   if (ctxt->state == XSLT_STATE_STOPPED)
+                       break;
+                   
+                   if (cur->type == XML_TEXT_NODE) {
+                       cur = cur->next;
+                       continue;
+                   }
+                   
+                   if (! IS_XSLT_ELEM(cur))
+                       break;
+                   if (IS_XSLT_NAME(cur, "with-param")) {
+                       param = xsltParseStylesheetCallerParam(ctxt, cur);
+                       if (param != NULL) {
+                           param->next = withParams;
+                           withParams = param;
+                       }
+                   }   
+                   if (IS_XSLT_NAME(cur, "sort")) {
+                       if (nbsorts >= XSLT_MAX_SORT) {
+                           xsltTransformError(ctxt, NULL, cur,
+                               "The number (%d) of xsl:sort instructions exceeds the "
+                               "maximum allowed by this processor's settings.\n",
+                               nbsorts);
+                           ctxt->state = XSLT_STATE_STOPPED;
+                           break;
+                       } else {
+                           sorts[nbsorts++] = cur;
+                       }
+                   }
+                   cur = cur->next;
+               }
+               /*
+               * The "current template rule" is cleared for xsl:sort.
+               */
+               ctxt->currentTemplateRule = NULL;
+               /*
+               * Sort.
+               */
+               xsltDoSortFunction(ctxt, sorts, nbsorts);
+               ctxt->currentTemplateRule = oldCurTempRule;
+               break;
+           }
+           cur = cur->next;
+       }
+    }    
+    xpctxt->contextSize = list->nodeNr;
+    /*
+    * Apply templates for all selected source nodes.
+    */    
+    for (i = 0; i < list->nodeNr; i++) {
+       cur = list->nodeTab[i];
+       /*
+       * The node becomes the "current node".
+       */
+       ctxt->node = cur;
+       /*
+       * An xsl:apply-templates can change the current context doc.
+       * OPTIMIZE TODO: Get rid of the need to set the context doc.
+       */
+       if ((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL))
+           xpctxt->doc = cur->doc;
+
+       xpctxt->proximityPosition = i + 1;
+       /*
+       * Find and apply a template for this node.
+       */
+       xsltProcessOneNode(ctxt, cur, withParams);
+    }
+
+exit:
+error:
+    /*
+    * Free the parameter list.
+    */
+    if (withParams != NULL)
+       xsltFreeStackElemList(withParams);
+    if (list != NULL)
+       xmlXPathFreeNodeSet(list);    
+    /*
+    * Restore context states.
+    */
+    xpctxt->doc = oldDoc;
+    xpctxt->contextSize = oldXPContextSize;
+    xpctxt->proximityPosition = oldXPProximityPosition;
+    
+    ctxt->tmpDoc = oldDoc;
+    ctxt->document = oldDocInfo;
+    ctxt->nodeList = oldList;
+    ctxt->node = oldContextNode;
+    ctxt->mode = oldMode;
+    ctxt->modeURI = oldModeURI;
+}
+
+
+/**
+ * xsltChoose:
+ * @ctxt:  a XSLT process context
+ * @contextNode:  the current node in the source tree
+ * @inst:  the xsl:choose instruction
+ * @comp:  compiled information of the instruction
+ *
+ * Processes the xsl:choose instruction on the source node.
+ */
+void
+xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
+          xmlNodePtr inst, xsltStylePreCompPtr comp ATTRIBUTE_UNUSED)
+{
+    xmlNodePtr cur;
+
+    if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))
+       return;
+    
+    /* 
+    * TODO: Content model checks should be done only at compilation
+    * time.
+    */
+    cur = inst->children;
+    if (cur == NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+           "xsl:choose: The instruction has no content.\n");
+       return;
+    }
+
+#ifdef XSLT_REFACTORED
+    /*
+    * We don't check the content model during transformation.
+    */
+#else
+    if ((! IS_XSLT_ELEM(cur)) || (! IS_XSLT_NAME(cur, "when"))) {
+       xsltTransformError(ctxt, NULL, inst,
+            "xsl:choose: xsl:when expected first\n");
+       return;
+    }
+#endif
+
+    {
+       int testRes = 0, res = 0;
+       xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;    
+       xmlDocPtr oldXPContextDoc = xpctxt->doc;
+       int oldXPProximityPosition = xpctxt->proximityPosition;
+       int oldXPContextSize = xpctxt->contextSize;
+       
+#ifdef XSLT_REFACTORED
+       xsltStyleItemWhenPtr wcomp = NULL;
+#else
+       xsltStylePreCompPtr wcomp = NULL;
+#endif
+
+       /*
+       * Process xsl:when ---------------------------------------------------
+       */
+       while (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "when")) {        
+           wcomp = cur->psvi;
+           
+           if ((wcomp == NULL) || (wcomp->test == NULL) ||
+               (wcomp->comp == NULL))
+           {
+               xsltTransformError(ctxt, NULL, cur,
+                   "Internal error in xsltChoose(): "
+                   "The XSLT 'when' instruction was not compiled.\n");
+               goto error;
+           }
+           
+           
+#ifdef WITH_DEBUGGER
+           if (xslDebugStatus != XSLT_DEBUG_NONE) {
+               /* 
+               * TODO: Isn't comp->templ always NULL for xsl:choose?
+               */
+               xslHandleDebugger(cur, contextNode, NULL, ctxt);
+           }
+#endif
+#ifdef WITH_XSLT_DEBUG_PROCESS
+           XSLT_TRACE(ctxt,XSLT_TRACE_CHOOSE,xsltGenericDebug(xsltGenericDebugContext,
+               "xsltChoose: test %s\n", wcomp->test));
+#endif
+
+           xpctxt->node = contextNode;
+           xpctxt->doc = oldXPContextDoc;
+           xpctxt->proximityPosition = oldXPProximityPosition;
+           xpctxt->contextSize = oldXPContextSize;
+           
+#ifdef XSLT_REFACTORED
+           if (wcomp->inScopeNs != NULL) {
+               xpctxt->namespaces = wcomp->inScopeNs->list;
+               xpctxt->nsNr = wcomp->inScopeNs->xpathNumber;
+           } else {
+               xpctxt->namespaces = NULL;
+               xpctxt->nsNr = 0;
+           }
+#else
+           xpctxt->namespaces = wcomp->nsList;
+           xpctxt->nsNr = wcomp->nsNr;
+#endif
+           
+           
+#ifdef XSLT_FAST_IF
+           res = xmlXPathCompiledEvalToBoolean(wcomp->comp, xpctxt);
+           
+           if (res == -1) {
+               ctxt->state = XSLT_STATE_STOPPED;
+               goto error;
+           }
+           testRes = (res == 1) ? 1 : 0;       
+           
+#else /* XSLT_FAST_IF */
+           
+           res = xmlXPathCompiledEval(wcomp->comp, xpctxt);
+           
+           if (res != NULL) {
+               if (res->type != XPATH_BOOLEAN)
+                   res = xmlXPathConvertBoolean(res);
+               if (res->type == XPATH_BOOLEAN)
+                   testRes = res->boolval;
+               else {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   XSLT_TRACE(ctxt,XSLT_TRACE_CHOOSE,xsltGenericDebug(xsltGenericDebugContext,
+                       "xsltChoose: test didn't evaluate to a boolean\n"));
+#endif
+                   goto error;
+               }
+               xmlXPathFreeObject(res);
+               res = NULL;
+           } else {
+               ctxt->state = XSLT_STATE_STOPPED;
+               goto error;
+           }
+           
+#endif /* else of XSLT_FAST_IF */
+           
+#ifdef WITH_XSLT_DEBUG_PROCESS
+           XSLT_TRACE(ctxt,XSLT_TRACE_CHOOSE,xsltGenericDebug(xsltGenericDebugContext,
+               "xsltChoose: test evaluate to %d\n", testRes));
+#endif
+           if (testRes)                
+               goto test_is_true;
+           
+           cur = cur->next;
+       }
+    
+       /*
+       * Process xsl:otherwise ----------------------------------------------
+       */
+       if (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "otherwise")) {
+           
+#ifdef WITH_DEBUGGER
+           if (xslDebugStatus != XSLT_DEBUG_NONE)
+               xslHandleDebugger(cur, contextNode, NULL, ctxt);
+#endif
+           
+#ifdef WITH_XSLT_DEBUG_PROCESS
+           XSLT_TRACE(ctxt,XSLT_TRACE_CHOOSE,xsltGenericDebug(xsltGenericDebugContext,
+               "evaluating xsl:otherwise\n"));
+#endif     
+           goto test_is_true;
+       }
+       xpctxt->node = contextNode;
+       xpctxt->doc = oldXPContextDoc;
+       xpctxt->proximityPosition = oldXPProximityPosition;
+       xpctxt->contextSize = oldXPContextSize;
+       goto exit;
+
+test_is_true:
+
+       xpctxt->node = contextNode;
+       xpctxt->doc = oldXPContextDoc;
+       xpctxt->proximityPosition = oldXPProximityPosition;
+       xpctxt->contextSize = oldXPContextSize;
+       goto process_sequence;
+    }
+
+process_sequence:
+    
+    /*
+    * Instantiate the sequence constructor.
+    */
+    xsltApplySequenceConstructor(ctxt, ctxt->node, cur->children,
+       NULL);
+
+exit:
+error:
+    return;
+}
+
+/**
+ * xsltIf:
+ * @ctxt:  a XSLT process context
+ * @contextNode:  the current node in the source tree
+ * @inst:  the xsl:if instruction
+ * @comp:  compiled information of the instruction
+ *
+ * Processes the xsl:if instruction on the source node.
+ */
+void
+xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
+                  xmlNodePtr inst, xsltStylePreCompPtr castedComp)
+{
+    int res = 0;
+
+#ifdef XSLT_REFACTORED
+    xsltStyleItemIfPtr comp = (xsltStyleItemIfPtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif
+
+    if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))
+       return;
+    if ((comp == NULL) || (comp->test == NULL) || (comp->comp == NULL)) {
+       xsltTransformError(ctxt, NULL, inst,
+           "Internal error in xsltIf(): "
+           "The XSLT 'if' instruction was not compiled.\n");
+       return;
+    }
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    XSLT_TRACE(ctxt,XSLT_TRACE_IF,xsltGenericDebug(xsltGenericDebugContext,
+        "xsltIf: test %s\n", comp->test));
+#endif
+
+#ifdef XSLT_FAST_IF    
+    {
+       xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;
+       xmlDocPtr oldXPContextDoc = xpctxt->doc;
+       xmlNsPtr *oldXPNamespaces = xpctxt->namespaces;
+       xmlNodePtr oldXPContextNode = xpctxt->node;
+       int oldXPProximityPosition = xpctxt->proximityPosition;
+       int oldXPContextSize = xpctxt->contextSize;
+       int oldXPNsNr = xpctxt->nsNr;
+       xmlDocPtr oldLocalFragmentTop = ctxt->localRVT; 
+       
+       xpctxt->node = contextNode;
+       if (comp != NULL) {
+           
+#ifdef XSLT_REFACTORED
+           if (comp->inScopeNs != NULL) {
+               xpctxt->namespaces = comp->inScopeNs->list;
+               xpctxt->nsNr = comp->inScopeNs->xpathNumber;
+           } else {
+               xpctxt->namespaces = NULL;
+               xpctxt->nsNr = 0;
+           }
+#else
+           xpctxt->namespaces = comp->nsList;
+           xpctxt->nsNr = comp->nsNr;
+#endif
+       } else {
+           xpctxt->namespaces = NULL;
+           xpctxt->nsNr = 0;
+       }
+       /*
+       * This XPath function is optimized for boolean results.
+       */      
+       res = xmlXPathCompiledEvalToBoolean(comp->comp, xpctxt);
+
+       /*
+       * Cleanup fragments created during evaluation of the
+       * "select" expression.
+       */
+       if (oldLocalFragmentTop != ctxt->localRVT)
+           xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
+       
+       xpctxt->doc = oldXPContextDoc;
+       xpctxt->node = oldXPContextNode;
+       xpctxt->contextSize = oldXPContextSize;
+       xpctxt->proximityPosition = oldXPProximityPosition;     
+       xpctxt->nsNr = oldXPNsNr;
+       xpctxt->namespaces = oldXPNamespaces;
+    }
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    XSLT_TRACE(ctxt,XSLT_TRACE_IF,xsltGenericDebug(xsltGenericDebugContext,
+       "xsltIf: test evaluate to %d\n", res));
+#endif
+    
+    if (res == -1) {
+       ctxt->state = XSLT_STATE_STOPPED;
+       goto error;
+    }
+    if (res == 1) {
+       /*
+       * Instantiate the sequence constructor of xsl:if.
+       */
+       xsltApplySequenceConstructor(ctxt,
+           contextNode, inst->children, NULL);
+    }
+       
+#else /* XSLT_FAST_IF */
+    {
+       xmlXPathObjectPtr xpobj = NULL;
+       /*
+       * OLD CODE:
+       */
+       {
+           xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;
+           xmlDocPtr oldXPContextDoc = xpctxt->doc;
+           xmlNsPtr *oldXPNamespaces = xpctxt->namespaces;
+           xmlNodePtr oldXPContextNode = xpctxt->node;
+           int oldXPProximityPosition = xpctxt->proximityPosition;
+           int oldXPContextSize = xpctxt->contextSize;
+           int oldXPNsNr = xpctxt->nsNr;       
+           
+           xpctxt->node = contextNode;
+           if (comp != NULL) {
+               
+#ifdef XSLT_REFACTORED
+               if (comp->inScopeNs != NULL) {
+                   xpctxt->namespaces = comp->inScopeNs->list;
+                   xpctxt->nsNr = comp->inScopeNs->xpathNumber;
+               } else {
+                   xpctxt->namespaces = NULL;
+                   xpctxt->nsNr = 0;
+               }
+#else
+               xpctxt->namespaces = comp->nsList;
+               xpctxt->nsNr = comp->nsNr;
+#endif
+           } else {
+               xpctxt->namespaces = NULL;
+               xpctxt->nsNr = 0;
+           }
+           
+           /*
+           * This XPath function is optimized for boolean results.
+           */  
+           xpobj = xmlXPathCompiledEval(comp->comp, xpctxt);
+           
+           xpctxt->doc = oldXPContextDoc;
+           xpctxt->node = oldXPContextNode;
+           xpctxt->contextSize = oldXPContextSize;
+           xpctxt->proximityPosition = oldXPProximityPosition; 
+           xpctxt->nsNr = oldXPNsNr;
+           xpctxt->namespaces = oldXPNamespaces;
+       }
+       if (xpobj != NULL) {
+           if (xpobj->type != XPATH_BOOLEAN)
+               xpobj = xmlXPathConvertBoolean(xpobj);
+           if (xpobj->type == XPATH_BOOLEAN) {
+               res = xpobj->boolval;
+               
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               XSLT_TRACE(ctxt,XSLT_TRACE_IF,xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltIf: test evaluate to %d\n", res));
+#endif
+               if (res) {
+                   xsltApplySequenceConstructor(ctxt,
+                       contextNode, inst->children, NULL);
+               }
+           } else {
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               XSLT_TRACE(ctxt, XSLT_TRACE_IF,
+                   xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltIf: test didn't evaluate to a boolean\n"));
+#endif
+               ctxt->state = XSLT_STATE_STOPPED;
+           }
+           xmlXPathFreeObject(xpobj);
+       } else {
+           ctxt->state = XSLT_STATE_STOPPED;
+       }
+    }
+#endif /* else of XSLT_FAST_IF */
+
+error:
+    return;
+}
+
+/**
+ * xsltForEach:
+ * @ctxt:  an XSLT transformation context
+ * @node:  the "current node" in the source tree  
+ * @inst:  the element node of the xsl:for-each instruction
+ * @comp:  the compiled information of the instruction
+ *
+ * Process the xslt for-each node on the source node
+ */
+void
+xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
+           xmlNodePtr inst, xsltStylePreCompPtr castedComp)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemForEachPtr comp = (xsltStyleItemForEachPtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif
+    int i;
+    xmlXPathObjectPtr res = NULL;
+    xmlNodePtr cur, curInst;
+    xmlNodeSetPtr list = NULL;
+    xmlNodeSetPtr oldList;        
+    int oldXPProximityPosition, oldXPContextSize;
+    xmlNodePtr oldContextNode;
+    xsltTemplatePtr oldCurTemplRule;    
+    xmlDocPtr oldSourceDoc;
+    xsltDocumentPtr oldDocInfo;
+    xmlXPathContextPtr xpctxt;
+
+    if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL)) {
+       xsltGenericError(xsltGenericErrorContext,       
+           "xsltForEach(): Bad arguments.\n");
+       return;
+    }
+
+    if (comp == NULL) {
+        xsltTransformError(ctxt, NULL, inst,
+           "Internal error in xsltForEach(): "
+           "The XSLT 'for-each' instruction was not compiled.\n");
+        return;
+    }
+    if ((comp->select == NULL) || (comp->comp == NULL)) {
+       xsltTransformError(ctxt, NULL, inst,
+           "Internal error in xsltForEach(): "
+           "The selecting expression of the XSLT 'for-each' "
+           "instruction was not compiled correctly.\n");
+       return;
+    }
+    xpctxt = ctxt->xpathCtxt;    
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    XSLT_TRACE(ctxt,XSLT_TRACE_FOR_EACH,xsltGenericDebug(xsltGenericDebugContext,
+        "xsltForEach: select %s\n", comp->select));
+#endif
+
+    /*
+    * Save context states.
+    */
+    oldDocInfo = ctxt->document;
+    oldList = ctxt->nodeList;
+    oldSourceDoc = ctxt->tmpDoc;
+    oldContextNode = ctxt->node;
+    /*
+    * The "current template rule" is cleared for the instantiation of
+    * xsl:for-each.
+    */
+    oldCurTemplRule = ctxt->currentTemplateRule;
+    ctxt->currentTemplateRule = NULL;
+
+    oldXPProximityPosition = xpctxt->proximityPosition;
+    oldXPContextSize = xpctxt->contextSize;
+    /*
+    * Set up XPath.
+    */
+    xpctxt->node = contextNode;
+#ifdef XSLT_REFACTORED
+    if (comp->inScopeNs != NULL) {
+       xpctxt->namespaces = comp->inScopeNs->list;
+       xpctxt->nsNr = comp->inScopeNs->xpathNumber;
+    } else {
+       xpctxt->namespaces = NULL;
+       xpctxt->nsNr = 0;
+    }
+#else
+    xpctxt->namespaces = comp->nsList;
+    xpctxt->nsNr = comp->nsNr;
+#endif   
+    
+    /*
+    * Evaluate the 'select' expression.
+    */
+    res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt);
+
+    if (res != NULL) {
+       if (res->type == XPATH_NODESET)
+           list = res->nodesetval;
+       else {
+           xsltTransformError(ctxt, NULL, inst,
+               "The 'select' expression does not evaluate to a node set.\n");
+           
+#ifdef WITH_XSLT_DEBUG_PROCESS
+           XSLT_TRACE(ctxt,XSLT_TRACE_FOR_EACH,xsltGenericDebug(xsltGenericDebugContext,
+               "xsltForEach: select didn't evaluate to a node list\n"));
+#endif
+           goto error;
+       }
+    } else {
+       xsltTransformError(ctxt, NULL, inst,
+           "Failed to evaluate the 'select' expression.\n");
+       ctxt->state = XSLT_STATE_STOPPED;
+       goto error;
+    }
+
+    if ((list == NULL) || (list->nodeNr <= 0))
+       goto exit;
+
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    XSLT_TRACE(ctxt,XSLT_TRACE_FOR_EACH,xsltGenericDebug(xsltGenericDebugContext,
+       "xsltForEach: select evaluates to %d nodes\n", list->nodeNr));
+#endif
+
+    /*
+    * Restore XPath states for the "current node".
+    */
+    xpctxt->contextSize = oldXPContextSize;
+    xpctxt->proximityPosition = oldXPProximityPosition;
+    xpctxt->node = contextNode;
+    
+    /*
+    * Set the list; this has to be done already here for xsltDoSortFunction().
+    */
+    ctxt->nodeList = list;    
+    /* 
+    * Handle xsl:sort instructions and skip them for further processing.
+    * BUG TODO: We are not using namespaced potentially defined on the
+    * xsl:sort element; XPath expression might fail.
+    */
+    curInst = inst->children;
+    if (IS_XSLT_ELEM(curInst) && IS_XSLT_NAME(curInst, "sort")) {
+       int nbsorts = 0;
+       xmlNodePtr sorts[XSLT_MAX_SORT];
+
+       sorts[nbsorts++] = curInst;
+
+#ifdef WITH_DEBUGGER
+       if (xslDebugStatus != XSLT_DEBUG_NONE)
+           xslHandleDebugger(curInst, contextNode, NULL, ctxt);
+#endif
+
+       curInst = curInst->next;
+       while (IS_XSLT_ELEM(curInst) && IS_XSLT_NAME(curInst, "sort")) {
+           if (nbsorts >= XSLT_MAX_SORT) {
+               xsltTransformError(ctxt, NULL, curInst,
+                   "The number of xsl:sort instructions exceeds the "
+                   "maximum (%d) allowed by this processor.\n",
+                   XSLT_MAX_SORT);
+               goto error;
+           } else {
+               sorts[nbsorts++] = curInst;
+           }
+           
+#ifdef WITH_DEBUGGER
+           if (xslDebugStatus != XSLT_DEBUG_NONE)
+               xslHandleDebugger(curInst, contextNode, NULL, ctxt);
+#endif
+           curInst = curInst->next;
+       }
+       xsltDoSortFunction(ctxt, sorts, nbsorts);
+    }    
+    xpctxt->contextSize = list->nodeNr;
+    /*
+    * Instantiate the sequence constructor for each selected node.
+    */    
+    for (i = 0; i < list->nodeNr; i++) {
+       cur = list->nodeTab[i];
+       /*
+       * The selected node becomes the "current node".
+       */
+       ctxt->node = cur;
+       /*
+       * An xsl:for-each can change the current context doc.
+       * OPTIMIZE TODO: Get rid of the need to set the context doc.
+       */
+       if ((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL))
+           xpctxt->doc = cur->doc;
+
+       xpctxt->proximityPosition = i + 1;
+
+       xsltApplySequenceConstructor(ctxt, cur, curInst, NULL);
+    }
+
+exit:
+error:
+    if (res != NULL)
+       xmlXPathFreeObject(res);
+    /*
+    * Restore old states.
+    */
+    ctxt->tmpDoc = oldSourceDoc;
+    ctxt->document = oldDocInfo;
+    ctxt->nodeList = oldList;
+    ctxt->node = oldContextNode;
+    ctxt->currentTemplateRule = oldCurTemplRule;
+
+    xpctxt->doc = oldSourceDoc;
+    xpctxt->contextSize = oldXPContextSize;
+    xpctxt->proximityPosition = oldXPProximityPosition;
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Generic interface                               *
+ *                                                                     *
+ ************************************************************************/
+
+#ifdef XSLT_GENERATE_HTML_DOCTYPE
+typedef struct xsltHTMLVersion {
+    const char *version;
+    const char *public;
+    const char *system;
+} xsltHTMLVersion;
+
+static xsltHTMLVersion xsltHTMLVersions[] = {
+    { "4.01frame", "-//W3C//DTD HTML 4.01 Frameset//EN",
+      "http://www.w3.org/TR/1999/REC-html401-19991224/frameset.dtd"},
+    { "4.01strict", "-//W3C//DTD HTML 4.01//EN",
+      "http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd"},
+    { "4.01trans", "-//W3C//DTD HTML 4.01 Transitional//EN",
+      "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd"},
+    { "4.01", "-//W3C//DTD HTML 4.01 Transitional//EN",
+      "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd"},
+    { "4.0strict", "-//W3C//DTD HTML 4.01//EN",
+      "http://www.w3.org/TR/html4/strict.dtd"},
+    { "4.0trans", "-//W3C//DTD HTML 4.01 Transitional//EN",
+      "http://www.w3.org/TR/html4/loose.dtd"},
+    { "4.0frame", "-//W3C//DTD HTML 4.01 Frameset//EN",
+      "http://www.w3.org/TR/html4/frameset.dtd"},
+    { "4.0", "-//W3C//DTD HTML 4.01 Transitional//EN",
+      "http://www.w3.org/TR/html4/loose.dtd"},
+    { "3.2", "-//W3C//DTD HTML 3.2//EN", NULL }
+};
+
+/**
+ * xsltGetHTMLIDs:
+ * @version:  the version string
+ * @publicID:  used to return the public ID
+ * @systemID:  used to return the system ID
+ *
+ * Returns -1 if not found, 0 otherwise and the system and public
+ *         Identifier for this given verion of HTML
+ */
+static int
+xsltGetHTMLIDs(const xmlChar *version, const xmlChar **publicID,
+                   const xmlChar **systemID) {
+    unsigned int i;
+    if (version == NULL)
+       return(-1);
+    for (i = 0;i < (sizeof(xsltHTMLVersions)/sizeof(xsltHTMLVersions[1]));
+        i++) {
+       if (!xmlStrcasecmp(version,
+                          (const xmlChar *) xsltHTMLVersions[i].version)) {
+           if (publicID != NULL)
+               *publicID = (const xmlChar *) xsltHTMLVersions[i].public;
+           if (systemID != NULL)
+               *systemID = (const xmlChar *) xsltHTMLVersions[i].system;
+           return(0);
+       }
+    }
+    return(-1);
+}
+#endif
+
+/**
+ * xsltApplyStripSpaces:
+ * @ctxt:  a XSLT process context
+ * @node:  the root of the XML tree
+ *
+ * Strip the unwanted ignorable spaces from the input tree
+ */
+void
+xsltApplyStripSpaces(xsltTransformContextPtr ctxt, xmlNodePtr node) {
+    xmlNodePtr current;
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    int nb = 0;
+#endif
+
+
+    current = node;
+    while (current != NULL) {
+       /*
+        * Cleanup children empty nodes if asked for
+        */
+       if ((IS_XSLT_REAL_NODE(current)) &&
+           (current->children != NULL) &&
+           (xsltFindElemSpaceHandling(ctxt, current))) {
+           xmlNodePtr delete = NULL, cur = current->children;
+
+           while (cur != NULL) {
+               if (IS_BLANK_NODE(cur))
+                   delete = cur;
+               
+               cur = cur->next;
+               if (delete != NULL) {
+                   xmlUnlinkNode(delete);
+                   xmlFreeNode(delete);
+                   delete = NULL;
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   nb++;
+#endif
+               }
+           }
+       }
+
+       /*
+        * Skip to next node in document order.
+        */
+       if (node->type == XML_ENTITY_REF_NODE) {
+           /* process deep in entities */
+           xsltApplyStripSpaces(ctxt, node->children);
+       }
+       if ((current->children != NULL) &&
+            (current->type != XML_ENTITY_REF_NODE)) {
+           current = current->children;
+       } else if (current->next != NULL) {
+           current = current->next;
+       } else {
+           do {
+               current = current->parent;
+               if (current == NULL)
+                   break;
+               if (current == node)
+                   goto done;
+               if (current->next != NULL) {
+                   current = current->next;
+                   break;
+               }
+           } while (current != NULL);
+       }
+    }
+
+done:
+#ifdef WITH_XSLT_DEBUG_PROCESS
+    XSLT_TRACE(ctxt,XSLT_TRACE_STRIP_SPACES,xsltGenericDebug(xsltGenericDebugContext,
+            "xsltApplyStripSpaces: removed %d ignorable blank node\n", nb));
+#endif
+    return;
+}
+
+#ifdef XSLT_REFACTORED_KEYCOMP
+static int
+xsltCountKeys(xsltTransformContextPtr ctxt)
+{
+    xsltStylesheetPtr style;
+    xsltKeyDefPtr keyd;
+
+    if (ctxt == NULL)
+       return(-1);    
+
+    /*
+    * Do we have those nastly templates with a key() in the match pattern?
+    */
+    ctxt->hasTemplKeyPatterns = 0;
+    style = ctxt->style;
+    while (style != NULL) {
+       if (style->keyMatch != NULL) {
+           ctxt->hasTemplKeyPatterns = 1;
+           break;
+       }
+       style = xsltNextImport(style);
+    }
+    /*
+    * Count number of key declarations.
+    */
+    ctxt->nbKeys = 0;
+    style = ctxt->style;
+    while (style != NULL) {
+       keyd = style->keys;
+       while (keyd) {
+           ctxt->nbKeys++;
+           keyd = keyd->next;
+       }
+       style = xsltNextImport(style);
+    }        
+    return(ctxt->nbKeys);
+}
+#endif /* XSLT_REFACTORED_KEYCOMP */
+
+/**
+ * xsltApplyStylesheetInternal:
+ * @style:  a parsed XSLT stylesheet
+ * @doc:  a parsed XML document
+ * @params:  a NULL terminated array of parameters names/values tuples
+ * @output:  the targetted output
+ * @profile:  profile FILE * output or NULL
+ * @user:  user provided parameter
+ *
+ * Apply the stylesheet to the document
+ * NOTE: This may lead to a non-wellformed output XML wise !
+ *
+ * Returns the result document or NULL in case of error
+ */
+static xmlDocPtr
+xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc,
+                            const char **params, const char *output,
+                            FILE * profile, xsltTransformContextPtr userCtxt)
+{
+    xmlDocPtr res = NULL;
+    xsltTransformContextPtr ctxt = NULL;
+    xmlNodePtr root, node;
+    const xmlChar *method;
+    const xmlChar *doctypePublic;
+    const xmlChar *doctypeSystem;
+    const xmlChar *version;
+    xsltStackElemPtr variables;
+    xsltStackElemPtr vptr;
+
+    if ((style == NULL) || (doc == NULL))
+        return (NULL);
+
+    if (style->internalized == 0) {
+#ifdef WITH_XSLT_DEBUG
+       xsltGenericDebug(xsltGenericDebugContext,
+                        "Stylesheet was not fully internalized !\n");
+#endif
+    }
+    if (doc->intSubset != NULL) {
+       /*
+        * Avoid hitting the DTD when scanning nodes
+        * but keep it linked as doc->intSubset
+        */
+       xmlNodePtr cur = (xmlNodePtr) doc->intSubset;
+       if (cur->next != NULL)
+           cur->next->prev = cur->prev;
+       if (cur->prev != NULL)
+           cur->prev->next = cur->next;
+       if (doc->children == cur)
+           doc->children = cur->next;
+       if (doc->last == cur)
+           doc->last = cur->prev;
+       cur->prev = cur->next = NULL;
+    }
+
+    /*
+     * Check for XPath document order availability
+     */
+    root = xmlDocGetRootElement(doc);
+    if (root != NULL) {
+       if (((long) root->content) >= 0 && (xslDebugStatus == XSLT_DEBUG_NONE))
+           xmlXPathOrderDocElems(doc);
+    }
+
+    if (userCtxt != NULL)
+       ctxt = userCtxt;
+    else
+       ctxt = xsltNewTransformContext(style, doc);
+
+    if (ctxt == NULL)
+        return (NULL);
+
+    ctxt->initialContextDoc = doc;
+    ctxt->initialContextNode = (xmlNodePtr) doc;
+
+    if (profile != NULL)
+        ctxt->profile = 1;
+
+    if (output != NULL)
+        ctxt->outputFile = output;
+    else
+        ctxt->outputFile = NULL;
+
+    /*
+     * internalize the modes if needed
+     */
+    if (ctxt->dict != NULL) {
+        if (ctxt->mode != NULL)
+           ctxt->mode = xmlDictLookup(ctxt->dict, ctxt->mode, -1);
+        if (ctxt->modeURI != NULL)
+           ctxt->modeURI = xmlDictLookup(ctxt->dict, ctxt->modeURI, -1);
+    }
+
+    XSLT_GET_IMPORT_PTR(method, style, method)
+    XSLT_GET_IMPORT_PTR(doctypePublic, style, doctypePublic)
+    XSLT_GET_IMPORT_PTR(doctypeSystem, style, doctypeSystem)
+    XSLT_GET_IMPORT_PTR(version, style, version)
+
+    if ((method != NULL) &&
+       (!xmlStrEqual(method, (const xmlChar *) "xml")))
+    {
+        if (xmlStrEqual(method, (const xmlChar *) "html")) {
+            ctxt->type = XSLT_OUTPUT_HTML;
+            if (((doctypePublic != NULL) || (doctypeSystem != NULL))) {
+                res = htmlNewDoc(doctypeSystem, doctypePublic);
+           } else {
+                if (version == NULL) {
+                   xmlDtdPtr dtd;
+                   
+                   res = htmlNewDoc(NULL, NULL);
+                   /*
+                   * Make sure no DTD node is generated in this case
+                   */
+                   if (res != NULL) {
+                       dtd = xmlGetIntSubset(res);
+                       if (dtd != NULL) {
+                           xmlUnlinkNode((xmlNodePtr) dtd);
+                           xmlFreeDtd(dtd);
+                       }
+                       res->intSubset = NULL;
+                       res->extSubset = NULL;
+                   }
+               } else {
+
+#ifdef XSLT_GENERATE_HTML_DOCTYPE
+                   xsltGetHTMLIDs(version, &doctypePublic, &doctypeSystem);
+#endif
+                   res = htmlNewDoc(doctypeSystem, doctypePublic);
+               }
+            }
+            if (res == NULL)
+                goto error;
+           res->dict = ctxt->dict;
+           xmlDictReference(res->dict);
+
+#ifdef WITH_XSLT_DEBUG
+           xsltGenericDebug(xsltGenericDebugContext,
+               "reusing transformation dict for output\n");
+#endif
+        } else if (xmlStrEqual(method, (const xmlChar *) "xhtml")) {
+           xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
+               "xsltApplyStylesheetInternal: unsupported method xhtml, using html\n",
+               style->method);
+            ctxt->type = XSLT_OUTPUT_HTML;
+            res = htmlNewDoc(doctypeSystem, doctypePublic);
+            if (res == NULL)
+                goto error;
+           res->dict = ctxt->dict;
+           xmlDictReference(res->dict);
+
+#ifdef WITH_XSLT_DEBUG
+           xsltGenericDebug(xsltGenericDebugContext,
+               "reusing transformation dict for output\n");
+#endif
+        } else if (xmlStrEqual(method, (const xmlChar *) "text")) {
+            ctxt->type = XSLT_OUTPUT_TEXT;
+            res = xmlNewDoc(style->version);
+            if (res == NULL)
+                goto error;
+           res->dict = ctxt->dict;
+           xmlDictReference(res->dict);
+
+#ifdef WITH_XSLT_DEBUG
+           xsltGenericDebug(xsltGenericDebugContext,
+               "reusing transformation dict for output\n");
+#endif
+        } else {
+           xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
+               "xsltApplyStylesheetInternal: unsupported method %s\n",
+               style->method);
+            goto error;
+        }
+    } else {
+        ctxt->type = XSLT_OUTPUT_XML;
+        res = xmlNewDoc(style->version);
+        if (res == NULL)
+            goto error;
+       res->dict = ctxt->dict;
+       xmlDictReference(ctxt->dict);
+#ifdef WITH_XSLT_DEBUG
+       xsltGenericDebug(xsltGenericDebugContext,
+                        "reusing transformation dict for output\n");
+#endif
+    }
+    res->charset = XML_CHAR_ENCODING_UTF8;
+    if (style->encoding != NULL)
+        res->encoding = xmlStrdup(style->encoding);
+    variables = style->variables;
+
+    /*
+     * Start the evaluation, evaluate the params, the stylesheets globals
+     * and start by processing the top node.
+     */
+    if (xsltNeedElemSpaceHandling(ctxt))
+       xsltApplyStripSpaces(ctxt, xmlDocGetRootElement(doc));    
+    /*
+    * Evaluate global params and user-provided params.
+    */
+    ctxt->tmpDoc = doc;
+    ctxt->node = (xmlNodePtr) doc;
+    if (ctxt->globalVars == NULL)
+       ctxt->globalVars = xmlHashCreate(20);
+    if (params != NULL) {      
+        xsltEvalUserParams(ctxt, params);
+    }
+    xsltEvalGlobalVariables(ctxt);
+
+#ifdef XSLT_REFACTORED_KEYCOMP    
+    xsltCountKeys(ctxt);
+#endif
+
+    ctxt->tmpDoc = doc;
+    ctxt->node = (xmlNodePtr) doc;
+    ctxt->output = res;
+    ctxt->insert = (xmlNodePtr) res;    
+    ctxt->varsBase = ctxt->varsNr - 1; 
+    
+    ctxt->xpathCtxt->contextSize = 1;
+    ctxt->xpathCtxt->proximityPosition = 1;
+    ctxt->xpathCtxt->node = NULL; /* TODO: Set the context node here? */
+    /*
+    * Start processing the source tree -----------------------------------
+    */
+    xsltProcessOneNode(ctxt, ctxt->node, NULL);
+    /*
+    * Remove all remaining vars from the stack.
+    */
+    xsltLocalVariablePop(ctxt, 0, -2);
+    xsltShutdownCtxtExts(ctxt);
+
+    xsltCleanupTemplates(style); /* TODO: <- style should be read only */
+
+    /*
+     * Now cleanup our variables so stylesheet can be re-used
+     *
+     * TODO: this is not needed anymore global variables are copied
+     *       and not evaluated directly anymore, keep this as a check
+     */
+    if (style->variables != variables) {
+        vptr = style->variables;
+        while (vptr->next != variables)
+            vptr = vptr->next;
+        vptr->next = NULL;
+        xsltFreeStackElemList(style->variables);
+        style->variables = variables;
+    }
+    vptr = style->variables;
+    while (vptr != NULL) {
+        if (vptr->computed) {
+            if (vptr->value != NULL) {
+                xmlXPathFreeObject(vptr->value);
+                vptr->value = NULL;
+                vptr->computed = 0;
+            }
+        }
+        vptr = vptr->next;
+    }
+    /*
+    * Free all remaining tree fragments.
+    */
+    xsltFreeRVTs(ctxt);
+    /*
+     * Do some post processing work depending on the generated output
+     */
+    root = xmlDocGetRootElement(res);
+    if (root != NULL) {
+        const xmlChar *doctype = NULL;
+
+        if ((root->ns != NULL) && (root->ns->prefix != NULL))
+           doctype = xmlDictQLookup(ctxt->dict, root->ns->prefix, root->name);
+       if (doctype == NULL)
+           doctype = root->name;
+
+        /*
+         * Apply the default selection of the method
+         */
+        if ((method == NULL) &&
+            (root->ns == NULL) &&
+            (!xmlStrcasecmp(root->name, (const xmlChar *) "html"))) {
+            xmlNodePtr tmp;
+
+            tmp = res->children;
+            while ((tmp != NULL) && (tmp != root)) {
+                if (tmp->type == XML_ELEMENT_NODE)
+                    break;
+                if ((tmp->type == XML_TEXT_NODE) && (!xmlIsBlankNode(tmp)))
+                    break;
+               tmp = tmp->next;
+            }
+            if (tmp == root) {
+                ctxt->type = XSLT_OUTPUT_HTML;
+               /*
+               * REVISIT TODO: XML_HTML_DOCUMENT_NODE is set after the
+               *  transformation on the doc, but functions like
+               */
+                res->type = XML_HTML_DOCUMENT_NODE;
+                if (((doctypePublic != NULL) || (doctypeSystem != NULL))) {
+                    res->intSubset = xmlCreateIntSubset(res, doctype,
+                                                        doctypePublic,
+                                                        doctypeSystem);
+#ifdef XSLT_GENERATE_HTML_DOCTYPE
+               } else if (version != NULL) {
+                    xsltGetHTMLIDs(version, &doctypePublic,
+                                   &doctypeSystem);
+                    if (((doctypePublic != NULL) || (doctypeSystem != NULL)))
+                        res->intSubset =
+                            xmlCreateIntSubset(res, doctype,
+                                               doctypePublic,
+                                               doctypeSystem);
+#endif
+                }
+            }
+
+        }
+        if (ctxt->type == XSLT_OUTPUT_XML) {
+            XSLT_GET_IMPORT_PTR(doctypePublic, style, doctypePublic)
+            XSLT_GET_IMPORT_PTR(doctypeSystem, style, doctypeSystem)
+            if (((doctypePublic != NULL) || (doctypeSystem != NULL))) {
+               xmlNodePtr last;
+               /* Need a small "hack" here to assure DTD comes before
+                  possible comment nodes */
+               node = res->children;
+               last = res->last;
+               res->children = NULL;
+               res->last = NULL;
+                res->intSubset = xmlCreateIntSubset(res, doctype,
+                                                    doctypePublic,
+                                                    doctypeSystem);
+               if (res->children != NULL) {
+                   res->children->next = node;
+                   node->prev = res->children;
+                   res->last = last;
+               } else {
+                   res->children = node;
+                   res->last = last;
+               }
+           }
+        }
+    }
+    xmlXPathFreeNodeSet(ctxt->nodeList);
+    if (profile != NULL) {
+        xsltSaveProfiling(ctxt, profile);
+    }
+
+    /*
+     * Be pedantic.
+     */
+    if ((ctxt != NULL) && (ctxt->state == XSLT_STATE_ERROR)) {
+       xmlFreeDoc(res);
+       res = NULL;
+    }
+    if ((res != NULL) && (ctxt != NULL) && (output != NULL)) {
+       int ret;
+
+       ret = xsltCheckWrite(ctxt->sec, ctxt, (const xmlChar *) output);
+       if (ret == 0) {
+           xsltTransformError(ctxt, NULL, NULL,
+                    "xsltApplyStylesheet: forbidden to save to %s\n",
+                              output);
+       } else if (ret < 0) {
+           xsltTransformError(ctxt, NULL, NULL,
+                    "xsltApplyStylesheet: saving to %s may not be possible\n",
+                              output);
+       }
+    }
+
+#ifdef XSLT_DEBUG_PROFILE_CACHE
+    printf("# Cache:\n");
+    printf("# Reused tree fragments: %d\n", ctxt->cache->dbgReusedRVTs);
+    printf("# Reused variables     : %d\n", ctxt->cache->dbgReusedVars);
+#endif
+
+    if ((ctxt != NULL) && (userCtxt == NULL))
+       xsltFreeTransformContext(ctxt);
+
+    return (res);
+
+error:
+    if (res != NULL)
+        xmlFreeDoc(res);
+
+#ifdef XSLT_DEBUG_PROFILE_CACHE
+    printf("# Cache:\n");
+    printf("# Reused tree fragments: %d\n", ctxt->cache->dbgReusedRVTs);
+    printf("# Reused variables     : %d\n", ctxt->cache->dbgReusedVars);
+#endif
+
+    if ((ctxt != NULL) && (userCtxt == NULL))
+        xsltFreeTransformContext(ctxt);
+    return (NULL);
+}
+
+/**
+ * xsltApplyStylesheet:
+ * @style:  a parsed XSLT stylesheet
+ * @doc:  a parsed XML document
+ * @params:  a NULL terminated arry of parameters names/values tuples
+ *
+ * Apply the stylesheet to the document
+ * NOTE: This may lead to a non-wellformed output XML wise !
+ *
+ * Returns the result document or NULL in case of error
+ */
+xmlDocPtr
+xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc,
+                    const char **params)
+{
+    return (xsltApplyStylesheetInternal(style, doc, params, NULL, NULL, NULL));
+}
+
+/**
+ * xsltProfileStylesheet:
+ * @style:  a parsed XSLT stylesheet
+ * @doc:  a parsed XML document
+ * @params:  a NULL terminated arry of parameters names/values tuples
+ * @output:  a FILE * for the profiling output
+ *
+ * Apply the stylesheet to the document and dump the profiling to
+ * the given output.
+ *
+ * Returns the result document or NULL in case of error
+ */
+xmlDocPtr
+xsltProfileStylesheet(xsltStylesheetPtr style, xmlDocPtr doc,
+                      const char **params, FILE * output)
+{
+    xmlDocPtr res;
+
+    res = xsltApplyStylesheetInternal(style, doc, params, NULL, output, NULL);
+    return (res);
+}
+
+/**
+ * xsltApplyStylesheetUser:
+ * @style:  a parsed XSLT stylesheet
+ * @doc:  a parsed XML document
+ * @params:  a NULL terminated array of parameters names/values tuples
+ * @output:  the targetted output
+ * @profile:  profile FILE * output or NULL
+ * @userCtxt:  user provided transform context
+ *
+ * Apply the stylesheet to the document and allow the user to provide
+ * its own transformation context.
+ *
+ * Returns the result document or NULL in case of error
+ */
+xmlDocPtr
+xsltApplyStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc,
+                            const char **params, const char *output,
+                            FILE * profile, xsltTransformContextPtr userCtxt)
+{
+    xmlDocPtr res;
+
+    res = xsltApplyStylesheetInternal(style, doc, params, output,
+                                     profile, userCtxt);
+    return (res);
+}
+
+/**
+ * xsltRunStylesheetUser:
+ * @style:  a parsed XSLT stylesheet
+ * @doc:  a parsed XML document
+ * @params:  a NULL terminated array of parameters names/values tuples
+ * @output:  the URL/filename ot the generated resource if available
+ * @SAX:  a SAX handler for progressive callback output (not implemented yet)
+ * @IObuf:  an output buffer for progressive output (not implemented yet)
+ * @profile:  profile FILE * output or NULL
+ * @userCtxt:  user provided transform context
+ *
+ * Apply the stylesheet to the document and generate the output according
+ * to @output @SAX and @IObuf. It's an error to specify both @SAX and @IObuf.
+ *
+ * NOTE: This may lead to a non-wellformed output XML wise !
+ * NOTE: This may also result in multiple files being generated
+ * NOTE: using IObuf, the result encoding used will be the one used for
+ *       creating the output buffer, use the following macro to read it
+ *       from the stylesheet
+ *       XSLT_GET_IMPORT_PTR(encoding, style, encoding)
+ * NOTE: using SAX, any encoding specified in the stylesheet will be lost
+ *       since the interface uses only UTF8
+ *
+ * Returns the number of by written to the main resource or -1 in case of
+ *         error.
+ */
+int
+xsltRunStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc,
+                  const char **params, const char *output,
+                  xmlSAXHandlerPtr SAX, xmlOutputBufferPtr IObuf,
+                 FILE * profile, xsltTransformContextPtr userCtxt)
+{
+    xmlDocPtr tmp;
+    int ret;
+
+    if ((output == NULL) && (SAX == NULL) && (IObuf == NULL))
+        return (-1);
+    if ((SAX != NULL) && (IObuf != NULL))
+        return (-1);
+
+    /* unsupported yet */
+    if (SAX != NULL) {
+        XSLT_TODO   /* xsltRunStylesheet xmlSAXHandlerPtr SAX */
+       return (-1);
+    }
+
+    tmp = xsltApplyStylesheetInternal(style, doc, params, output, profile,
+                                     userCtxt);
+    if (tmp == NULL) {
+       xsltTransformError(NULL, NULL, (xmlNodePtr) doc,
+                         "xsltRunStylesheet : run failed\n");
+        return (-1);
+    }
+    if (IObuf != NULL) {
+        /* TODO: incomplete, IObuf output not progressive */
+        ret = xsltSaveResultTo(IObuf, tmp, style);
+    } else {
+        ret = xsltSaveResultToFilename(output, tmp, style, 0);
+    }
+    xmlFreeDoc(tmp);
+    return (ret);
+}
+
+/**
+ * xsltRunStylesheet:
+ * @style:  a parsed XSLT stylesheet
+ * @doc:  a parsed XML document
+ * @params:  a NULL terminated array of parameters names/values tuples
+ * @output:  the URL/filename ot the generated resource if available
+ * @SAX:  a SAX handler for progressive callback output (not implemented yet)
+ * @IObuf:  an output buffer for progressive output (not implemented yet)
+ *
+ * Apply the stylesheet to the document and generate the output according
+ * to @output @SAX and @IObuf. It's an error to specify both @SAX and @IObuf.
+ *
+ * NOTE: This may lead to a non-wellformed output XML wise !
+ * NOTE: This may also result in multiple files being generated
+ * NOTE: using IObuf, the result encoding used will be the one used for
+ *       creating the output buffer, use the following macro to read it
+ *       from the stylesheet
+ *       XSLT_GET_IMPORT_PTR(encoding, style, encoding)
+ * NOTE: using SAX, any encoding specified in the stylesheet will be lost
+ *       since the interface uses only UTF8
+ *
+ * Returns the number of bytes written to the main resource or -1 in case of
+ *         error.
+ */
+int
+xsltRunStylesheet(xsltStylesheetPtr style, xmlDocPtr doc,
+                  const char **params, const char *output,
+                  xmlSAXHandlerPtr SAX, xmlOutputBufferPtr IObuf)
+{
+    return(xsltRunStylesheetUser(style, doc, params, output, SAX, IObuf,
+                                NULL, NULL));
+}
+
+/**
+ * xsltRegisterAllElement:
+ * @ctxt:  the XPath context
+ *
+ * Registers all default XSLT elements in this context
+ */
+void
+xsltRegisterAllElement(xsltTransformContextPtr ctxt)
+{
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "apply-templates",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltApplyTemplates);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "apply-imports",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltApplyImports);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "call-template",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltCallTemplate);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "element",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltElement);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "attribute",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltAttribute);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "text",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltText);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "processing-instruction",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltProcessingInstruction);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "comment",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltComment);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "copy",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltCopy);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "value-of",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltValueOf);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "number",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltNumber);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "for-each",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltForEach);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "if",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltIf);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "choose",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltChoose);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "sort",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltSort);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "copy-of",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltCopyOf);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "message",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltMessage);
+
+    /*
+     * Those don't have callable entry points but are registered anyway
+     */
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "variable",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltDebug);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "param",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltDebug);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "with-param",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltDebug);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "decimal-format",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltDebug);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "when",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltDebug);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "otherwise",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltDebug);
+    xsltRegisterExtElement(ctxt, (const xmlChar *) "fallback",
+                           XSLT_NAMESPACE,
+                          (xsltTransformFunction) xsltDebug);
+
+}
index 5adb082..9c2075b 100644 (file)
-/*\r
- * variables.c: Implementation of the variable storage and lookup\r
- *\r
- * Reference:\r
- *   http://www.w3.org/TR/1999/REC-xslt-19991116\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * daniel@veillard.com\r
- */\r
-\r
-#define IN_LIBXSLT\r
-#include "libxslt.h"\r
-\r
-#include <string.h>\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/tree.h>\r
-#include <libxml/valid.h>\r
-#include <libxml/hash.h>\r
-#include <libxml/xmlerror.h>\r
-#include <libxml/xpath.h>\r
-#include <libxml/xpathInternals.h>\r
-#include <libxml/parserInternals.h>\r
-#include <libxml/dict.h>\r
-#include "xslt.h"\r
-#include "xsltInternals.h"\r
-#include "xsltutils.h"\r
-#include "variables.h"\r
-#include "transform.h"\r
-#include "imports.h"\r
-#include "preproc.h"\r
-#include "keys.h"\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
- #define WITH_XSLT_DEBUG_VARIABLE\r
-#endif\r
-\r
-#ifdef XSLT_REFACTORED\r
-const xmlChar *xsltDocFragFake = (const xmlChar *) " fake node libxslt";\r
-#endif\r
-\r
-const xmlChar *xsltComputingGlobalVarMarker =\r
- (const xmlChar *) " var/param being computed";\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *  Result Value Tree (Result Tree Fragment) interfaces                        *\r
- *                                                                     *\r
- ************************************************************************/\r
-/**\r
- * xsltCreateRVT:\r
- * @ctxt:  an XSLT transformation context\r
- *\r
- * Creates a Result Value Tree\r
- * (the XSLT 1.0 term for this is "Result Tree Fragment") \r
- *\r
- * Returns the result value tree or NULL in case of API or internal errors.\r
- */\r
-xmlDocPtr\r
-xsltCreateRVT(xsltTransformContextPtr ctxt)\r
-{\r
-    xmlDocPtr container;\r
-\r
-    /*\r
-    * Question: Why is this function public?\r
-    * Answer: It is called by the EXSLT module.\r
-    */    \r
-    if (ctxt == NULL)\r
-       return(NULL);\r
-\r
-    /*\r
-    * Reuse a RTF from the cache if available.\r
-    */\r
-    if (ctxt->cache->RVT) {\r
-       container = ctxt->cache->RVT;\r
-       ctxt->cache->RVT = (xmlDocPtr) container->next;\r
-       container->next = NULL;\r
-       if (ctxt->cache->nbRVT > 0)\r
-           ctxt->cache->nbRVT--;\r
-#ifdef XSLT_DEBUG_PROFILE_CACHE\r
-       ctxt->cache->dbgReusedRVTs++;\r
-#endif\r
-       return(container);\r
-    }\r
-\r
-    container = xmlNewDoc(NULL);\r
-    if (container == NULL)\r
-       return(NULL);\r
-    container->dict = ctxt->dict;\r
-    xmlDictReference(container->dict);\r
-    XSLT_MARK_RES_TREE_FRAG(container);\r
-    container->doc = container;\r
-    container->parent = NULL;\r
-    return(container);\r
-}\r
-\r
-/**\r
- * xsltRegisterTmpRVT:\r
- * @ctxt:  an XSLT transformation context\r
- * @RVT:  a result value tree (Result Tree Fragment)\r
- *\r
- * Registers the result value tree (XSLT 1.0 term: Result Tree Fragment)\r
- * in the garbage collector.\r
- * The fragment will be freed at the exit of the currently\r
- * instantiated xsl:template.\r
- * Obsolete; this function might produce massive memory overhead,\r
- * since the fragment is only freed when the current xsl:template\r
- * exits. Use xsltRegisterLocalRVT() instead.\r
- *\r
- * Returns 0 in case of success and -1 in case of API or internal errors.\r
- */\r
-int\r
-xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)\r
-{\r
-    if ((ctxt == NULL) || (RVT == NULL))\r
-       return(-1);\r
-\r
-    /*\r
-    * We'll restrict the lifetime of user-created fragments\r
-    * insinde an xsl:variable and xsl:param to the lifetime of the\r
-    * var/param itself.\r
-    */\r
-    if (ctxt->contextVariable != NULL) {\r
-       RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;\r
-       XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;\r
-       return(0);\r
-    }\r
-\r
-    RVT->next = (xmlNodePtr) ctxt->tmpRVT;\r
-    if (ctxt->tmpRVT != NULL)\r
-       ctxt->tmpRVT->prev = (xmlNodePtr) RVT;\r
-    ctxt->tmpRVT = RVT;\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltRegisterLocalRVT:\r
- * @ctxt:  an XSLT transformation context\r
- * @RVT:  a result value tree (Result Tree Fragment; xmlDocPtr)\r
- *\r
- * Registers a result value tree (XSLT 1.0 term: Result Tree Fragment)\r
- * in the RVT garbage collector.\r
- * The fragment will be freed when the instruction which created the\r
- * fragment exits.\r
- *\r
- * Returns 0 in case of success and -1 in case of API or internal errors.\r
- */\r
-int\r
-xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,\r
-                    xmlDocPtr RVT)\r
-{\r
-    if ((ctxt == NULL) || (RVT == NULL))\r
-       return(-1);\r
-    \r
-    /*\r
-    * When evaluating "select" expressions of xsl:variable\r
-    * and xsl:param, we need to bind newly created tree fragments\r
-    * to the variable itself; otherwise the tragment will be\r
-    * freed before we leave the scope of a var.\r
-    */\r
-    if ((ctxt->contextVariable != NULL) &&\r
-       (XSLT_TCTXT_VARIABLE(ctxt)->flags & XSLT_VAR_IN_SELECT))\r
-    {\r
-       RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;\r
-       XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;\r
-       return(0);\r
-    }\r
-    /*\r
-    * Store the fragment in the scope of the current instruction.\r
-    * If not reference by a returning instruction (like EXSLT's function),\r
-    * then this fragment will be freed, when the instruction exits.\r
-    */\r
-    RVT->next = (xmlNodePtr) ctxt->localRVT;\r
-    if (ctxt->localRVT != NULL)\r
-       ctxt->localRVT->prev = (xmlNodePtr) RVT;\r
-    ctxt->localRVT = RVT;\r
-    /*\r
-    * We need to keep track of the first registered fragment\r
-    * for extension instructions which return fragments\r
-    * (e.g. EXSLT'S function), in order to let\r
-    * xsltExtensionInstructionResultFinalize() clear the\r
-    * preserving flag on the fragments.\r
-    */\r
-    if (ctxt->localRVTBase == NULL)\r
-       ctxt->localRVTBase = RVT;\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltExtensionInstructionResultFinalize:\r
- * @ctxt:  an XSLT transformation context\r
- *\r
- * Finalizes the data (e.g. result tree fragments) created\r
- * within a value-returning process (e.g. EXSLT's function).\r
- * Tree fragments marked as being returned by a function are\r
- * set to normal state, which means that the fragment garbage\r
- * collector will free them after the function-calling process exits.\r
- *\r
- * Returns 0 in case of success and -1 in case of API or internal errors.\r
- */\r
-int\r
-xsltExtensionInstructionResultFinalize(xsltTransformContextPtr ctxt)\r
-{\r
-    xmlDocPtr cur;\r
-\r
-    if (ctxt == NULL)\r
-       return(-1);\r
-    if (ctxt->localRVTBase == NULL)\r
-       return(0);\r
-    /*\r
-    * Enable remaining local tree fragments to be freed\r
-    * by the fragment garbage collector.\r
-    */\r
-    cur = ctxt->localRVTBase;\r
-    do {\r
-       cur->psvi = NULL;\r
-       cur = (xmlDocPtr) cur->next;\r
-    } while (cur != NULL);\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltExtensionInstructionResultRegister:\r
- * @ctxt: an XSLT transformation context\r
- * @nodeSet: a node set to be inspected for result tree fragments\r
- *\r
- * Marks the result of a value-returning extension instruction\r
- * in order to avoid it being garbage collected before the\r
- * extension instruction exits.\r
- * Note that one still has to additionally register any newly created\r
- * tree fragments (via xsltCreateRVT()) with xsltRegisterLocalRVT().\r
- *\r
- * Returns 0 in case of success and -1 in case of error.\r
- */\r
-int\r
-xsltExtensionInstructionResultRegister(xsltTransformContextPtr ctxt,\r
-                                      xmlXPathObjectPtr obj)\r
-{\r
-    int i;\r
-    xmlNodePtr cur;\r
-    xmlDocPtr doc;\r
-\r
-    if ((ctxt == NULL) || (obj == NULL))\r
-       return(-1);\r
-\r
-    /*\r
-    * OPTIMIZE TODO: If no local variables/params and no local tree\r
-    * fragments were created, then we don't need to analyse the XPath\r
-    * objects for tree fragments.\r
-    */\r
-\r
-    if ((obj->type != XPATH_NODESET) && (obj->type != XPATH_XSLT_TREE))\r
-       return(0);\r
-    if ((obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0))\r
-       return(0);\r
-\r
-    for (i = 0; i < obj->nodesetval->nodeNr; i++) {\r
-       cur = obj->nodesetval->nodeTab[i];\r
-       if (cur->type == XML_NAMESPACE_DECL) {\r
-           /*\r
-           * The XPath module sets the owner element of a ns-node on\r
-           * the ns->next field.\r
-           */\r
-           if ((((xmlNsPtr) cur)->next != NULL) &&\r
-               (((xmlNsPtr) cur)->next->type == XML_ELEMENT_NODE))\r
-           {\r
-               cur = (xmlNodePtr) ((xmlNsPtr) cur)->next;\r
-               doc = cur->doc; \r
-           } else {\r
-               xsltTransformError(ctxt, NULL, ctxt->inst,\r
-                   "Internal error in "\r
-                   "xsltExtensionInstructionResultRegister(): "\r
-                   "Cannot retrieve the doc of a namespace node.\n");\r
-               goto error;\r
-           }\r
-       } else {\r
-           doc = cur->doc;\r
-       }\r
-       if (doc == NULL) {\r
-           xsltTransformError(ctxt, NULL, ctxt->inst,\r
-               "Internal error in "\r
-               "xsltExtensionInstructionResultRegister(): "\r
-               "Cannot retrieve the doc of a node.\n");\r
-           goto error;\r
-       }\r
-       if (doc->name && (doc->name[0] == ' ')) {\r
-           /*\r
-           * This is a result tree fragment.\r
-           * We'll use the @psvi field for reference counting.\r
-           * TODO: How do we know if this is a value of a\r
-           *  global variable or a doc acquired via the\r
-           *  document() function?\r
-           */\r
-           doc->psvi = (void *) ((long) 1);\r
-       }\r
-    }\r
-\r
-    return(0);\r
-error:\r
-    return(-1);\r
-}\r
-\r
-/**\r
- * xsltReleaseRVT:\r
- * @ctxt:  an XSLT transformation context\r
- * @RVT:  a result value tree (Result Tree Fragment)\r
- *\r
- * Either frees the RVT (which is an xmlDoc) or stores\r
- * it in the context's cache for later reuse.\r
- */\r
-void\r
-xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)\r
-{\r
-    if (RVT == NULL)\r
-       return;\r
-\r
-    if (ctxt && (ctxt->cache->nbRVT < 40)) {\r
-       /*\r
-       * Store the Result Tree Fragment.\r
-       * Free the document info.\r
-       */\r
-       if (RVT->_private != NULL) {\r
-           xsltFreeDocumentKeys((xsltDocumentPtr) RVT->_private);\r
-           xmlFree(RVT->_private);\r
-           RVT->_private = NULL;\r
-       }\r
-       /*\r
-       * Clear the document tree.\r
-       * REVISIT TODO: Do we expect ID/IDREF tables to be existent?    \r
-       */\r
-       if (RVT->children != NULL) {\r
-           xmlFreeNodeList(RVT->children);\r
-           RVT->children = NULL;\r
-           RVT->last = NULL;\r
-       }\r
-       if (RVT->ids != NULL) {\r
-           xmlFreeIDTable((xmlIDTablePtr) RVT->ids);\r
-           RVT->ids = NULL;\r
-       }\r
-       if (RVT->refs != NULL) {\r
-           xmlFreeRefTable((xmlRefTablePtr) RVT->refs);\r
-           RVT->refs = NULL;\r
-       }\r
-\r
-       /*\r
-       * Reset the reference counter.\r
-       */\r
-       RVT->psvi = 0;\r
-\r
-       RVT->next = (xmlNodePtr) ctxt->cache->RVT;\r
-       ctxt->cache->RVT = RVT;\r
-\r
-       ctxt->cache->nbRVT++;\r
-\r
-#ifdef XSLT_DEBUG_PROFILE_CACHE\r
-       ctxt->cache->dbgCachedRVTs++;\r
-#endif\r
-       return;\r
-    }\r
-    /*\r
-    * Free it.\r
-    */\r
-    if (RVT->_private != NULL) {\r
-       xsltFreeDocumentKeys((xsltDocumentPtr) RVT->_private);\r
-       xmlFree(RVT->_private);\r
-    }\r
-    xmlFreeDoc(RVT);\r
-}\r
-\r
-/**\r
- * xsltRegisterPersistRVT:\r
- * @ctxt:  an XSLT transformation context\r
- * @RVT:  a result value tree (Result Tree Fragment)\r
- *\r
- * Register the result value tree (XSLT 1.0 term: Result Tree Fragment)\r
- * in the fragment garbage collector.\r
- * The fragment will be freed when the transformation context is\r
- * freed.\r
- *\r
- * Returns 0 in case of success and -1 in case of error.\r
- */\r
-int\r
-xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)\r
-{\r
-    if ((ctxt == NULL) || (RVT == NULL)) return(-1);\r
-\r
-    RVT->next = (xmlNodePtr) ctxt->persistRVT;\r
-    if (ctxt->persistRVT != NULL)\r
-       ctxt->persistRVT->prev = (xmlNodePtr) RVT;\r
-    ctxt->persistRVT = RVT;\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltFreeRVTs:\r
- * @ctxt:  an XSLT transformation context\r
- *\r
- * Frees all registered result value trees (Result Tree Fragments)\r
- * of the transformation. Internal function; should not be called\r
- * by user-code.\r
- */\r
-void\r
-xsltFreeRVTs(xsltTransformContextPtr ctxt)\r
-{\r
-    xmlDocPtr cur, next;\r
-\r
-    if (ctxt == NULL)\r
-       return;\r
-    /*\r
-    * Local fragments.\r
-    */\r
-    cur = ctxt->localRVT;\r
-    while (cur != NULL) {\r
-        next = (xmlDocPtr) cur->next;\r
-       if (cur->_private != NULL) {\r
-           xsltFreeDocumentKeys(cur->_private);\r
-           xmlFree(cur->_private);\r
-       }\r
-       xmlFreeDoc(cur);\r
-       cur = next;\r
-    }\r
-    ctxt->localRVT = NULL;\r
-    /*\r
-    * User-created per-template fragments.\r
-    */\r
-    cur = ctxt->tmpRVT;\r
-    while (cur != NULL) {\r
-        next = (xmlDocPtr) cur->next;\r
-       if (cur->_private != NULL) {\r
-           xsltFreeDocumentKeys(cur->_private);\r
-           xmlFree(cur->_private);\r
-       }\r
-       xmlFreeDoc(cur);\r
-       cur = next;\r
-    }\r
-    ctxt->tmpRVT = NULL;\r
-    /*\r
-    * Global fragments.\r
-    */\r
-    cur = ctxt->persistRVT;\r
-    while (cur != NULL) {\r
-        next = (xmlDocPtr) cur->next;\r
-       if (cur->_private != NULL) {\r
-           xsltFreeDocumentKeys(cur->_private);\r
-           xmlFree(cur->_private);\r
-       }\r
-       xmlFreeDoc(cur);\r
-       cur = next;\r
-    }\r
-    ctxt->persistRVT = NULL;\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Module interfaces                               *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltNewStackElem:\r
- *\r
- * Create a new XSLT ParserContext\r
- *\r
- * Returns the newly allocated xsltParserStackElem or NULL in case of error\r
- */\r
-static xsltStackElemPtr\r
-xsltNewStackElem(xsltTransformContextPtr ctxt)\r
-{\r
-    xsltStackElemPtr ret;\r
-    /*\r
-    * Reuse a stack item from the cache if available.\r
-    */\r
-    if (ctxt && ctxt->cache->stackItems) {\r
-       ret = ctxt->cache->stackItems;\r
-       ctxt->cache->stackItems = ret->next;\r
-       ret->next = NULL;\r
-       ctxt->cache->nbStackItems--;\r
-#ifdef XSLT_DEBUG_PROFILE_CACHE\r
-       ctxt->cache->dbgReusedVars++;\r
-#endif\r
-       return(ret);\r
-    }\r
-    ret = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));\r
-    if (ret == NULL) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-               "xsltNewStackElem : malloc failed\n");\r
-       return(NULL);\r
-    }\r
-    memset(ret, 0, sizeof(xsltStackElem));\r
-    ret->context = ctxt;\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltCopyStackElem:\r
- * @elem:  an XSLT stack element\r
- *\r
- * Makes a copy of the stack element\r
- *\r
- * Returns the copy of NULL\r
- */\r
-static xsltStackElemPtr\r
-xsltCopyStackElem(xsltStackElemPtr elem) {\r
-    xsltStackElemPtr cur;\r
-\r
-    cur = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));\r
-    if (cur == NULL) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-               "xsltCopyStackElem : malloc failed\n");\r
-       return(NULL);\r
-    }\r
-    memset(cur, 0, sizeof(xsltStackElem));\r
-    cur->context = elem->context;\r
-    cur->name = elem->name;\r
-    cur->nameURI = elem->nameURI;\r
-    cur->select = elem->select;\r
-    cur->tree = elem->tree;\r
-    cur->comp = elem->comp;    \r
-    return(cur);\r
-}\r
-\r
-/**\r
- * xsltFreeStackElem:\r
- * @elem:  an XSLT stack element\r
- *\r
- * Free up the memory allocated by @elem\r
- */\r
-static void\r
-xsltFreeStackElem(xsltStackElemPtr elem) {\r
-    if (elem == NULL)\r
-       return;\r
-    if (elem->value != NULL)\r
-       xmlXPathFreeObject(elem->value);\r
-    /*\r
-    * Release the list of temporary Result Tree Fragments.\r
-    */\r
-    if (elem->fragment) {\r
-       xmlDocPtr cur;\r
-\r
-       while (elem->fragment != NULL) {\r
-           cur = elem->fragment;\r
-           elem->fragment = (xmlDocPtr) cur->next;\r
-\r
-           if (elem->context &&\r
-               (cur->psvi == (void *) ((long) 1)))\r
-           {\r
-               /*\r
-               * This fragment is a result of an extension instruction\r
-               * (e.g. XSLT's function) and needs to be preserved until\r
-               * the instruction exits.\r
-               * Example: The fragment of the variable must not be freed\r
-               *  since it is returned by the EXSLT function:\r
-               *  <f:function name="foo">\r
-               *   <xsl:variable name="bar">\r
-               *     <bar/>\r
-               *   </xsl:variable>\r
-               *   <f:result select="$bar"/>\r
-               *  </f:function>\r
-               * \r
-               */\r
-               xsltRegisterLocalRVT(elem->context, cur);\r
-           } else {\r
-               xsltReleaseRVT((xsltTransformContextPtr) elem->context,\r
-                   cur);\r
-           }       \r
-       }\r
-    }\r
-    /*\r
-    * Cache or free the variable structure.\r
-    */\r
-    if (elem->context && (elem->context->cache->nbStackItems < 50)) {\r
-       /*\r
-       * Store the item in the cache.\r
-       */\r
-       xsltTransformContextPtr ctxt = elem->context;\r
-       memset(elem, 0, sizeof(xsltStackElem));\r
-       elem->context = ctxt;\r
-       elem->next = ctxt->cache->stackItems;\r
-       ctxt->cache->stackItems = elem; \r
-       ctxt->cache->nbStackItems++;\r
-#ifdef XSLT_DEBUG_PROFILE_CACHE\r
-       ctxt->cache->dbgCachedVars++;\r
-#endif\r
-       return;\r
-    }\r
-    xmlFree(elem);\r
-}\r
-\r
-/**\r
- * xsltFreeStackElemList:\r
- * @elem:  an XSLT stack element\r
- *\r
- * Free up the memory allocated by @elem\r
- */\r
-void\r
-xsltFreeStackElemList(xsltStackElemPtr elem) {\r
-    xsltStackElemPtr next;\r
-    \r
-    while (elem != NULL) {\r
-       next = elem->next;\r
-       xsltFreeStackElem(elem);\r
-       elem = next;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltStackLookup:\r
- * @ctxt:  an XSLT transformation context\r
- * @name:  the local part of the name\r
- * @nameURI:  the URI part of the name\r
- *\r
- * Locate an element in the stack based on its name.\r
- */\r
-#if 0 /* TODO: Those seem to have been used for debugging. */\r
-static int stack_addr = 0;\r
-static int stack_cmp = 0;\r
-#endif\r
-\r
-static xsltStackElemPtr\r
-xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,\r
-               const xmlChar *nameURI) {\r
-    int i;\r
-    xsltStackElemPtr cur;\r
-\r
-    if ((ctxt == NULL) || (name == NULL) || (ctxt->varsNr == 0))\r
-       return(NULL);\r
-\r
-    /*\r
-     * Do the lookup from the top of the stack, but\r
-     * don't use params being computed in a call-param\r
-     * First lookup expects the variable name and URI to\r
-     * come from the disctionnary and hence pointer comparison.\r
-     */\r
-    for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {\r
-       cur = ctxt->varsTab[i-1];\r
-       while (cur != NULL) {\r
-           if ((cur->name == name) && (cur->nameURI == nameURI)) {\r
-#if 0\r
-               stack_addr++;\r
-#endif\r
-               return(cur);\r
-           }\r
-           cur = cur->next;\r
-       }\r
-    }\r
-\r
-    /*\r
-     * Redo the lookup with interned string compares\r
-     * to avoid string compares.\r
-     */\r
-    name = xmlDictLookup(ctxt->dict, name, -1);\r
-    if (nameURI != NULL)\r
-        nameURI = xmlDictLookup(ctxt->dict, nameURI, -1);\r
-\r
-    for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {\r
-       cur = ctxt->varsTab[i-1];\r
-       while (cur != NULL) {\r
-           if ((cur->name == name) && (cur->nameURI == nameURI)) {\r
-#if 0\r
-               stack_cmp++;\r
-#endif\r
-               return(cur);\r
-           }\r
-           cur = cur->next;\r
-       }\r
-    }\r
-\r
-    return(NULL);\r
-}\r
-\r
-/**\r
- * xsltCheckStackElem:\r
- * @ctxt:  xn XSLT transformation context\r
- * @name:  the variable name\r
- * @nameURI:  the variable namespace URI\r
- *\r
- * Checks whether a variable or param is already defined.\r
- *\r
- * URGENT TODO: Checks for redefinition of vars/params should be\r
- *  done only at compilation time.\r
- *\r
- * Returns 1 if variable is present, 2 if param is present, 3 if this\r
- *         is an inherited param, 0 if not found, -1 in case of failure.\r
- */\r
-static int\r
-xsltCheckStackElem(xsltTransformContextPtr ctxt, const xmlChar *name,\r
-                  const xmlChar *nameURI) {\r
-    xsltStackElemPtr cur;\r
-\r
-    if ((ctxt == NULL) || (name == NULL))\r
-       return(-1);\r
-\r
-    cur = xsltStackLookup(ctxt, name, nameURI);\r
-    if (cur == NULL)\r
-        return(0);\r
-    if (cur->comp != NULL) {\r
-        if (cur->comp->type == XSLT_FUNC_WITHPARAM)\r
-           return(3);\r
-       else if (cur->comp->type == XSLT_FUNC_PARAM)\r
-           return(2);\r
-    }\r
-    \r
-    return(1);\r
-}\r
-\r
-/**\r
- * xsltAddStackElem:\r
- * @ctxt:  xn XSLT transformation context\r
- * @elem:  a stack element\r
- *\r
- * Push an element (or list) onto the stack.\r
- * In case of a list, each member will be pushed into\r
- * a seperate slot; i.e. there's always 1 stack entry for\r
- * 1 stack element.\r
- *\r
- * Returns 0 in case of success, -1 in case of failure.\r
- */\r
-static int\r
-xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem)\r
-{\r
-    if ((ctxt == NULL) || (elem == NULL))\r
-       return(-1);\r
-\r
-    do {\r
-       if (ctxt->varsMax == 0) {\r
-           ctxt->varsMax = 10;\r
-           ctxt->varsTab =\r
-               (xsltStackElemPtr *) xmlMalloc(ctxt->varsMax *\r
-               sizeof(ctxt->varsTab[0]));\r
-           if (ctxt->varsTab == NULL) {\r
-               xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");\r
-               return (-1);\r
-           }\r
-       }\r
-       if (ctxt->varsNr >= ctxt->varsMax) {\r
-           ctxt->varsMax *= 2;\r
-           ctxt->varsTab =\r
-               (xsltStackElemPtr *) xmlRealloc(ctxt->varsTab,\r
-               ctxt->varsMax *\r
-               sizeof(ctxt->varsTab[0]));\r
-           if (ctxt->varsTab == NULL) {\r
-               xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");\r
-               return (-1);\r
-           }\r
-       }\r
-       ctxt->varsTab[ctxt->varsNr++] = elem;\r
-       ctxt->vars = elem;\r
-       \r
-       elem = elem->next;\r
-    } while (elem != NULL);\r
-    \r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltAddStackElemList:\r
- * @ctxt:  xn XSLT transformation context\r
- * @elems:  a stack element list\r
- *\r
- * Push an element list onto the stack.\r
- *\r
- * Returns 0 in case of success, -1 in case of failure.\r
- */\r
-int\r
-xsltAddStackElemList(xsltTransformContextPtr ctxt, xsltStackElemPtr elems)\r
-{\r
-    return(xsltAddStackElem(ctxt, elems));\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Module interfaces                               *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltEvalVariable:\r
- * @ctxt:  the XSLT transformation context\r
- * @variable:  the variable or parameter item\r
- * @comp: the compiled XSLT instruction\r
- *\r
- * Evaluate a variable value.\r
- *\r
- * Returns the XPath Object value or NULL in case of error\r
- */\r
-static xmlXPathObjectPtr\r
-xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable,\r
-                xsltStylePreCompPtr castedComp)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemVariablePtr comp =\r
-       (xsltStyleItemVariablePtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif   \r
-    xmlXPathObjectPtr result = NULL;\r
-    xmlNodePtr oldInst;\r
-\r
-    if ((ctxt == NULL) || (variable == NULL))\r
-       return(NULL);\r
-\r
-    /*\r
-    * A variable or parameter are evaluated on demand; thus the\r
-    * context (of XSLT and XPath) need to be temporarily adjusted and\r
-    * restored on exit.\r
-    */\r
-    oldInst = ctxt->inst;\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-       "Evaluating variable '%s'\n", variable->name));\r
-#endif\r
-    if (variable->select != NULL) {\r
-       xmlXPathCompExprPtr xpExpr = NULL;\r
-       xmlDocPtr oldXPDoc;\r
-       xmlNodePtr oldXPContextNode;\r
-       int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;\r
-       xmlNsPtr *oldXPNamespaces;\r
-       xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;\r
-       xsltStackElemPtr oldVar = ctxt->contextVariable;\r
-\r
-       if ((comp != NULL) && (comp->comp != NULL)) {\r
-           xpExpr = comp->comp;\r
-       } else {\r
-           xpExpr = xmlXPathCompile(variable->select);\r
-       }\r
-       if (xpExpr == NULL)\r
-           return(NULL);\r
-       /*\r
-       * Save context states.\r
-       */\r
-       oldXPDoc = xpctxt->doc;\r
-       oldXPContextNode = xpctxt->node;\r
-       oldXPProximityPosition = xpctxt->proximityPosition;\r
-       oldXPContextSize = xpctxt->contextSize;\r
-       oldXPNamespaces = xpctxt->namespaces;\r
-       oldXPNsNr = xpctxt->nsNr;\r
-               \r
-       xpctxt->node = ctxt->node;\r
-       /*\r
-       * OPTIMIZE TODO: Lame try to set the context doc.\r
-       *   Get rid of this somehow in xpath.c.\r
-       */\r
-       if ((ctxt->node->type != XML_NAMESPACE_DECL) &&\r
-           ctxt->node->doc)\r
-           xpctxt->doc = ctxt->node->doc;\r
-       /*\r
-       * BUG TODO: The proximity position and the context size will\r
-       *  potentially be wrong.\r
-       *  Example: \r
-       *  <xsl:template select="foo">\r
-       *    <xsl:variable name="pos" select="position()"/>\r
-       *    <xsl:for-each select="bar">\r
-       *      <xsl:value-of select="$pos"/>\r
-       *    </xsl:for-each>\r
-       *  </xsl:template>\r
-       *  Here the proximity position and context size are changed\r
-       *  to the context of <xsl:for-each select="bar">, but\r
-       *  the variable needs to be evaluated in the context of\r
-       *  <xsl:template select="foo">.\r
-       */      \r
-       if (comp != NULL) {\r
-           \r
-#ifdef XSLT_REFACTORED\r
-           if (comp->inScopeNs != NULL) {\r
-               xpctxt->namespaces = comp->inScopeNs->list;\r
-               xpctxt->nsNr = comp->inScopeNs->xpathNumber;\r
-           } else {\r
-               xpctxt->namespaces = NULL;\r
-               xpctxt->nsNr = 0;\r
-           }\r
-#else\r
-           xpctxt->namespaces = comp->nsList;\r
-           xpctxt->nsNr = comp->nsNr;\r
-#endif\r
-       } else {\r
-           xpctxt->namespaces = NULL;\r
-           xpctxt->nsNr = 0;\r
-       }\r
-\r
-       /*\r
-       * We need to mark that we are "selecting" a var's value;\r
-       * if any tree fragments are created inside the expression,\r
-       * then those need to be stored inside the variable; otherwise\r
-       * we'll eventually free still referenced fragments, before\r
-       * we leave the scope of the variable.\r
-       */\r
-       ctxt->contextVariable = variable;       \r
-       variable->flags |= XSLT_VAR_IN_SELECT;  \r
-       \r
-       result = xmlXPathCompiledEval(xpExpr, xpctxt);\r
-\r
-       variable->flags ^= XSLT_VAR_IN_SELECT;\r
-       /*\r
-       * Restore Context states.\r
-       */\r
-       ctxt->contextVariable = oldVar;\r
-\r
-       xpctxt->doc = oldXPDoc;\r
-       xpctxt->node = oldXPContextNode;\r
-       xpctxt->contextSize = oldXPContextSize;\r
-       xpctxt->proximityPosition = oldXPProximityPosition;\r
-       xpctxt->namespaces = oldXPNamespaces;\r
-       xpctxt->nsNr = oldXPNsNr;\r
-\r
-       if ((comp == NULL) || (comp->comp == NULL))\r
-           xmlXPathFreeCompExpr(xpExpr);\r
-       if (result == NULL) {\r
-           xsltTransformError(ctxt, NULL,\r
-               (comp != NULL) ? comp->inst : NULL,\r
-               "Failed to evaluate the expression of variable '%s'.\n",\r
-               variable->name);\r
-           ctxt->state = XSLT_STATE_STOPPED;\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-#ifdef LIBXML_DEBUG_ENABLED\r
-       } else {\r
-           if ((xsltGenericDebugContext == stdout) ||\r
-               (xsltGenericDebugContext == stderr))\r
-               xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,\r
-                                       result, 0);\r
-#endif\r
-#endif\r
-       }\r
-    } else {\r
-       if (variable->tree == NULL) {\r
-           result = xmlXPathNewCString("");\r
-       } else {            \r
-           if (variable->tree) {\r
-               xmlDocPtr container;\r
-               xmlNodePtr oldInsert;\r
-               xmlDocPtr  oldOutput;\r
-               xsltStackElemPtr oldVar = ctxt->contextVariable;\r
-\r
-               /*\r
-               * Generate a result tree fragment.\r
-               */\r
-               container = xsltCreateRVT(ctxt);\r
-               if (container == NULL)\r
-                   goto error;\r
-               /*\r
-               * NOTE: Local Result Tree Fragments of params/variables\r
-               * are not registered globally anymore; the life-time\r
-               * is not directly dependant of the param/variable itself.\r
-               *\r
-               * OLD: xsltRegisterTmpRVT(ctxt, container);\r
-               */\r
-               /*\r
-               * Attach the Result Tree Fragment to the variable;\r
-               * when the variable is freed, it will also free \r
-               * the Result Tree Fragment.\r
-               */\r
-               variable->fragment = container;\r
-               \r
-               oldOutput = ctxt->output;\r
-               oldInsert = ctxt->insert;               \r
-               \r
-               ctxt->output = container;\r
-               ctxt->insert = (xmlNodePtr) container;\r
-               ctxt->contextVariable = variable;\r
-               /*\r
-               * Process the sequence constructor (variable->tree).\r
-               * The resulting tree will be held by @container.\r
-               */\r
-               xsltApplyOneTemplate(ctxt, ctxt->node, variable->tree,\r
-                   NULL, NULL);\r
-\r
-               ctxt->contextVariable = oldVar;         \r
-               ctxt->insert = oldInsert;\r
-               ctxt->output = oldOutput;\r
-               \r
-               result = xmlXPathNewValueTree((xmlNodePtr) container);\r
-           }\r
-           if (result == NULL) {\r
-               result = xmlXPathNewCString("");\r
-           } else {\r
-               /*\r
-               * Freeing is not handled there anymore.\r
-               * QUESTION TODO: What does the above comment mean?\r
-               */\r
-               result->boolval = 0; \r
-           }\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-#ifdef LIBXML_DEBUG_ENABLED\r
-\r
-           if ((xsltGenericDebugContext == stdout) ||\r
-               (xsltGenericDebugContext == stderr))\r
-               xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,\r
-                                       result, 0);\r
-#endif\r
-#endif\r
-       }\r
-    }\r
-\r
-error:\r
-    ctxt->inst = oldInst;\r
-    return(result);\r
-}\r
-\r
-/**\r
- * xsltEvalGlobalVariable:\r
- * @elem:  the variable or parameter\r
- * @ctxt:  the XSLT transformation context\r
- *\r
- * Evaluates a the value of a global xsl:variable or\r
- * xsl:param declaration.\r
- *\r
- * Returns the XPath Object value or NULL in case of error\r
- */\r
-static xmlXPathObjectPtr\r
-xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt)\r
-{\r
-    xmlXPathObjectPtr result = NULL;\r
-    xmlNodePtr oldInst;\r
-    const xmlChar* oldVarName;\r
-\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleBasicItemVariablePtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((ctxt == NULL) || (elem == NULL))\r
-       return(NULL);\r
-    if (elem->computed)\r
-       return(elem->value);\r
-\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-       "Evaluating global variable %s\n", elem->name));\r
-#endif\r
-\r
-#ifdef WITH_DEBUGGER\r
-    if ((ctxt->debugStatus != XSLT_DEBUG_NONE) &&\r
-        elem->comp && elem->comp->inst)\r
-        xslHandleDebugger(elem->comp->inst, NULL, NULL, ctxt);\r
-#endif\r
-\r
-    oldInst = ctxt->inst;\r
-    comp = elem->comp;\r
-    oldVarName = elem->name;\r
-    elem->name = xsltComputingGlobalVarMarker;\r
-    /*\r
-    * OPTIMIZE TODO: We should consider instantiating global vars/params\r
-    *  on-demand. The vars/params don't need to be evaluated if never\r
-    *  called; and in the case of global params, if values for such params\r
-    *  are provided by the user.\r
-    */\r
-    if (elem->select != NULL) {                \r
-       xmlXPathCompExprPtr xpExpr = NULL;\r
-       xmlDocPtr oldXPDoc;\r
-       xmlNodePtr oldXPContextNode;\r
-       int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;\r
-       xmlNsPtr *oldXPNamespaces;\r
-       xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;\r
-\r
-       if ((comp != NULL) && (comp->comp != NULL)) {\r
-           xpExpr = comp->comp;\r
-       } else {\r
-           xpExpr = xmlXPathCompile(elem->select);\r
-       }\r
-       if (xpExpr == NULL)\r
-           goto error;\r
-       \r
-       \r
-       if (comp != NULL)\r
-           ctxt->inst = comp->inst;\r
-       else\r
-           ctxt->inst = NULL;\r
-       /*\r
-       * SPEC XSLT 1.0:\r
-       * "At top-level, the expression or template specifying the\r
-       *  variable value is evaluated with the same context as that used\r
-       *  to process the root node of the source document: the current\r
-       *  node is the root node of the source document and the current\r
-       *  node list is a list containing just the root node of the source\r
-       *  document."   \r
-       */\r
-       /*\r
-       * Save context states.\r
-       */\r
-       oldXPDoc = xpctxt->doc;\r
-       oldXPContextNode = xpctxt->node;\r
-       oldXPProximityPosition = xpctxt->proximityPosition;\r
-       oldXPContextSize = xpctxt->contextSize;\r
-       oldXPNamespaces = xpctxt->namespaces;\r
-       oldXPNsNr = xpctxt->nsNr;\r
-               \r
-       xpctxt->node = ctxt->initialContextNode;\r
-       xpctxt->doc = ctxt->initialContextDoc;\r
-       xpctxt->contextSize = 1;\r
-       xpctxt->proximityPosition = 1;\r
-               \r
-       if (comp != NULL) {\r
-           \r
-#ifdef XSLT_REFACTORED\r
-           if (comp->inScopeNs != NULL) {\r
-               xpctxt->namespaces = comp->inScopeNs->list;\r
-               xpctxt->nsNr = comp->inScopeNs->xpathNumber;\r
-           } else {\r
-               xpctxt->namespaces = NULL;\r
-               xpctxt->nsNr = 0;\r
-           }\r
-#else\r
-           xpctxt->namespaces = comp->nsList;\r
-           xpctxt->nsNr = comp->nsNr;\r
-#endif\r
-       } else {\r
-           xpctxt->namespaces = NULL;\r
-           xpctxt->nsNr = 0;\r
-       }\r
-       \r
-       result = xmlXPathCompiledEval(xpExpr, xpctxt);\r
-\r
-       /*\r
-       * Restore Context states.\r
-       */\r
-       xpctxt->doc = oldXPDoc;\r
-       xpctxt->node = oldXPContextNode;\r
-       xpctxt->contextSize = oldXPContextSize;\r
-       xpctxt->proximityPosition = oldXPProximityPosition;\r
-       xpctxt->namespaces = oldXPNamespaces;\r
-       xpctxt->nsNr = oldXPNsNr;\r
-\r
-       if ((comp == NULL) || (comp->comp == NULL))\r
-           xmlXPathFreeCompExpr(xpExpr);\r
-       if (result == NULL) {\r
-           if (comp == NULL)\r
-               xsltTransformError(ctxt, NULL, NULL,\r
-                   "Evaluating global variable %s failed\n", elem->name);\r
-           else\r
-               xsltTransformError(ctxt, NULL, comp->inst,\r
-                   "Evaluating global variable %s failed\n", elem->name);\r
-           ctxt->state = XSLT_STATE_STOPPED;\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-#ifdef LIBXML_DEBUG_ENABLED\r
-       } else {\r
-           if ((xsltGenericDebugContext == stdout) ||\r
-               (xsltGenericDebugContext == stderr))\r
-               xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,\r
-                                       result, 0);\r
-#endif\r
-#endif\r
-       }\r
-    } else {\r
-       if (elem->tree == NULL) {\r
-           result = xmlXPathNewCString("");\r
-       } else {\r
-           xmlDocPtr container;\r
-           xmlNodePtr oldInsert;\r
-           xmlDocPtr  oldOutput, oldXPDoc;         \r
-           /*\r
-           * Generate a result tree fragment.\r
-           */\r
-           container = xsltCreateRVT(ctxt);\r
-           if (container == NULL)\r
-               goto error;\r
-           /*\r
-           * Let the lifetime of the tree fragment be handled by\r
-           * the Libxslt's garbage collector.\r
-           */\r
-           xsltRegisterPersistRVT(ctxt, container);        \r
-\r
-           oldOutput = ctxt->output;\r
-           oldInsert = ctxt->insert;\r
-\r
-           oldXPDoc = ctxt->xpathCtxt->doc;\r
-           \r
-           ctxt->output = container;       \r
-           ctxt->insert = (xmlNodePtr) container;\r
-\r
-           ctxt->xpathCtxt->doc = ctxt->initialContextDoc;\r
-           /*\r
-           * Process the sequence constructor.\r
-           */\r
-           xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);\r
-\r
-           ctxt->xpathCtxt->doc = oldXPDoc;\r
-\r
-           ctxt->insert = oldInsert;\r
-           ctxt->output = oldOutput;\r
-           \r
-           result = xmlXPathNewValueTree((xmlNodePtr) container);\r
-           if (result == NULL) {\r
-               result = xmlXPathNewCString("");\r
-           } else {\r
-               result->boolval = 0; /* Freeing is not handled there anymore */\r
-           }\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-#ifdef LIBXML_DEBUG_ENABLED\r
-           if ((xsltGenericDebugContext == stdout) ||\r
-               (xsltGenericDebugContext == stderr))\r
-               xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,\r
-                                       result, 0);\r
-#endif\r
-#endif\r
-       }\r
-    }\r
-\r
-error:\r
-    elem->name = oldVarName;\r
-    ctxt->inst = oldInst;\r
-    if (result != NULL) {\r
-       elem->value = result;\r
-       elem->computed = 1;\r
-    }\r
-    return(result);\r
-}\r
-\r
-/**\r
- * xsltEvalGlobalVariables:\r
- * @ctxt:  the XSLT transformation context\r
- *\r
- * Evaluates all global variables and parameters of a stylesheet.\r
- * For internal use only. This is called at start of a transformation.\r
- *\r
- * Returns 0 in case of success, -1 in case of error\r
- */\r
-int\r
-xsltEvalGlobalVariables(xsltTransformContextPtr ctxt) {\r
-    xsltStackElemPtr elem;\r
-    xsltStylesheetPtr style;    \r
-\r
-    if ((ctxt == NULL) || (ctxt->document == NULL))\r
-       return(-1);\r
\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-       "Registering global variables\n"));\r
-#endif\r
-    /*\r
-     * Walk the list from the stylesheets and populate the hash table\r
-     */\r
-    style = ctxt->style;\r
-    while (style != NULL) {\r
-       elem = style->variables;\r
-       \r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-       if ((style->doc != NULL) && (style->doc->URL != NULL)) {\r
-           XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-                            "Registering global variables from %s\n",\r
-                            style->doc->URL));\r
-       }\r
-#endif\r
-\r
-       while (elem != NULL) {\r
-           xsltStackElemPtr def;\r
-\r
-           /*\r
-            * Global variables are stored in the variables pool.\r
-            */\r
-           def = (xsltStackElemPtr) \r
-                   xmlHashLookup2(ctxt->globalVars,\r
-                                elem->name, elem->nameURI);\r
-           if (def == NULL) {\r
-\r
-               def = xsltCopyStackElem(elem);\r
-               xmlHashAddEntry2(ctxt->globalVars,\r
-                                elem->name, elem->nameURI, def);\r
-           } else if ((elem->comp != NULL) &&\r
-                      (elem->comp->type == XSLT_FUNC_VARIABLE)) {\r
-               /*\r
-                * Redefinition of variables from a different stylesheet\r
-                * should not generate a message.\r
-                */\r
-               if ((elem->comp->inst != NULL) &&\r
-                   (def->comp != NULL) && (def->comp->inst != NULL) &&\r
-                   (elem->comp->inst->doc == def->comp->inst->doc))\r
-               {\r
-                   xsltTransformError(ctxt, style, elem->comp->inst,\r
-                       "Global variable %s already defined\n", elem->name);\r
-                   if (style != NULL) style->errors++;\r
-               }\r
-           }\r
-           elem = elem->next;\r
-       }\r
-\r
-       style = xsltNextImport(style);\r
-    }\r
-\r
-    /*\r
-     * This part does the actual evaluation\r
-     */    \r
-    xmlHashScan(ctxt->globalVars,\r
-               (xmlHashScanner) xsltEvalGlobalVariable, ctxt);\r
-\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltRegisterGlobalVariable:\r
- * @style:  the XSLT transformation context\r
- * @name:  the variable name\r
- * @ns_uri:  the variable namespace URI\r
- * @sel:  the expression which need to be evaluated to generate a value\r
- * @tree:  the subtree if sel is NULL\r
- * @comp:  the precompiled value\r
- * @value:  the string value if available\r
- *\r
- * Register a new variable value. If @value is NULL it unregisters\r
- * the variable\r
- *\r
- * Returns 0 in case of success, -1 in case of error\r
- */\r
-static int\r
-xsltRegisterGlobalVariable(xsltStylesheetPtr style, const xmlChar *name,\r
-                    const xmlChar *ns_uri, const xmlChar *sel,\r
-                    xmlNodePtr tree, xsltStylePreCompPtr comp,\r
-                    const xmlChar *value) {\r
-    xsltStackElemPtr elem, tmp;\r
-    if (style == NULL)\r
-       return(-1);\r
-    if (name == NULL)\r
-       return(-1);\r
-    if (comp == NULL)\r
-       return(-1);\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    if (comp->type == XSLT_FUNC_PARAM)\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-                        "Defining global param %s\n", name);\r
-    else\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-                        "Defining global variable %s\n", name);\r
-#endif\r
-\r
-    elem = xsltNewStackElem(NULL);\r
-    if (elem == NULL)\r
-       return(-1);\r
-    elem->comp = comp;\r
-    elem->name = xmlDictLookup(style->dict, name, -1);\r
-    elem->select = xmlDictLookup(style->dict, sel, -1);\r
-    if (ns_uri)\r
-       elem->nameURI = xmlDictLookup(style->dict, ns_uri, -1);\r
-    elem->tree = tree;\r
-    tmp = style->variables;\r
-    if (tmp == NULL) {\r
-       elem->next = NULL;\r
-       style->variables = elem;\r
-    } else {\r
-       while (tmp != NULL) {\r
-           if ((elem->comp->type == XSLT_FUNC_VARIABLE) &&\r
-               (tmp->comp->type == XSLT_FUNC_VARIABLE) &&\r
-               (xmlStrEqual(elem->name, tmp->name)) &&\r
-               ((elem->nameURI == tmp->nameURI) ||\r
-                (xmlStrEqual(elem->nameURI, tmp->nameURI))))\r
-           {\r
-               xsltTransformError(NULL, style, comp->inst,\r
-               "redefinition of global variable %s\n", elem->name);\r
-               style->errors++;\r
-           }\r
-           if (tmp->next == NULL)\r
-               break;\r
-           tmp = tmp->next;\r
-       }\r
-       elem->next = NULL;\r
-       tmp->next = elem;\r
-    }\r
-    if (value != NULL) {\r
-       elem->computed = 1;\r
-       elem->value = xmlXPathNewString(value);\r
-    }\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltProcessUserParamInternal\r
- *\r
- * @ctxt:  the XSLT transformation context\r
- * @name:  a null terminated parameter name\r
- * @value: a null terminated value (may be an XPath expression)\r
- * @eval:  0 to treat the value literally, else evaluate as XPath expression\r
- *\r
- * If @eval is 0 then @value is treated literally and is stored in the global\r
- * parameter/variable table without any change.\r
- *\r
- * Uf @eval is 1 then @value is treated as an XPath expression and is\r
- * evaluated.  In this case, if you want to pass a string which will be\r
- * interpreted literally then it must be enclosed in single or double quotes.\r
- * If the string contains single quotes (double quotes) then it cannot be\r
- * enclosed single quotes (double quotes).  If the string which you want to\r
- * be treated literally contains both single and double quotes (e.g. Meet\r
- * at Joe's for "Twelfth Night" at 7 o'clock) then there is no suitable\r
- * quoting character.  You cannot use &apos; or &quot; inside the string\r
- * because the replacement of character entities with their equivalents is\r
- * done at a different stage of processing.  The solution is to call\r
- * xsltQuoteUserParams or xsltQuoteOneUserParam.\r
- *\r
- * This needs to be done on parsed stylesheets before starting to apply\r
- * transformations.  Normally this will be called (directly or indirectly)\r
- * only from xsltEvalUserParams, xsltEvalOneUserParam, xsltQuoteUserParams,\r
- * or xsltQuoteOneUserParam.\r
- *\r
- * Returns 0 in case of success, -1 in case of error\r
- */\r
-\r
-static\r
-int\r
-xsltProcessUserParamInternal(xsltTransformContextPtr ctxt,\r
-                            const xmlChar * name,\r
-                            const xmlChar * value,\r
-                            int eval) {\r
-\r
-    xsltStylesheetPtr style;\r
-    const xmlChar *prefix;\r
-    const xmlChar *href;\r
-    xmlXPathCompExprPtr xpExpr;\r
-    xmlXPathObjectPtr result;\r
-    \r
-    xsltStackElemPtr elem;\r
-    int res;\r
-    void *res_ptr;\r
-\r
-    if (ctxt == NULL)\r
-       return(-1);\r
-    if (name == NULL)\r
-       return(0);\r
-    if (value == NULL)\r
-       return(0);\r
-\r
-    style = ctxt->style;\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-           "Evaluating user parameter %s=%s\n", name, value));\r
-#endif\r
-\r
-    /*\r
-     * Name lookup\r
-     */\r
-\r
-    name = xsltSplitQName(ctxt->dict, name, &prefix);\r
-    href = NULL;\r
-    if (prefix != NULL) {\r
-       xmlNsPtr ns;\r
-\r
-       ns = xmlSearchNs(style->doc, xmlDocGetRootElement(style->doc),\r
-                        prefix);\r
-       if (ns == NULL) {\r
-           xsltTransformError(ctxt, style, NULL,\r
-           "user param : no namespace bound to prefix %s\n", prefix);\r
-           href = NULL;\r
-       } else {\r
-           href = ns->href;\r
-       }\r
-    }\r
-\r
-    if (name == NULL)\r
-       return (-1);\r
-\r
-    res_ptr = xmlHashLookup2(ctxt->globalVars, name, href);\r
-    if (res_ptr != 0) {\r
-       xsltTransformError(ctxt, style, NULL,\r
-           "Global parameter %s already defined\n", name);\r
-    }\r
-    if (ctxt->globalVars == NULL)\r
-       ctxt->globalVars = xmlHashCreate(20);\r
-\r
-    /*\r
-     * do not overwrite variables with parameters from the command line\r
-     */\r
-    while (style != NULL) {\r
-        elem = ctxt->style->variables;\r
-       while (elem != NULL) {\r
-           if ((elem->comp != NULL) &&\r
-               (elem->comp->type == XSLT_FUNC_VARIABLE) &&\r
-               (xmlStrEqual(elem->name, name)) &&\r
-               (xmlStrEqual(elem->nameURI, href))) {\r
-               return(0);\r
-           }\r
-            elem = elem->next;\r
-       }\r
-        style = xsltNextImport(style);\r
-    }\r
-    style = ctxt->style;\r
-    elem = NULL;\r
-\r
-    /*\r
-     * Do the evaluation if @eval is non-zero.\r
-     */\r
-\r
-    result = NULL;\r
-    if (eval != 0) {\r
-        xpExpr = xmlXPathCompile(value);\r
-       if (xpExpr != NULL) {\r
-           xmlDocPtr oldXPDoc;\r
-           xmlNodePtr oldXPContextNode;\r
-           int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;\r
-           xmlNsPtr *oldXPNamespaces;\r
-           xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;\r
-           /*\r
-           * SPEC XSLT 1.0:\r
-           * "At top-level, the expression or template specifying the\r
-           *  variable value is evaluated with the same context as that used\r
-           *  to process the root node of the source document: the current\r
-           *  node is the root node of the source document and the current\r
-           *  node list is a list containing just the root node of the source\r
-           *  document."\r
-           */\r
-           xpctxt->doc = ctxt->tmpDoc;\r
-           /*\r
-           * Save context states.\r
-           */\r
-           oldXPDoc = xpctxt->doc;\r
-           oldXPContextNode = xpctxt->node;\r
-           oldXPProximityPosition = xpctxt->proximityPosition;\r
-           oldXPContextSize = xpctxt->contextSize;\r
-           oldXPNamespaces = xpctxt->namespaces;\r
-           oldXPNsNr = xpctxt->nsNr;\r
-           \r
-           xpctxt->node = ctxt->initialContextNode;\r
-           xpctxt->doc = ctxt->initialContextDoc;\r
-           xpctxt->contextSize = 1;\r
-           xpctxt->proximityPosition = 1;\r
-           /* \r
-           * There is really no in scope namespace for parameters on the\r
-           * command line.\r
-           */\r
-           xpctxt->namespaces = NULL;\r
-           xpctxt->nsNr = 0;      \r
-           \r
-           result = xmlXPathCompiledEval(xpExpr, xpctxt);\r
-           \r
-           /*\r
-           * Restore Context states.\r
-           */\r
-           xpctxt->doc = oldXPDoc;\r
-           xpctxt->node = oldXPContextNode;\r
-           xpctxt->contextSize = oldXPContextSize;\r
-           xpctxt->proximityPosition = oldXPProximityPosition;\r
-           xpctxt->namespaces = oldXPNamespaces;\r
-           xpctxt->nsNr = oldXPNsNr;\r
-           \r
-           xmlXPathFreeCompExpr(xpExpr);\r
-       }\r
-       if (result == NULL) {\r
-           xsltTransformError(ctxt, style, NULL,\r
-               "Evaluating user parameter %s failed\n", name);\r
-           ctxt->state = XSLT_STATE_STOPPED;\r
-           return(-1);\r
-       }\r
-    }\r
-\r
-    /* \r
-     * If @eval is 0 then @value is to be taken literally and result is NULL\r
-     * \r
-     * If @eval is not 0, then @value is an XPath expression and has been\r
-     * successfully evaluated and result contains the resulting value and\r
-     * is not NULL.\r
-     *\r
-     * Now create an xsltStackElemPtr for insertion into the context's\r
-     * global variable/parameter hash table.\r
-     */\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-#ifdef LIBXML_DEBUG_ENABLED\r
-    if ((xsltGenericDebugContext == stdout) ||\r
-        (xsltGenericDebugContext == stderr))\r
-           xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,\r
-                                   result, 0);\r
-#endif\r
-#endif\r
-\r
-    elem = xsltNewStackElem(NULL);\r
-    if (elem != NULL) {\r
-       elem->name = name;\r
-       elem->select = xmlDictLookup(ctxt->dict, value, -1);\r
-       if (href != NULL)\r
-           elem->nameURI = xmlDictLookup(ctxt->dict, href, -1);\r
-       elem->tree = NULL;\r
-       elem->computed = 1;\r
-       if (eval == 0) {\r
-           elem->value = xmlXPathNewString(value);\r
-       } \r
-       else {\r
-           elem->value = result;\r
-       }\r
-    }\r
-\r
-    /*\r
-     * Global parameters are stored in the XPath context variables pool.\r
-     */\r
-\r
-    res = xmlHashAddEntry2(ctxt->globalVars, name, href, elem);\r
-    if (res != 0) {\r
-       xsltFreeStackElem(elem);\r
-       xsltTransformError(ctxt, style, NULL,\r
-           "Global parameter %s already defined\n", name);\r
-    }\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltEvalUserParams:\r
- *\r
- * @ctxt:  the XSLT transformation context\r
- * @params:  a NULL terminated array of parameters name/value tuples\r
- *\r
- * Evaluate the global variables of a stylesheet. This needs to be\r
- * done on parsed stylesheets before starting to apply transformations.\r
- * Each of the parameters is evaluated as an XPath expression and stored\r
- * in the global variables/parameter hash table.  If you want your\r
- * parameter used literally, use xsltQuoteUserParams.\r
- *\r
- * Returns 0 in case of success, -1 in case of error\r
- */\r
\r
-int\r
-xsltEvalUserParams(xsltTransformContextPtr ctxt, const char **params) {\r
-    int indx = 0;\r
-    const xmlChar *name;\r
-    const xmlChar *value;\r
-\r
-    if (params == NULL)\r
-       return(0);\r
-    while (params[indx] != NULL) {\r
-       name = (const xmlChar *) params[indx++];\r
-       value = (const xmlChar *) params[indx++];\r
-       if (xsltEvalOneUserParam(ctxt, name, value) != 0) \r
-           return(-1);\r
-    }\r
-    return 0;\r
-}\r
-\r
-/**\r
- * xsltQuoteUserParams:\r
- *\r
- * @ctxt:  the XSLT transformation context\r
- * @params:  a NULL terminated arry of parameters names/values tuples\r
- *\r
- * Similar to xsltEvalUserParams, but the values are treated literally and\r
- * are * *not* evaluated as XPath expressions. This should be done on parsed\r
- * stylesheets before starting to apply transformations.\r
- *\r
- * Returns 0 in case of success, -1 in case of error.\r
- */\r
\r
-int\r
-xsltQuoteUserParams(xsltTransformContextPtr ctxt, const char **params) {\r
-    int indx = 0;\r
-    const xmlChar *name;\r
-    const xmlChar *value;\r
-\r
-    if (params == NULL)\r
-       return(0);\r
-    while (params[indx] != NULL) {\r
-       name = (const xmlChar *) params[indx++];\r
-       value = (const xmlChar *) params[indx++];\r
-       if (xsltQuoteOneUserParam(ctxt, name, value) != 0) \r
-           return(-1);\r
-    }\r
-    return 0;\r
-}\r
-\r
-/**\r
- * xsltEvalOneUserParam:\r
- * @ctxt:  the XSLT transformation context\r
- * @name:  a null terminated string giving the name of the parameter\r
- * @value:  a null terminated string giving the XPath expression to be evaluated\r
- *\r
- * This is normally called from xsltEvalUserParams to process a single\r
- * parameter from a list of parameters.  The @value is evaluated as an\r
- * XPath expression and the result is stored in the context's global\r
- * variable/parameter hash table.\r
- *\r
- * To have a parameter treated literally (not as an XPath expression)\r
- * use xsltQuoteUserParams (or xsltQuoteOneUserParam).  For more\r
- * details see description of xsltProcessOneUserParamInternal.\r
- *\r
- * Returns 0 in case of success, -1 in case of error.\r
- */\r
-\r
-int\r
-xsltEvalOneUserParam(xsltTransformContextPtr ctxt,\r
-                    const xmlChar * name,\r
-                    const xmlChar * value) {\r
-    return xsltProcessUserParamInternal(ctxt, name, value,\r
-                                       1 /* xpath eval ? */);\r
-}\r
-\r
-/**\r
- * xsltQuoteOneUserParam:\r
- * @ctxt:  the XSLT transformation context\r
- * @name:  a null terminated string giving the name of the parameter\r
- * @value:  a null terminated string giving the parameter value\r
- *\r
- * This is normally called from xsltQuoteUserParams to process a single\r
- * parameter from a list of parameters.  The @value is stored in the\r
- * context's global variable/parameter hash table.\r
- *\r
- * Returns 0 in case of success, -1 in case of error.\r
- */\r
-\r
-int\r
-xsltQuoteOneUserParam(xsltTransformContextPtr ctxt,\r
-                        const xmlChar * name,\r
-                        const xmlChar * value) {\r
-    return xsltProcessUserParamInternal(ctxt, name, value,\r
-                                       0 /* xpath eval ? */);\r
-}\r
-\r
-/**\r
- * xsltBuildVariable:\r
- * @ctxt:  the XSLT transformation context\r
- * @comp:  the precompiled form\r
- * @tree:  the tree if select is NULL\r
- *\r
- * Computes a new variable value.\r
- *\r
- * Returns the xsltStackElemPtr or NULL in case of error\r
- */\r
-static xsltStackElemPtr\r
-xsltBuildVariable(xsltTransformContextPtr ctxt,\r
-                 xsltStylePreCompPtr castedComp,\r
-                 xmlNodePtr tree)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleBasicItemVariablePtr comp =\r
-       (xsltStyleBasicItemVariablePtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-#endif \r
-    xsltStackElemPtr elem;\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "Building variable %s", comp->name));\r
-    if (comp->select != NULL)\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-                        " select %s", comp->select));\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext, "\n"));\r
-#endif\r
-\r
-    elem = xsltNewStackElem(ctxt);\r
-    if (elem == NULL)\r
-       return(NULL);\r
-    elem->comp = (xsltStylePreCompPtr) comp;\r
-    elem->name = comp->name;\r
-    elem->select = comp->select;\r
-    elem->nameURI = comp->ns;\r
-    elem->tree = tree;\r
-    elem->value = xsltEvalVariable(ctxt, elem,\r
-       (xsltStylePreCompPtr) comp);\r
-    if (elem->value != NULL)\r
-       elem->computed = 1;\r
-    return(elem);\r
-}\r
-\r
-/**\r
- * xsltRegisterVariable:\r
- * @ctxt:  the XSLT transformation context\r
- * @comp: the compiled XSLT-variable (or param) instruction\r
- * @tree:  the tree if select is NULL\r
- * @isParam:  indicates if this is a parameter\r
- *\r
- * Computes and registers a new variable.\r
- *\r
- * Returns 0 in case of success, -1 in case of error\r
- */\r
-static int\r
-xsltRegisterVariable(xsltTransformContextPtr ctxt,\r
-                    xsltStylePreCompPtr castedComp,\r
-                    xmlNodePtr tree, int isParam)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleBasicItemVariablePtr comp =\r
-       (xsltStyleBasicItemVariablePtr) castedComp;\r
-#else\r
-    xsltStylePreCompPtr comp = castedComp;\r
-    int present;\r
-#endif\r
-    xsltStackElemPtr variable;    \r
-    \r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * REFACTORED NOTE: Redefinitions of vars/params are checked\r
-    *  at compilation time in the refactored code.\r
-    * xsl:with-param parameters are checked in xsltApplyXSLTTemplate().\r
-    */\r
-#else\r
-    present = xsltCheckStackElem(ctxt, comp->name, comp->ns);\r
-    if (isParam == 0) {        \r
-       if ((present != 0) && (present != 3)) {\r
-           /* TODO: report QName. */\r
-           xsltTransformError(ctxt, NULL, comp->inst,\r
-               "XSLT-variable: Redefinition of variable '%s'.\n", comp->name);\r
-           return(0);\r
-       }\r
-    } else if (present != 0) {\r
-       if ((present == 1) || (present == 2)) {\r
-           /* TODO: report QName. */\r
-           xsltTransformError(ctxt, NULL, comp->inst,\r
-               "XSLT-param: Redefinition of parameter '%s'.\n", comp->name);\r
-           return(0);\r
-       }\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-                "param %s defined by caller\n", comp->name));\r
-#endif\r
-       return(0);\r
-    }\r
-#endif /* else of XSLT_REFACTORED */\r
-\r
-    variable = xsltBuildVariable(ctxt, (xsltStylePreCompPtr) comp, tree);\r
-    xsltAddStackElem(ctxt, variable);\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltGlobalVariableLookup:\r
- * @ctxt:  the XSLT transformation context\r
- * @name:  the variable name\r
- * @ns_uri:  the variable namespace URI\r
- *\r
- * Search in the Variable array of the context for the given\r
- * variable value.\r
- *\r
- * Returns the value or NULL if not found\r
- */\r
-static xmlXPathObjectPtr\r
-xsltGlobalVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,\r
-                        const xmlChar *ns_uri) {\r
-    xsltStackElemPtr elem;\r
-    xmlXPathObjectPtr ret = NULL;\r
-\r
-    /*\r
-     * Lookup the global variables in XPath global variable hash table\r
-     */\r
-    if ((ctxt->xpathCtxt == NULL) || (ctxt->globalVars == NULL))\r
-       return(NULL);\r
-    elem = (xsltStackElemPtr)\r
-           xmlHashLookup2(ctxt->globalVars, name, ns_uri);\r
-    if (elem == NULL) {\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-                        "global variable not found %s\n", name));\r
-#endif\r
-       return(NULL);\r
-    }\r
-    /*\r
-    * URGENT TODO: Move the detection of recursive definitions\r
-    * to compile-time.\r
-    */\r
-    if (elem->computed == 0) {\r
-       if (elem->name == xsltComputingGlobalVarMarker) {\r
-           xsltTransformError(ctxt, NULL, elem->comp->inst,\r
-               "Recursive definition of %s\n", name);\r
-           return(NULL);\r
-       }\r
-       ret = xsltEvalGlobalVariable(elem, ctxt);\r
-    } else\r
-       ret = elem->value;\r
-    return(xmlXPathObjectCopy(ret));\r
-}\r
-\r
-/**\r
- * xsltVariableLookup:\r
- * @ctxt:  the XSLT transformation context\r
- * @name:  the variable name\r
- * @ns_uri:  the variable namespace URI\r
- *\r
- * Search in the Variable array of the context for the given\r
- * variable value.\r
- *\r
- * Returns the value or NULL if not found\r
- */\r
-xmlXPathObjectPtr\r
-xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,\r
-                  const xmlChar *ns_uri) {\r
-    xsltStackElemPtr elem;\r
-\r
-    if (ctxt == NULL)\r
-       return(NULL);\r
-\r
-    elem = xsltStackLookup(ctxt, name, ns_uri);\r
-    if (elem == NULL) {\r
-       return(xsltGlobalVariableLookup(ctxt, name, ns_uri));\r
-    }\r
-    if (elem->computed == 0) {\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-                        "uncomputed variable %s\n", name));\r
-#endif\r
-        elem->value = xsltEvalVariable(ctxt, elem, NULL);\r
-       elem->computed = 1;\r
-    }\r
-    if (elem->value != NULL)\r
-       return(xmlXPathObjectCopy(elem->value));\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "variable not found %s\n", name));\r
-#endif\r
-    return(NULL);\r
-}\r
-\r
-/**\r
- * xsltParseStylesheetCallerParam:\r
- * @ctxt:  the XSLT transformation context \r
- * @inst:  the xsl:with-param instruction element\r
- *\r
- * Processes an xsl:with-param instruction at transformation time.\r
- * The value is compute, but not recorded.\r
- * NOTE that this is also called with an *xsl:param* element\r
- * from exsltFuncFunctionFunction(). \r
- *\r
- * Returns the new xsltStackElemPtr or NULL\r
- */\r
-\r
-xsltStackElemPtr\r
-xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr inst)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleBasicItemVariablePtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    xmlNodePtr tree = NULL; /* The first child node of the instruction or\r
-                               the instruction itself. */\r
-    xsltStackElemPtr param = NULL;\r
-    \r
-    if ((ctxt == NULL) || (inst == NULL))\r
-       return(NULL);\r
-\r
-#ifdef XSLT_REFACTORED\r
-    comp = (xsltStyleBasicItemVariablePtr) inst->psvi;\r
-#else\r
-    comp = (xsltStylePreCompPtr) inst->psvi;\r
-#endif\r
-    \r
-    if (comp == NULL) {\r
-        xsltTransformError(ctxt, NULL, inst,\r
-           "Internal error in xsltParseStylesheetCallerParam(): "\r
-           "The XSLT 'with-param' instruction was not compiled.\n");\r
-        return(NULL);\r
-    }\r
-    if (comp->name == NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-           "Internal error in xsltParseStylesheetCallerParam(): "\r
-           "XSLT 'with-param': The attribute 'name' was not compiled.\n");\r
-       return(NULL);\r
-    }\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-           "Handling xsl:with-param %s\n", comp->name));\r
-#endif\r
-\r
-    if (comp->select == NULL) {\r
-       tree = inst->children;\r
-    } else {\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-       XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-           "        select %s\n", comp->select));\r
-#endif\r
-       tree = inst;\r
-    }\r
-\r
-    param = xsltBuildVariable(ctxt, (xsltStylePreCompPtr) comp, tree);\r
-\r
-    return(param);\r
-}\r
-\r
-/**\r
- * xsltParseGlobalVariable:\r
- * @style:  the XSLT stylesheet\r
- * @cur:  the "variable" element\r
- *\r
- * Parses a global XSLT 'variable' declaration at compilation time\r
- * and registers it\r
- */\r
-void\r
-xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemVariablePtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((cur == NULL) || (style == NULL))\r
-       return;\r
-    \r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * Note that xsltStylePreCompute() will be called from\r
-    * xslt.c only.\r
-    */\r
-    comp = (xsltStyleItemVariablePtr) cur->psvi;\r
-#else\r
-    xsltStylePreCompute(style, cur);\r
-    comp = (xsltStylePreCompPtr) cur->psvi;\r
-#endif\r
-    if (comp == NULL) {\r
-       xsltTransformError(NULL, style, cur,\r
-            "xsl:variable : compilation failed\n");\r
-       return;\r
-    }\r
-\r
-    if (comp->name == NULL) {\r
-       xsltTransformError(NULL, style, cur,\r
-           "xsl:variable : missing name attribute\n");\r
-       return;\r
-    }\r
-\r
-    /*\r
-    * Parse the content (a sequence constructor) of xsl:variable.\r
-    */\r
-    if (cur->children != NULL) {\r
-#ifdef XSLT_REFACTORED \r
-        xsltParseSequenceConstructor(XSLT_CCTXT(style), cur->children);\r
-#else\r
-        xsltParseTemplateContent(style, cur);\r
-#endif\r
-    }\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "Registering global variable %s\n", comp->name);\r
-#endif\r
-\r
-    xsltRegisterGlobalVariable(style, comp->name, comp->ns,\r
-       comp->select, cur->children, (xsltStylePreCompPtr) comp,\r
-       NULL);\r
-}\r
-\r
-/**\r
- * xsltParseGlobalParam:\r
- * @style:  the XSLT stylesheet\r
- * @cur:  the "param" element\r
- *\r
- * parse an XSLT transformation param declaration and record\r
- * its value.\r
- */\r
-\r
-void\r
-xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemParamPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((cur == NULL) || (style == NULL))\r
-       return;\r
-    \r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * Note that xsltStylePreCompute() will be called from\r
-    * xslt.c only.\r
-    */\r
-    comp = (xsltStyleItemParamPtr) cur->psvi;\r
-#else\r
-    xsltStylePreCompute(style, cur);\r
-    comp = (xsltStylePreCompPtr) cur->psvi;\r
-#endif    \r
-    if (comp == NULL) {\r
-       xsltTransformError(NULL, style, cur,\r
-            "xsl:param : compilation failed\n");\r
-       return;\r
-    }\r
-\r
-    if (comp->name == NULL) {\r
-       xsltTransformError(NULL, style, cur,\r
-           "xsl:param : missing name attribute\n");\r
-       return;\r
-    }\r
-\r
-    /*\r
-    * Parse the content (a sequence constructor) of xsl:param.\r
-    */\r
-    if (cur->children != NULL) {\r
-#ifdef XSLT_REFACTORED \r
-        xsltParseSequenceConstructor(XSLT_CCTXT(style), cur->children);\r
-#else\r
-        xsltParseTemplateContent(style, cur);\r
-#endif\r
-    }\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "Registering global param %s\n", comp->name);\r
-#endif\r
-\r
-    xsltRegisterGlobalVariable(style, comp->name, comp->ns,\r
-       comp->select, cur->children, (xsltStylePreCompPtr) comp,\r
-       NULL);\r
-}\r
-\r
-/**\r
- * xsltParseStylesheetVariable:\r
- * @ctxt:  the XSLT transformation context\r
- * @inst:  the xsl:variable instruction element\r
- *\r
- * Registers a local XSLT 'variable' instruction at transformation time\r
- * and evaluates its value.\r
- */\r
-void\r
-xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr inst)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemVariablePtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((inst == NULL) || (ctxt == NULL))\r
-       return;\r
-\r
-    comp = inst->psvi;\r
-    if (comp == NULL) {\r
-        xsltTransformError(ctxt, NULL, inst,\r
-           "Internal error in xsltParseStylesheetVariable(): "\r
-           "The XSLT 'variable' instruction was not compiled.\n");\r
-        return;\r
-    }\r
-    if (comp->name == NULL) {\r
-       xsltTransformError(ctxt, NULL, inst,\r
-           "Internal error in xsltParseStylesheetVariable(): "\r
-           "The attribute 'name' was not compiled.\n");\r
-       return;\r
-    }\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-       "Registering variable '%s'\n", comp->name));\r
-#endif\r
-\r
-    xsltRegisterVariable(ctxt, (xsltStylePreCompPtr) comp, inst->children, 0);\r
-}\r
-\r
-/**\r
- * xsltParseStylesheetParam:\r
- * @ctxt:  the XSLT transformation context\r
- * @cur:  the XSLT 'param' element\r
- *\r
- * Registers a local XSLT 'param' declaration at transformation time and\r
- * evaluates its value.\r
- */\r
-void\r
-xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur)\r
-{\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemParamPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-\r
-    if ((cur == NULL) || (ctxt == NULL))\r
-       return;\r
-\r
-    comp = cur->psvi;\r
-    if ((comp == NULL) || (comp->name == NULL)) {\r
-       xsltTransformError(ctxt, NULL, cur,\r
-           "Internal error in xsltParseStylesheetParam(): "\r
-           "The XSLT 'param' declaration was not compiled correctly.\n");\r
-       return;\r
-    }\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-       "Registering param %s\n", comp->name));\r
-#endif\r
-\r
-    xsltRegisterVariable(ctxt, (xsltStylePreCompPtr) comp, cur->children, 1);\r
-}\r
-\r
-/**\r
- * xsltFreeGlobalVariables:\r
- * @ctxt:  the XSLT transformation context\r
- *\r
- * Free up the data associated to the global variables\r
- * its value.\r
- */\r
-\r
-void\r
-xsltFreeGlobalVariables(xsltTransformContextPtr ctxt) {\r
-    xmlHashFree(ctxt->globalVars, (xmlHashDeallocator) xsltFreeStackElem);\r
-}\r
-\r
-/**\r
- * xsltXPathVariableLookup:\r
- * @ctxt:  a void * but the the XSLT transformation context actually\r
- * @name:  the variable name\r
- * @ns_uri:  the variable namespace URI\r
- *\r
- * This is the entry point when a varibale is needed by the XPath\r
- * interpretor.\r
- *\r
- * Returns the value or NULL if not found\r
- */\r
-xmlXPathObjectPtr\r
-xsltXPathVariableLookup(void *ctxt, const xmlChar *name,\r
-                       const xmlChar *ns_uri) {\r
-    xsltTransformContextPtr tctxt;\r
-    xmlXPathObjectPtr valueObj = NULL;\r
-\r
-    if ((ctxt == NULL) || (name == NULL))\r
-       return(NULL);\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    XSLT_TRACE(((xsltTransformContextPtr)ctxt),XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-           "Lookup variable '%s'\n", name));\r
-#endif\r
-    \r
-    tctxt = (xsltTransformContextPtr) ctxt;\r
-    /*\r
-    * Local variables/params ---------------------------------------------\r
-    *\r
-    * Do the lookup from the top of the stack, but\r
-    * don't use params being computed in a call-param\r
-    * First lookup expects the variable name and URI to\r
-    * come from the disctionnary and hence pointer comparison.\r
-    */\r
-    if (tctxt->varsNr != 0) {\r
-       int i;\r
-       xsltStackElemPtr variable = NULL, cur;\r
-\r
-       for (i = tctxt->varsNr; i > tctxt->varsBase; i--) {\r
-           cur = tctxt->varsTab[i-1];\r
-           if ((cur->name == name) && (cur->nameURI == ns_uri)) {\r
-#if 0\r
-               stack_addr++;\r
-#endif\r
-               variable = cur;\r
-               goto local_variable_found;\r
-           }\r
-           cur = cur->next;\r
-       }       \r
-       /*\r
-       * Redo the lookup with interned strings to avoid string comparison.\r
-       *\r
-       * OPTIMIZE TODO: The problem here is, that if we request a\r
-       *  global variable, then this will be also executed.\r
-       */\r
-       {\r
-           const xmlChar *tmpName = name, *tmpNsName = ns_uri;\r
-\r
-           name = xmlDictLookup(tctxt->dict, name, -1);\r
-           if (ns_uri)\r
-               ns_uri = xmlDictLookup(tctxt->dict, ns_uri, -1);\r
-           if ((tmpName != name) || (tmpNsName != ns_uri)) {           \r
-               for (i = tctxt->varsNr; i > tctxt->varsBase; i--) {\r
-                   cur = tctxt->varsTab[i-1];\r
-                   if ((cur->name == name) && (cur->nameURI == ns_uri)) {\r
-#if 0\r
-                       stack_cmp++;\r
-#endif\r
-                       variable = cur;\r
-                       goto local_variable_found;\r
-                   }\r
-               }\r
-           }\r
-       }\r
-\r
-local_variable_found:\r
-\r
-       if (variable) {\r
-           if (variable->computed == 0) {\r
-               \r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-               XSLT_TRACE(tctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-                   "uncomputed variable '%s'\n", name));\r
-#endif\r
-               variable->value = xsltEvalVariable(tctxt, variable, NULL);\r
-               variable->computed = 1;\r
-           }\r
-           if (variable->value != NULL) {\r
-               valueObj = xmlXPathObjectCopy(variable->value); \r
-           }\r
-           return(valueObj);\r
-       }\r
-    }\r
-    /*\r
-    * Global variables/params --------------------------------------------\r
-    */    \r
-    if (tctxt->globalVars) {\r
-       valueObj = xsltGlobalVariableLookup(tctxt, name, ns_uri);\r
-    }\r
-\r
-    if (valueObj == NULL) {\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-    XSLT_TRACE(tctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-                    "variable not found '%s'\n", name));\r
-#endif\r
-\r
-       if (ns_uri) {\r
-           xsltTransformError(tctxt, NULL, tctxt->inst,\r
-               "Variable '{%s}%s' has not been declared.\n", ns_uri, name);\r
-       } else {\r
-           xsltTransformError(tctxt, NULL, tctxt->inst,\r
-               "Variable '%s' has not been declared.\n", name);\r
-       }\r
-    } else {\r
-\r
-#ifdef WITH_XSLT_DEBUG_VARIABLE\r
-       XSLT_TRACE(tctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,\r
-           "found variable '%s'\n", name));\r
-#endif\r
-    }\r
-\r
-    return(valueObj);\r
-}\r
-\r
-\r
+/*
+ * variables.c: Implementation of the variable storage and lookup
+ *
+ * Reference:
+ *   http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/valid.h>
+#include <libxml/hash.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/parserInternals.h>
+#include <libxml/dict.h>
+#include "xslt.h"
+#include "xsltInternals.h"
+#include "xsltutils.h"
+#include "variables.h"
+#include "transform.h"
+#include "imports.h"
+#include "preproc.h"
+#include "keys.h"
+
+#ifdef WITH_XSLT_DEBUG
+ #define WITH_XSLT_DEBUG_VARIABLE
+#endif
+
+#ifdef XSLT_REFACTORED
+const xmlChar *xsltDocFragFake = (const xmlChar *) " fake node libxslt";
+#endif
+
+const xmlChar *xsltComputingGlobalVarMarker =
+ (const xmlChar *) " var/param being computed";
+
+/************************************************************************
+ *                                                                     *
+ *  Result Value Tree (Result Tree Fragment) interfaces                        *
+ *                                                                     *
+ ************************************************************************/
+/**
+ * xsltCreateRVT:
+ * @ctxt:  an XSLT transformation context
+ *
+ * Creates a Result Value Tree
+ * (the XSLT 1.0 term for this is "Result Tree Fragment") 
+ *
+ * Returns the result value tree or NULL in case of API or internal errors.
+ */
+xmlDocPtr
+xsltCreateRVT(xsltTransformContextPtr ctxt)
+{
+    xmlDocPtr container;
+
+    /*
+    * Question: Why is this function public?
+    * Answer: It is called by the EXSLT module.
+    */    
+    if (ctxt == NULL)
+       return(NULL);
+
+    /*
+    * Reuse a RTF from the cache if available.
+    */
+    if (ctxt->cache->RVT) {
+       container = ctxt->cache->RVT;
+       ctxt->cache->RVT = (xmlDocPtr) container->next;
+       container->next = NULL;
+       if (ctxt->cache->nbRVT > 0)
+           ctxt->cache->nbRVT--;
+#ifdef XSLT_DEBUG_PROFILE_CACHE
+       ctxt->cache->dbgReusedRVTs++;
+#endif
+       return(container);
+    }
+
+    container = xmlNewDoc(NULL);
+    if (container == NULL)
+       return(NULL);
+    container->dict = ctxt->dict;
+    xmlDictReference(container->dict);
+    XSLT_MARK_RES_TREE_FRAG(container);
+    container->doc = container;
+    container->parent = NULL;
+    return(container);
+}
+
+/**
+ * xsltRegisterTmpRVT:
+ * @ctxt:  an XSLT transformation context
+ * @RVT:  a result value tree (Result Tree Fragment)
+ *
+ * Registers the result value tree (XSLT 1.0 term: Result Tree Fragment)
+ * in the garbage collector.
+ * The fragment will be freed at the exit of the currently
+ * instantiated xsl:template.
+ * Obsolete; this function might produce massive memory overhead,
+ * since the fragment is only freed when the current xsl:template
+ * exits. Use xsltRegisterLocalRVT() instead.
+ *
+ * Returns 0 in case of success and -1 in case of API or internal errors.
+ */
+int
+xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
+{
+    if ((ctxt == NULL) || (RVT == NULL))
+       return(-1);
+
+    /*
+    * We'll restrict the lifetime of user-created fragments
+    * insinde an xsl:variable and xsl:param to the lifetime of the
+    * var/param itself.
+    */
+    if (ctxt->contextVariable != NULL) {
+       RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;
+       XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;
+       return(0);
+    }
+
+    RVT->next = (xmlNodePtr) ctxt->tmpRVT;
+    if (ctxt->tmpRVT != NULL)
+       ctxt->tmpRVT->prev = (xmlNodePtr) RVT;
+    ctxt->tmpRVT = RVT;
+    return(0);
+}
+
+/**
+ * xsltRegisterLocalRVT:
+ * @ctxt:  an XSLT transformation context
+ * @RVT:  a result value tree (Result Tree Fragment; xmlDocPtr)
+ *
+ * Registers a result value tree (XSLT 1.0 term: Result Tree Fragment)
+ * in the RVT garbage collector.
+ * The fragment will be freed when the instruction which created the
+ * fragment exits.
+ *
+ * Returns 0 in case of success and -1 in case of API or internal errors.
+ */
+int
+xsltRegisterLocalRVT(xsltTransformContextPtr ctxt,
+                    xmlDocPtr RVT)
+{
+    if ((ctxt == NULL) || (RVT == NULL))
+       return(-1);
+    
+    /*
+    * When evaluating "select" expressions of xsl:variable
+    * and xsl:param, we need to bind newly created tree fragments
+    * to the variable itself; otherwise the tragment will be
+    * freed before we leave the scope of a var.
+    */
+    if ((ctxt->contextVariable != NULL) &&
+       (XSLT_TCTXT_VARIABLE(ctxt)->flags & XSLT_VAR_IN_SELECT))
+    {
+       RVT->next = (xmlNodePtr) XSLT_TCTXT_VARIABLE(ctxt)->fragment;
+       XSLT_TCTXT_VARIABLE(ctxt)->fragment = RVT;
+       return(0);
+    }
+    /*
+    * Store the fragment in the scope of the current instruction.
+    * If not reference by a returning instruction (like EXSLT's function),
+    * then this fragment will be freed, when the instruction exits.
+    */
+    RVT->next = (xmlNodePtr) ctxt->localRVT;
+    if (ctxt->localRVT != NULL)
+       ctxt->localRVT->prev = (xmlNodePtr) RVT;
+    ctxt->localRVT = RVT;
+    /*
+    * We need to keep track of the first registered fragment
+    * for extension instructions which return fragments
+    * (e.g. EXSLT'S function), in order to let
+    * xsltExtensionInstructionResultFinalize() clear the
+    * preserving flag on the fragments.
+    */
+    if (ctxt->localRVTBase == NULL)
+       ctxt->localRVTBase = RVT;
+    return(0);
+}
+
+/**
+ * xsltExtensionInstructionResultFinalize:
+ * @ctxt:  an XSLT transformation context
+ *
+ * Finalizes the data (e.g. result tree fragments) created
+ * within a value-returning process (e.g. EXSLT's function).
+ * Tree fragments marked as being returned by a function are
+ * set to normal state, which means that the fragment garbage
+ * collector will free them after the function-calling process exits.
+ *
+ * Returns 0 in case of success and -1 in case of API or internal errors.
+ */
+int
+xsltExtensionInstructionResultFinalize(xsltTransformContextPtr ctxt)
+{
+    xmlDocPtr cur;
+
+    if (ctxt == NULL)
+       return(-1);
+    if (ctxt->localRVTBase == NULL)
+       return(0);
+    /*
+    * Enable remaining local tree fragments to be freed
+    * by the fragment garbage collector.
+    */
+    cur = ctxt->localRVTBase;
+    do {
+       cur->psvi = NULL;
+       cur = (xmlDocPtr) cur->next;
+    } while (cur != NULL);
+    return(0);
+}
+
+/**
+ * xsltExtensionInstructionResultRegister:
+ * @ctxt: an XSLT transformation context
+ * @nodeSet: a node set to be inspected for result tree fragments
+ *
+ * Marks the result of a value-returning extension instruction
+ * in order to avoid it being garbage collected before the
+ * extension instruction exits.
+ * Note that one still has to additionally register any newly created
+ * tree fragments (via xsltCreateRVT()) with xsltRegisterLocalRVT().
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+int
+xsltExtensionInstructionResultRegister(xsltTransformContextPtr ctxt,
+                                      xmlXPathObjectPtr obj)
+{
+    int i;
+    xmlNodePtr cur;
+    xmlDocPtr doc;
+
+    if ((ctxt == NULL) || (obj == NULL))
+       return(-1);
+
+    /*
+    * OPTIMIZE TODO: If no local variables/params and no local tree
+    * fragments were created, then we don't need to analyse the XPath
+    * objects for tree fragments.
+    */
+
+    if ((obj->type != XPATH_NODESET) && (obj->type != XPATH_XSLT_TREE))
+       return(0);
+    if ((obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0))
+       return(0);
+
+    for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+       cur = obj->nodesetval->nodeTab[i];
+       if (cur->type == XML_NAMESPACE_DECL) {
+           /*
+           * The XPath module sets the owner element of a ns-node on
+           * the ns->next field.
+           */
+           if ((((xmlNsPtr) cur)->next != NULL) &&
+               (((xmlNsPtr) cur)->next->type == XML_ELEMENT_NODE))
+           {
+               cur = (xmlNodePtr) ((xmlNsPtr) cur)->next;
+               doc = cur->doc; 
+           } else {
+               xsltTransformError(ctxt, NULL, ctxt->inst,
+                   "Internal error in "
+                   "xsltExtensionInstructionResultRegister(): "
+                   "Cannot retrieve the doc of a namespace node.\n");
+               goto error;
+           }
+       } else {
+           doc = cur->doc;
+       }
+       if (doc == NULL) {
+           xsltTransformError(ctxt, NULL, ctxt->inst,
+               "Internal error in "
+               "xsltExtensionInstructionResultRegister(): "
+               "Cannot retrieve the doc of a node.\n");
+           goto error;
+       }
+       if (doc->name && (doc->name[0] == ' ')) {
+           /*
+           * This is a result tree fragment.
+           * We'll use the @psvi field for reference counting.
+           * TODO: How do we know if this is a value of a
+           *  global variable or a doc acquired via the
+           *  document() function?
+           */
+           doc->psvi = (void *) ((long) 1);
+       }
+    }
+
+    return(0);
+error:
+    return(-1);
+}
+
+/**
+ * xsltReleaseRVT:
+ * @ctxt:  an XSLT transformation context
+ * @RVT:  a result value tree (Result Tree Fragment)
+ *
+ * Either frees the RVT (which is an xmlDoc) or stores
+ * it in the context's cache for later reuse.
+ */
+void
+xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
+{
+    if (RVT == NULL)
+       return;
+
+    if (ctxt && (ctxt->cache->nbRVT < 40)) {
+       /*
+       * Store the Result Tree Fragment.
+       * Free the document info.
+       */
+       if (RVT->_private != NULL) {
+           xsltFreeDocumentKeys((xsltDocumentPtr) RVT->_private);
+           xmlFree(RVT->_private);
+           RVT->_private = NULL;
+       }
+       /*
+       * Clear the document tree.
+       * REVISIT TODO: Do we expect ID/IDREF tables to be existent?    
+       */
+       if (RVT->children != NULL) {
+           xmlFreeNodeList(RVT->children);
+           RVT->children = NULL;
+           RVT->last = NULL;
+       }
+       if (RVT->ids != NULL) {
+           xmlFreeIDTable((xmlIDTablePtr) RVT->ids);
+           RVT->ids = NULL;
+       }
+       if (RVT->refs != NULL) {
+           xmlFreeRefTable((xmlRefTablePtr) RVT->refs);
+           RVT->refs = NULL;
+       }
+
+       /*
+       * Reset the reference counter.
+       */
+       RVT->psvi = 0;
+
+       RVT->next = (xmlNodePtr) ctxt->cache->RVT;
+       ctxt->cache->RVT = RVT;
+
+       ctxt->cache->nbRVT++;
+
+#ifdef XSLT_DEBUG_PROFILE_CACHE
+       ctxt->cache->dbgCachedRVTs++;
+#endif
+       return;
+    }
+    /*
+    * Free it.
+    */
+    if (RVT->_private != NULL) {
+       xsltFreeDocumentKeys((xsltDocumentPtr) RVT->_private);
+       xmlFree(RVT->_private);
+    }
+    xmlFreeDoc(RVT);
+}
+
+/**
+ * xsltRegisterPersistRVT:
+ * @ctxt:  an XSLT transformation context
+ * @RVT:  a result value tree (Result Tree Fragment)
+ *
+ * Register the result value tree (XSLT 1.0 term: Result Tree Fragment)
+ * in the fragment garbage collector.
+ * The fragment will be freed when the transformation context is
+ * freed.
+ *
+ * Returns 0 in case of success and -1 in case of error.
+ */
+int
+xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
+{
+    if ((ctxt == NULL) || (RVT == NULL)) return(-1);
+
+    RVT->next = (xmlNodePtr) ctxt->persistRVT;
+    if (ctxt->persistRVT != NULL)
+       ctxt->persistRVT->prev = (xmlNodePtr) RVT;
+    ctxt->persistRVT = RVT;
+    return(0);
+}
+
+/**
+ * xsltFreeRVTs:
+ * @ctxt:  an XSLT transformation context
+ *
+ * Frees all registered result value trees (Result Tree Fragments)
+ * of the transformation. Internal function; should not be called
+ * by user-code.
+ */
+void
+xsltFreeRVTs(xsltTransformContextPtr ctxt)
+{
+    xmlDocPtr cur, next;
+
+    if (ctxt == NULL)
+       return;
+    /*
+    * Local fragments.
+    */
+    cur = ctxt->localRVT;
+    while (cur != NULL) {
+        next = (xmlDocPtr) cur->next;
+       if (cur->_private != NULL) {
+           xsltFreeDocumentKeys(cur->_private);
+           xmlFree(cur->_private);
+       }
+       xmlFreeDoc(cur);
+       cur = next;
+    }
+    ctxt->localRVT = NULL;
+    /*
+    * User-created per-template fragments.
+    */
+    cur = ctxt->tmpRVT;
+    while (cur != NULL) {
+        next = (xmlDocPtr) cur->next;
+       if (cur->_private != NULL) {
+           xsltFreeDocumentKeys(cur->_private);
+           xmlFree(cur->_private);
+       }
+       xmlFreeDoc(cur);
+       cur = next;
+    }
+    ctxt->tmpRVT = NULL;
+    /*
+    * Global fragments.
+    */
+    cur = ctxt->persistRVT;
+    while (cur != NULL) {
+        next = (xmlDocPtr) cur->next;
+       if (cur->_private != NULL) {
+           xsltFreeDocumentKeys(cur->_private);
+           xmlFree(cur->_private);
+       }
+       xmlFreeDoc(cur);
+       cur = next;
+    }
+    ctxt->persistRVT = NULL;
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Module interfaces                               *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltNewStackElem:
+ *
+ * Create a new XSLT ParserContext
+ *
+ * Returns the newly allocated xsltParserStackElem or NULL in case of error
+ */
+static xsltStackElemPtr
+xsltNewStackElem(xsltTransformContextPtr ctxt)
+{
+    xsltStackElemPtr ret;
+    /*
+    * Reuse a stack item from the cache if available.
+    */
+    if (ctxt && ctxt->cache->stackItems) {
+       ret = ctxt->cache->stackItems;
+       ctxt->cache->stackItems = ret->next;
+       ret->next = NULL;
+       ctxt->cache->nbStackItems--;
+#ifdef XSLT_DEBUG_PROFILE_CACHE
+       ctxt->cache->dbgReusedVars++;
+#endif
+       return(ret);
+    }
+    ret = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));
+    if (ret == NULL) {
+       xsltTransformError(NULL, NULL, NULL,
+               "xsltNewStackElem : malloc failed\n");
+       return(NULL);
+    }
+    memset(ret, 0, sizeof(xsltStackElem));
+    ret->context = ctxt;
+    return(ret);
+}
+
+/**
+ * xsltCopyStackElem:
+ * @elem:  an XSLT stack element
+ *
+ * Makes a copy of the stack element
+ *
+ * Returns the copy of NULL
+ */
+static xsltStackElemPtr
+xsltCopyStackElem(xsltStackElemPtr elem) {
+    xsltStackElemPtr cur;
+
+    cur = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));
+    if (cur == NULL) {
+       xsltTransformError(NULL, NULL, NULL,
+               "xsltCopyStackElem : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltStackElem));
+    cur->context = elem->context;
+    cur->name = elem->name;
+    cur->nameURI = elem->nameURI;
+    cur->select = elem->select;
+    cur->tree = elem->tree;
+    cur->comp = elem->comp;    
+    return(cur);
+}
+
+/**
+ * xsltFreeStackElem:
+ * @elem:  an XSLT stack element
+ *
+ * Free up the memory allocated by @elem
+ */
+static void
+xsltFreeStackElem(xsltStackElemPtr elem) {
+    if (elem == NULL)
+       return;
+    if (elem->value != NULL)
+       xmlXPathFreeObject(elem->value);
+    /*
+    * Release the list of temporary Result Tree Fragments.
+    */
+    if (elem->fragment) {
+       xmlDocPtr cur;
+
+       while (elem->fragment != NULL) {
+           cur = elem->fragment;
+           elem->fragment = (xmlDocPtr) cur->next;
+
+           if (elem->context &&
+               (cur->psvi == (void *) ((long) 1)))
+           {
+               /*
+               * This fragment is a result of an extension instruction
+               * (e.g. XSLT's function) and needs to be preserved until
+               * the instruction exits.
+               * Example: The fragment of the variable must not be freed
+               *  since it is returned by the EXSLT function:
+               *  <f:function name="foo">
+               *   <xsl:variable name="bar">
+               *     <bar/>
+               *   </xsl:variable>
+               *   <f:result select="$bar"/>
+               *  </f:function>
+               * 
+               */
+               xsltRegisterLocalRVT(elem->context, cur);
+           } else {
+               xsltReleaseRVT((xsltTransformContextPtr) elem->context,
+                   cur);
+           }       
+       }
+    }
+    /*
+    * Cache or free the variable structure.
+    */
+    if (elem->context && (elem->context->cache->nbStackItems < 50)) {
+       /*
+       * Store the item in the cache.
+       */
+       xsltTransformContextPtr ctxt = elem->context;
+       memset(elem, 0, sizeof(xsltStackElem));
+       elem->context = ctxt;
+       elem->next = ctxt->cache->stackItems;
+       ctxt->cache->stackItems = elem; 
+       ctxt->cache->nbStackItems++;
+#ifdef XSLT_DEBUG_PROFILE_CACHE
+       ctxt->cache->dbgCachedVars++;
+#endif
+       return;
+    }
+    xmlFree(elem);
+}
+
+/**
+ * xsltFreeStackElemList:
+ * @elem:  an XSLT stack element
+ *
+ * Free up the memory allocated by @elem
+ */
+void
+xsltFreeStackElemList(xsltStackElemPtr elem) {
+    xsltStackElemPtr next;
+    
+    while (elem != NULL) {
+       next = elem->next;
+       xsltFreeStackElem(elem);
+       elem = next;
+    }
+}
+
+/**
+ * xsltStackLookup:
+ * @ctxt:  an XSLT transformation context
+ * @name:  the local part of the name
+ * @nameURI:  the URI part of the name
+ *
+ * Locate an element in the stack based on its name.
+ */
+#if 0 /* TODO: Those seem to have been used for debugging. */
+static int stack_addr = 0;
+static int stack_cmp = 0;
+#endif
+
+static xsltStackElemPtr
+xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
+               const xmlChar *nameURI) {
+    int i;
+    xsltStackElemPtr cur;
+
+    if ((ctxt == NULL) || (name == NULL) || (ctxt->varsNr == 0))
+       return(NULL);
+
+    /*
+     * Do the lookup from the top of the stack, but
+     * don't use params being computed in a call-param
+     * First lookup expects the variable name and URI to
+     * come from the disctionnary and hence pointer comparison.
+     */
+    for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
+       cur = ctxt->varsTab[i-1];
+       while (cur != NULL) {
+           if ((cur->name == name) && (cur->nameURI == nameURI)) {
+#if 0
+               stack_addr++;
+#endif
+               return(cur);
+           }
+           cur = cur->next;
+       }
+    }
+
+    /*
+     * Redo the lookup with interned string compares
+     * to avoid string compares.
+     */
+    name = xmlDictLookup(ctxt->dict, name, -1);
+    if (nameURI != NULL)
+        nameURI = xmlDictLookup(ctxt->dict, nameURI, -1);
+
+    for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
+       cur = ctxt->varsTab[i-1];
+       while (cur != NULL) {
+           if ((cur->name == name) && (cur->nameURI == nameURI)) {
+#if 0
+               stack_cmp++;
+#endif
+               return(cur);
+           }
+           cur = cur->next;
+       }
+    }
+
+    return(NULL);
+}
+
+/**
+ * xsltCheckStackElem:
+ * @ctxt:  xn XSLT transformation context
+ * @name:  the variable name
+ * @nameURI:  the variable namespace URI
+ *
+ * Checks whether a variable or param is already defined.
+ *
+ * URGENT TODO: Checks for redefinition of vars/params should be
+ *  done only at compilation time.
+ *
+ * Returns 1 if variable is present, 2 if param is present, 3 if this
+ *         is an inherited param, 0 if not found, -1 in case of failure.
+ */
+static int
+xsltCheckStackElem(xsltTransformContextPtr ctxt, const xmlChar *name,
+                  const xmlChar *nameURI) {
+    xsltStackElemPtr cur;
+
+    if ((ctxt == NULL) || (name == NULL))
+       return(-1);
+
+    cur = xsltStackLookup(ctxt, name, nameURI);
+    if (cur == NULL)
+        return(0);
+    if (cur->comp != NULL) {
+        if (cur->comp->type == XSLT_FUNC_WITHPARAM)
+           return(3);
+       else if (cur->comp->type == XSLT_FUNC_PARAM)
+           return(2);
+    }
+    
+    return(1);
+}
+
+/**
+ * xsltAddStackElem:
+ * @ctxt:  xn XSLT transformation context
+ * @elem:  a stack element
+ *
+ * Push an element (or list) onto the stack.
+ * In case of a list, each member will be pushed into
+ * a seperate slot; i.e. there's always 1 stack entry for
+ * 1 stack element.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+static int
+xsltAddStackElem(xsltTransformContextPtr ctxt, xsltStackElemPtr elem)
+{
+    if ((ctxt == NULL) || (elem == NULL))
+       return(-1);
+
+    do {
+       if (ctxt->varsMax == 0) {
+           ctxt->varsMax = 10;
+           ctxt->varsTab =
+               (xsltStackElemPtr *) xmlMalloc(ctxt->varsMax *
+               sizeof(ctxt->varsTab[0]));
+           if (ctxt->varsTab == NULL) {
+               xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
+               return (-1);
+           }
+       }
+       if (ctxt->varsNr >= ctxt->varsMax) {
+           ctxt->varsMax *= 2;
+           ctxt->varsTab =
+               (xsltStackElemPtr *) xmlRealloc(ctxt->varsTab,
+               ctxt->varsMax *
+               sizeof(ctxt->varsTab[0]));
+           if (ctxt->varsTab == NULL) {
+               xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
+               return (-1);
+           }
+       }
+       ctxt->varsTab[ctxt->varsNr++] = elem;
+       ctxt->vars = elem;
+       
+       elem = elem->next;
+    } while (elem != NULL);
+    
+    return(0);
+}
+
+/**
+ * xsltAddStackElemList:
+ * @ctxt:  xn XSLT transformation context
+ * @elems:  a stack element list
+ *
+ * Push an element list onto the stack.
+ *
+ * Returns 0 in case of success, -1 in case of failure.
+ */
+int
+xsltAddStackElemList(xsltTransformContextPtr ctxt, xsltStackElemPtr elems)
+{
+    return(xsltAddStackElem(ctxt, elems));
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Module interfaces                               *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltEvalVariable:
+ * @ctxt:  the XSLT transformation context
+ * @variable:  the variable or parameter item
+ * @comp: the compiled XSLT instruction
+ *
+ * Evaluate a variable value.
+ *
+ * Returns the XPath Object value or NULL in case of error
+ */
+static xmlXPathObjectPtr
+xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr variable,
+                xsltStylePreCompPtr castedComp)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemVariablePtr comp =
+       (xsltStyleItemVariablePtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif   
+    xmlXPathObjectPtr result = NULL;
+    xmlNodePtr oldInst;
+
+    if ((ctxt == NULL) || (variable == NULL))
+       return(NULL);
+
+    /*
+    * A variable or parameter are evaluated on demand; thus the
+    * context (of XSLT and XPath) need to be temporarily adjusted and
+    * restored on exit.
+    */
+    oldInst = ctxt->inst;
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+       "Evaluating variable '%s'\n", variable->name));
+#endif
+    if (variable->select != NULL) {
+       xmlXPathCompExprPtr xpExpr = NULL;
+       xmlDocPtr oldXPDoc;
+       xmlNodePtr oldXPContextNode;
+       int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
+       xmlNsPtr *oldXPNamespaces;
+       xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;
+       xsltStackElemPtr oldVar = ctxt->contextVariable;
+
+       if ((comp != NULL) && (comp->comp != NULL)) {
+           xpExpr = comp->comp;
+       } else {
+           xpExpr = xmlXPathCompile(variable->select);
+       }
+       if (xpExpr == NULL)
+           return(NULL);
+       /*
+       * Save context states.
+       */
+       oldXPDoc = xpctxt->doc;
+       oldXPContextNode = xpctxt->node;
+       oldXPProximityPosition = xpctxt->proximityPosition;
+       oldXPContextSize = xpctxt->contextSize;
+       oldXPNamespaces = xpctxt->namespaces;
+       oldXPNsNr = xpctxt->nsNr;
+               
+       xpctxt->node = ctxt->node;
+       /*
+       * OPTIMIZE TODO: Lame try to set the context doc.
+       *   Get rid of this somehow in xpath.c.
+       */
+       if ((ctxt->node->type != XML_NAMESPACE_DECL) &&
+           ctxt->node->doc)
+           xpctxt->doc = ctxt->node->doc;
+       /*
+       * BUG TODO: The proximity position and the context size will
+       *  potentially be wrong.
+       *  Example: 
+       *  <xsl:template select="foo">
+       *    <xsl:variable name="pos" select="position()"/>
+       *    <xsl:for-each select="bar">
+       *      <xsl:value-of select="$pos"/>
+       *    </xsl:for-each>
+       *  </xsl:template>
+       *  Here the proximity position and context size are changed
+       *  to the context of <xsl:for-each select="bar">, but
+       *  the variable needs to be evaluated in the context of
+       *  <xsl:template select="foo">.
+       */      
+       if (comp != NULL) {
+           
+#ifdef XSLT_REFACTORED
+           if (comp->inScopeNs != NULL) {
+               xpctxt->namespaces = comp->inScopeNs->list;
+               xpctxt->nsNr = comp->inScopeNs->xpathNumber;
+           } else {
+               xpctxt->namespaces = NULL;
+               xpctxt->nsNr = 0;
+           }
+#else
+           xpctxt->namespaces = comp->nsList;
+           xpctxt->nsNr = comp->nsNr;
+#endif
+       } else {
+           xpctxt->namespaces = NULL;
+           xpctxt->nsNr = 0;
+       }
+
+       /*
+       * We need to mark that we are "selecting" a var's value;
+       * if any tree fragments are created inside the expression,
+       * then those need to be stored inside the variable; otherwise
+       * we'll eventually free still referenced fragments, before
+       * we leave the scope of the variable.
+       */
+       ctxt->contextVariable = variable;       
+       variable->flags |= XSLT_VAR_IN_SELECT;  
+       
+       result = xmlXPathCompiledEval(xpExpr, xpctxt);
+
+       variable->flags ^= XSLT_VAR_IN_SELECT;
+       /*
+       * Restore Context states.
+       */
+       ctxt->contextVariable = oldVar;
+
+       xpctxt->doc = oldXPDoc;
+       xpctxt->node = oldXPContextNode;
+       xpctxt->contextSize = oldXPContextSize;
+       xpctxt->proximityPosition = oldXPProximityPosition;
+       xpctxt->namespaces = oldXPNamespaces;
+       xpctxt->nsNr = oldXPNsNr;
+
+       if ((comp == NULL) || (comp->comp == NULL))
+           xmlXPathFreeCompExpr(xpExpr);
+       if (result == NULL) {
+           xsltTransformError(ctxt, NULL,
+               (comp != NULL) ? comp->inst : NULL,
+               "Failed to evaluate the expression of variable '%s'.\n",
+               variable->name);
+           ctxt->state = XSLT_STATE_STOPPED;
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+#ifdef LIBXML_DEBUG_ENABLED
+       } else {
+           if ((xsltGenericDebugContext == stdout) ||
+               (xsltGenericDebugContext == stderr))
+               xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
+                                       result, 0);
+#endif
+#endif
+       }
+    } else {
+       if (variable->tree == NULL) {
+           result = xmlXPathNewCString("");
+       } else {            
+           if (variable->tree) {
+               xmlDocPtr container;
+               xmlNodePtr oldInsert;
+               xmlDocPtr  oldOutput;
+               xsltStackElemPtr oldVar = ctxt->contextVariable;
+
+               /*
+               * Generate a result tree fragment.
+               */
+               container = xsltCreateRVT(ctxt);
+               if (container == NULL)
+                   goto error;
+               /*
+               * NOTE: Local Result Tree Fragments of params/variables
+               * are not registered globally anymore; the life-time
+               * is not directly dependant of the param/variable itself.
+               *
+               * OLD: xsltRegisterTmpRVT(ctxt, container);
+               */
+               /*
+               * Attach the Result Tree Fragment to the variable;
+               * when the variable is freed, it will also free 
+               * the Result Tree Fragment.
+               */
+               variable->fragment = container;
+               
+               oldOutput = ctxt->output;
+               oldInsert = ctxt->insert;               
+               
+               ctxt->output = container;
+               ctxt->insert = (xmlNodePtr) container;
+               ctxt->contextVariable = variable;
+               /*
+               * Process the sequence constructor (variable->tree).
+               * The resulting tree will be held by @container.
+               */
+               xsltApplyOneTemplate(ctxt, ctxt->node, variable->tree,
+                   NULL, NULL);
+
+               ctxt->contextVariable = oldVar;         
+               ctxt->insert = oldInsert;
+               ctxt->output = oldOutput;
+               
+               result = xmlXPathNewValueTree((xmlNodePtr) container);
+           }
+           if (result == NULL) {
+               result = xmlXPathNewCString("");
+           } else {
+               /*
+               * Freeing is not handled there anymore.
+               * QUESTION TODO: What does the above comment mean?
+               */
+               result->boolval = 0; 
+           }
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+#ifdef LIBXML_DEBUG_ENABLED
+
+           if ((xsltGenericDebugContext == stdout) ||
+               (xsltGenericDebugContext == stderr))
+               xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
+                                       result, 0);
+#endif
+#endif
+       }
+    }
+
+error:
+    ctxt->inst = oldInst;
+    return(result);
+}
+
+/**
+ * xsltEvalGlobalVariable:
+ * @elem:  the variable or parameter
+ * @ctxt:  the XSLT transformation context
+ *
+ * Evaluates a the value of a global xsl:variable or
+ * xsl:param declaration.
+ *
+ * Returns the XPath Object value or NULL in case of error
+ */
+static xmlXPathObjectPtr
+xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt)
+{
+    xmlXPathObjectPtr result = NULL;
+    xmlNodePtr oldInst;
+    const xmlChar* oldVarName;
+
+#ifdef XSLT_REFACTORED
+    xsltStyleBasicItemVariablePtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((ctxt == NULL) || (elem == NULL))
+       return(NULL);
+    if (elem->computed)
+       return(elem->value);
+
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+       "Evaluating global variable %s\n", elem->name));
+#endif
+
+#ifdef WITH_DEBUGGER
+    if ((ctxt->debugStatus != XSLT_DEBUG_NONE) &&
+        elem->comp && elem->comp->inst)
+        xslHandleDebugger(elem->comp->inst, NULL, NULL, ctxt);
+#endif
+
+    oldInst = ctxt->inst;
+    comp = elem->comp;
+    oldVarName = elem->name;
+    elem->name = xsltComputingGlobalVarMarker;
+    /*
+    * OPTIMIZE TODO: We should consider instantiating global vars/params
+    *  on-demand. The vars/params don't need to be evaluated if never
+    *  called; and in the case of global params, if values for such params
+    *  are provided by the user.
+    */
+    if (elem->select != NULL) {                
+       xmlXPathCompExprPtr xpExpr = NULL;
+       xmlDocPtr oldXPDoc;
+       xmlNodePtr oldXPContextNode;
+       int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
+       xmlNsPtr *oldXPNamespaces;
+       xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;
+
+       if ((comp != NULL) && (comp->comp != NULL)) {
+           xpExpr = comp->comp;
+       } else {
+           xpExpr = xmlXPathCompile(elem->select);
+       }
+       if (xpExpr == NULL)
+           goto error;
+       
+       
+       if (comp != NULL)
+           ctxt->inst = comp->inst;
+       else
+           ctxt->inst = NULL;
+       /*
+       * SPEC XSLT 1.0:
+       * "At top-level, the expression or template specifying the
+       *  variable value is evaluated with the same context as that used
+       *  to process the root node of the source document: the current
+       *  node is the root node of the source document and the current
+       *  node list is a list containing just the root node of the source
+       *  document."   
+       */
+       /*
+       * Save context states.
+       */
+       oldXPDoc = xpctxt->doc;
+       oldXPContextNode = xpctxt->node;
+       oldXPProximityPosition = xpctxt->proximityPosition;
+       oldXPContextSize = xpctxt->contextSize;
+       oldXPNamespaces = xpctxt->namespaces;
+       oldXPNsNr = xpctxt->nsNr;
+               
+       xpctxt->node = ctxt->initialContextNode;
+       xpctxt->doc = ctxt->initialContextDoc;
+       xpctxt->contextSize = 1;
+       xpctxt->proximityPosition = 1;
+               
+       if (comp != NULL) {
+           
+#ifdef XSLT_REFACTORED
+           if (comp->inScopeNs != NULL) {
+               xpctxt->namespaces = comp->inScopeNs->list;
+               xpctxt->nsNr = comp->inScopeNs->xpathNumber;
+           } else {
+               xpctxt->namespaces = NULL;
+               xpctxt->nsNr = 0;
+           }
+#else
+           xpctxt->namespaces = comp->nsList;
+           xpctxt->nsNr = comp->nsNr;
+#endif
+       } else {
+           xpctxt->namespaces = NULL;
+           xpctxt->nsNr = 0;
+       }
+       
+       result = xmlXPathCompiledEval(xpExpr, xpctxt);
+
+       /*
+       * Restore Context states.
+       */
+       xpctxt->doc = oldXPDoc;
+       xpctxt->node = oldXPContextNode;
+       xpctxt->contextSize = oldXPContextSize;
+       xpctxt->proximityPosition = oldXPProximityPosition;
+       xpctxt->namespaces = oldXPNamespaces;
+       xpctxt->nsNr = oldXPNsNr;
+
+       if ((comp == NULL) || (comp->comp == NULL))
+           xmlXPathFreeCompExpr(xpExpr);
+       if (result == NULL) {
+           if (comp == NULL)
+               xsltTransformError(ctxt, NULL, NULL,
+                   "Evaluating global variable %s failed\n", elem->name);
+           else
+               xsltTransformError(ctxt, NULL, comp->inst,
+                   "Evaluating global variable %s failed\n", elem->name);
+           ctxt->state = XSLT_STATE_STOPPED;
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+#ifdef LIBXML_DEBUG_ENABLED
+       } else {
+           if ((xsltGenericDebugContext == stdout) ||
+               (xsltGenericDebugContext == stderr))
+               xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
+                                       result, 0);
+#endif
+#endif
+       }
+    } else {
+       if (elem->tree == NULL) {
+           result = xmlXPathNewCString("");
+       } else {
+           xmlDocPtr container;
+           xmlNodePtr oldInsert;
+           xmlDocPtr  oldOutput, oldXPDoc;         
+           /*
+           * Generate a result tree fragment.
+           */
+           container = xsltCreateRVT(ctxt);
+           if (container == NULL)
+               goto error;
+           /*
+           * Let the lifetime of the tree fragment be handled by
+           * the Libxslt's garbage collector.
+           */
+           xsltRegisterPersistRVT(ctxt, container);        
+
+           oldOutput = ctxt->output;
+           oldInsert = ctxt->insert;
+
+           oldXPDoc = ctxt->xpathCtxt->doc;
+           
+           ctxt->output = container;       
+           ctxt->insert = (xmlNodePtr) container;
+
+           ctxt->xpathCtxt->doc = ctxt->initialContextDoc;
+           /*
+           * Process the sequence constructor.
+           */
+           xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
+
+           ctxt->xpathCtxt->doc = oldXPDoc;
+
+           ctxt->insert = oldInsert;
+           ctxt->output = oldOutput;
+           
+           result = xmlXPathNewValueTree((xmlNodePtr) container);
+           if (result == NULL) {
+               result = xmlXPathNewCString("");
+           } else {
+               result->boolval = 0; /* Freeing is not handled there anymore */
+           }
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+#ifdef LIBXML_DEBUG_ENABLED
+           if ((xsltGenericDebugContext == stdout) ||
+               (xsltGenericDebugContext == stderr))
+               xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
+                                       result, 0);
+#endif
+#endif
+       }
+    }
+
+error:
+    elem->name = oldVarName;
+    ctxt->inst = oldInst;
+    if (result != NULL) {
+       elem->value = result;
+       elem->computed = 1;
+    }
+    return(result);
+}
+
+/**
+ * xsltEvalGlobalVariables:
+ * @ctxt:  the XSLT transformation context
+ *
+ * Evaluates all global variables and parameters of a stylesheet.
+ * For internal use only. This is called at start of a transformation.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+int
+xsltEvalGlobalVariables(xsltTransformContextPtr ctxt) {
+    xsltStackElemPtr elem;
+    xsltStylesheetPtr style;    
+
+    if ((ctxt == NULL) || (ctxt->document == NULL))
+       return(-1);
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+       "Registering global variables\n"));
+#endif
+    /*
+     * Walk the list from the stylesheets and populate the hash table
+     */
+    style = ctxt->style;
+    while (style != NULL) {
+       elem = style->variables;
+       
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+       if ((style->doc != NULL) && (style->doc->URL != NULL)) {
+           XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+                            "Registering global variables from %s\n",
+                            style->doc->URL));
+       }
+#endif
+
+       while (elem != NULL) {
+           xsltStackElemPtr def;
+
+           /*
+            * Global variables are stored in the variables pool.
+            */
+           def = (xsltStackElemPtr) 
+                   xmlHashLookup2(ctxt->globalVars,
+                                elem->name, elem->nameURI);
+           if (def == NULL) {
+
+               def = xsltCopyStackElem(elem);
+               xmlHashAddEntry2(ctxt->globalVars,
+                                elem->name, elem->nameURI, def);
+           } else if ((elem->comp != NULL) &&
+                      (elem->comp->type == XSLT_FUNC_VARIABLE)) {
+               /*
+                * Redefinition of variables from a different stylesheet
+                * should not generate a message.
+                */
+               if ((elem->comp->inst != NULL) &&
+                   (def->comp != NULL) && (def->comp->inst != NULL) &&
+                   (elem->comp->inst->doc == def->comp->inst->doc))
+               {
+                   xsltTransformError(ctxt, style, elem->comp->inst,
+                       "Global variable %s already defined\n", elem->name);
+                   if (style != NULL) style->errors++;
+               }
+           }
+           elem = elem->next;
+       }
+
+       style = xsltNextImport(style);
+    }
+
+    /*
+     * This part does the actual evaluation
+     */    
+    xmlHashScan(ctxt->globalVars,
+               (xmlHashScanner) xsltEvalGlobalVariable, ctxt);
+
+    return(0);
+}
+
+/**
+ * xsltRegisterGlobalVariable:
+ * @style:  the XSLT transformation context
+ * @name:  the variable name
+ * @ns_uri:  the variable namespace URI
+ * @sel:  the expression which need to be evaluated to generate a value
+ * @tree:  the subtree if sel is NULL
+ * @comp:  the precompiled value
+ * @value:  the string value if available
+ *
+ * Register a new variable value. If @value is NULL it unregisters
+ * the variable
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+xsltRegisterGlobalVariable(xsltStylesheetPtr style, const xmlChar *name,
+                    const xmlChar *ns_uri, const xmlChar *sel,
+                    xmlNodePtr tree, xsltStylePreCompPtr comp,
+                    const xmlChar *value) {
+    xsltStackElemPtr elem, tmp;
+    if (style == NULL)
+       return(-1);
+    if (name == NULL)
+       return(-1);
+    if (comp == NULL)
+       return(-1);
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    if (comp->type == XSLT_FUNC_PARAM)
+       xsltGenericDebug(xsltGenericDebugContext,
+                        "Defining global param %s\n", name);
+    else
+       xsltGenericDebug(xsltGenericDebugContext,
+                        "Defining global variable %s\n", name);
+#endif
+
+    elem = xsltNewStackElem(NULL);
+    if (elem == NULL)
+       return(-1);
+    elem->comp = comp;
+    elem->name = xmlDictLookup(style->dict, name, -1);
+    elem->select = xmlDictLookup(style->dict, sel, -1);
+    if (ns_uri)
+       elem->nameURI = xmlDictLookup(style->dict, ns_uri, -1);
+    elem->tree = tree;
+    tmp = style->variables;
+    if (tmp == NULL) {
+       elem->next = NULL;
+       style->variables = elem;
+    } else {
+       while (tmp != NULL) {
+           if ((elem->comp->type == XSLT_FUNC_VARIABLE) &&
+               (tmp->comp->type == XSLT_FUNC_VARIABLE) &&
+               (xmlStrEqual(elem->name, tmp->name)) &&
+               ((elem->nameURI == tmp->nameURI) ||
+                (xmlStrEqual(elem->nameURI, tmp->nameURI))))
+           {
+               xsltTransformError(NULL, style, comp->inst,
+               "redefinition of global variable %s\n", elem->name);
+               style->errors++;
+           }
+           if (tmp->next == NULL)
+               break;
+           tmp = tmp->next;
+       }
+       elem->next = NULL;
+       tmp->next = elem;
+    }
+    if (value != NULL) {
+       elem->computed = 1;
+       elem->value = xmlXPathNewString(value);
+    }
+    return(0);
+}
+
+/**
+ * xsltProcessUserParamInternal
+ *
+ * @ctxt:  the XSLT transformation context
+ * @name:  a null terminated parameter name
+ * @value: a null terminated value (may be an XPath expression)
+ * @eval:  0 to treat the value literally, else evaluate as XPath expression
+ *
+ * If @eval is 0 then @value is treated literally and is stored in the global
+ * parameter/variable table without any change.
+ *
+ * Uf @eval is 1 then @value is treated as an XPath expression and is
+ * evaluated.  In this case, if you want to pass a string which will be
+ * interpreted literally then it must be enclosed in single or double quotes.
+ * If the string contains single quotes (double quotes) then it cannot be
+ * enclosed single quotes (double quotes).  If the string which you want to
+ * be treated literally contains both single and double quotes (e.g. Meet
+ * at Joe's for "Twelfth Night" at 7 o'clock) then there is no suitable
+ * quoting character.  You cannot use &apos; or &quot; inside the string
+ * because the replacement of character entities with their equivalents is
+ * done at a different stage of processing.  The solution is to call
+ * xsltQuoteUserParams or xsltQuoteOneUserParam.
+ *
+ * This needs to be done on parsed stylesheets before starting to apply
+ * transformations.  Normally this will be called (directly or indirectly)
+ * only from xsltEvalUserParams, xsltEvalOneUserParam, xsltQuoteUserParams,
+ * or xsltQuoteOneUserParam.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+
+static
+int
+xsltProcessUserParamInternal(xsltTransformContextPtr ctxt,
+                            const xmlChar * name,
+                            const xmlChar * value,
+                            int eval) {
+
+    xsltStylesheetPtr style;
+    const xmlChar *prefix;
+    const xmlChar *href;
+    xmlXPathCompExprPtr xpExpr;
+    xmlXPathObjectPtr result;
+    
+    xsltStackElemPtr elem;
+    int res;
+    void *res_ptr;
+
+    if (ctxt == NULL)
+       return(-1);
+    if (name == NULL)
+       return(0);
+    if (value == NULL)
+       return(0);
+
+    style = ctxt->style;
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+           "Evaluating user parameter %s=%s\n", name, value));
+#endif
+
+    /*
+     * Name lookup
+     */
+
+    name = xsltSplitQName(ctxt->dict, name, &prefix);
+    href = NULL;
+    if (prefix != NULL) {
+       xmlNsPtr ns;
+
+       ns = xmlSearchNs(style->doc, xmlDocGetRootElement(style->doc),
+                        prefix);
+       if (ns == NULL) {
+           xsltTransformError(ctxt, style, NULL,
+           "user param : no namespace bound to prefix %s\n", prefix);
+           href = NULL;
+       } else {
+           href = ns->href;
+       }
+    }
+
+    if (name == NULL)
+       return (-1);
+
+    res_ptr = xmlHashLookup2(ctxt->globalVars, name, href);
+    if (res_ptr != 0) {
+       xsltTransformError(ctxt, style, NULL,
+           "Global parameter %s already defined\n", name);
+    }
+    if (ctxt->globalVars == NULL)
+       ctxt->globalVars = xmlHashCreate(20);
+
+    /*
+     * do not overwrite variables with parameters from the command line
+     */
+    while (style != NULL) {
+        elem = ctxt->style->variables;
+       while (elem != NULL) {
+           if ((elem->comp != NULL) &&
+               (elem->comp->type == XSLT_FUNC_VARIABLE) &&
+               (xmlStrEqual(elem->name, name)) &&
+               (xmlStrEqual(elem->nameURI, href))) {
+               return(0);
+           }
+            elem = elem->next;
+       }
+        style = xsltNextImport(style);
+    }
+    style = ctxt->style;
+    elem = NULL;
+
+    /*
+     * Do the evaluation if @eval is non-zero.
+     */
+
+    result = NULL;
+    if (eval != 0) {
+        xpExpr = xmlXPathCompile(value);
+       if (xpExpr != NULL) {
+           xmlDocPtr oldXPDoc;
+           xmlNodePtr oldXPContextNode;
+           int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
+           xmlNsPtr *oldXPNamespaces;
+           xmlXPathContextPtr xpctxt = ctxt->xpathCtxt;
+           /*
+           * SPEC XSLT 1.0:
+           * "At top-level, the expression or template specifying the
+           *  variable value is evaluated with the same context as that used
+           *  to process the root node of the source document: the current
+           *  node is the root node of the source document and the current
+           *  node list is a list containing just the root node of the source
+           *  document."
+           */
+           xpctxt->doc = ctxt->tmpDoc;
+           /*
+           * Save context states.
+           */
+           oldXPDoc = xpctxt->doc;
+           oldXPContextNode = xpctxt->node;
+           oldXPProximityPosition = xpctxt->proximityPosition;
+           oldXPContextSize = xpctxt->contextSize;
+           oldXPNamespaces = xpctxt->namespaces;
+           oldXPNsNr = xpctxt->nsNr;
+           
+           xpctxt->node = ctxt->initialContextNode;
+           xpctxt->doc = ctxt->initialContextDoc;
+           xpctxt->contextSize = 1;
+           xpctxt->proximityPosition = 1;
+           /* 
+           * There is really no in scope namespace for parameters on the
+           * command line.
+           */
+           xpctxt->namespaces = NULL;
+           xpctxt->nsNr = 0;      
+           
+           result = xmlXPathCompiledEval(xpExpr, xpctxt);
+           
+           /*
+           * Restore Context states.
+           */
+           xpctxt->doc = oldXPDoc;
+           xpctxt->node = oldXPContextNode;
+           xpctxt->contextSize = oldXPContextSize;
+           xpctxt->proximityPosition = oldXPProximityPosition;
+           xpctxt->namespaces = oldXPNamespaces;
+           xpctxt->nsNr = oldXPNsNr;
+           
+           xmlXPathFreeCompExpr(xpExpr);
+       }
+       if (result == NULL) {
+           xsltTransformError(ctxt, style, NULL,
+               "Evaluating user parameter %s failed\n", name);
+           ctxt->state = XSLT_STATE_STOPPED;
+           return(-1);
+       }
+    }
+
+    /* 
+     * If @eval is 0 then @value is to be taken literally and result is NULL
+     * 
+     * If @eval is not 0, then @value is an XPath expression and has been
+     * successfully evaluated and result contains the resulting value and
+     * is not NULL.
+     *
+     * Now create an xsltStackElemPtr for insertion into the context's
+     * global variable/parameter hash table.
+     */
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+#ifdef LIBXML_DEBUG_ENABLED
+    if ((xsltGenericDebugContext == stdout) ||
+        (xsltGenericDebugContext == stderr))
+           xmlXPathDebugDumpObject((FILE *)xsltGenericDebugContext,
+                                   result, 0);
+#endif
+#endif
+
+    elem = xsltNewStackElem(NULL);
+    if (elem != NULL) {
+       elem->name = name;
+       elem->select = xmlDictLookup(ctxt->dict, value, -1);
+       if (href != NULL)
+           elem->nameURI = xmlDictLookup(ctxt->dict, href, -1);
+       elem->tree = NULL;
+       elem->computed = 1;
+       if (eval == 0) {
+           elem->value = xmlXPathNewString(value);
+       } 
+       else {
+           elem->value = result;
+       }
+    }
+
+    /*
+     * Global parameters are stored in the XPath context variables pool.
+     */
+
+    res = xmlHashAddEntry2(ctxt->globalVars, name, href, elem);
+    if (res != 0) {
+       xsltFreeStackElem(elem);
+       xsltTransformError(ctxt, style, NULL,
+           "Global parameter %s already defined\n", name);
+    }
+    return(0);
+}
+
+/**
+ * xsltEvalUserParams:
+ *
+ * @ctxt:  the XSLT transformation context
+ * @params:  a NULL terminated array of parameters name/value tuples
+ *
+ * Evaluate the global variables of a stylesheet. This needs to be
+ * done on parsed stylesheets before starting to apply transformations.
+ * Each of the parameters is evaluated as an XPath expression and stored
+ * in the global variables/parameter hash table.  If you want your
+ * parameter used literally, use xsltQuoteUserParams.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+int
+xsltEvalUserParams(xsltTransformContextPtr ctxt, const char **params) {
+    int indx = 0;
+    const xmlChar *name;
+    const xmlChar *value;
+
+    if (params == NULL)
+       return(0);
+    while (params[indx] != NULL) {
+       name = (const xmlChar *) params[indx++];
+       value = (const xmlChar *) params[indx++];
+       if (xsltEvalOneUserParam(ctxt, name, value) != 0) 
+           return(-1);
+    }
+    return 0;
+}
+
+/**
+ * xsltQuoteUserParams:
+ *
+ * @ctxt:  the XSLT transformation context
+ * @params:  a NULL terminated arry of parameters names/values tuples
+ *
+ * Similar to xsltEvalUserParams, but the values are treated literally and
+ * are * *not* evaluated as XPath expressions. This should be done on parsed
+ * stylesheets before starting to apply transformations.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+int
+xsltQuoteUserParams(xsltTransformContextPtr ctxt, const char **params) {
+    int indx = 0;
+    const xmlChar *name;
+    const xmlChar *value;
+
+    if (params == NULL)
+       return(0);
+    while (params[indx] != NULL) {
+       name = (const xmlChar *) params[indx++];
+       value = (const xmlChar *) params[indx++];
+       if (xsltQuoteOneUserParam(ctxt, name, value) != 0) 
+           return(-1);
+    }
+    return 0;
+}
+
+/**
+ * xsltEvalOneUserParam:
+ * @ctxt:  the XSLT transformation context
+ * @name:  a null terminated string giving the name of the parameter
+ * @value:  a null terminated string giving the XPath expression to be evaluated
+ *
+ * This is normally called from xsltEvalUserParams to process a single
+ * parameter from a list of parameters.  The @value is evaluated as an
+ * XPath expression and the result is stored in the context's global
+ * variable/parameter hash table.
+ *
+ * To have a parameter treated literally (not as an XPath expression)
+ * use xsltQuoteUserParams (or xsltQuoteOneUserParam).  For more
+ * details see description of xsltProcessOneUserParamInternal.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+
+int
+xsltEvalOneUserParam(xsltTransformContextPtr ctxt,
+                    const xmlChar * name,
+                    const xmlChar * value) {
+    return xsltProcessUserParamInternal(ctxt, name, value,
+                                       1 /* xpath eval ? */);
+}
+
+/**
+ * xsltQuoteOneUserParam:
+ * @ctxt:  the XSLT transformation context
+ * @name:  a null terminated string giving the name of the parameter
+ * @value:  a null terminated string giving the parameter value
+ *
+ * This is normally called from xsltQuoteUserParams to process a single
+ * parameter from a list of parameters.  The @value is stored in the
+ * context's global variable/parameter hash table.
+ *
+ * Returns 0 in case of success, -1 in case of error.
+ */
+
+int
+xsltQuoteOneUserParam(xsltTransformContextPtr ctxt,
+                        const xmlChar * name,
+                        const xmlChar * value) {
+    return xsltProcessUserParamInternal(ctxt, name, value,
+                                       0 /* xpath eval ? */);
+}
+
+/**
+ * xsltBuildVariable:
+ * @ctxt:  the XSLT transformation context
+ * @comp:  the precompiled form
+ * @tree:  the tree if select is NULL
+ *
+ * Computes a new variable value.
+ *
+ * Returns the xsltStackElemPtr or NULL in case of error
+ */
+static xsltStackElemPtr
+xsltBuildVariable(xsltTransformContextPtr ctxt,
+                 xsltStylePreCompPtr castedComp,
+                 xmlNodePtr tree)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleBasicItemVariablePtr comp =
+       (xsltStyleBasicItemVariablePtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+#endif 
+    xsltStackElemPtr elem;
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+                    "Building variable %s", comp->name));
+    if (comp->select != NULL)
+       XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+                        " select %s", comp->select));
+    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext, "\n"));
+#endif
+
+    elem = xsltNewStackElem(ctxt);
+    if (elem == NULL)
+       return(NULL);
+    elem->comp = (xsltStylePreCompPtr) comp;
+    elem->name = comp->name;
+    elem->select = comp->select;
+    elem->nameURI = comp->ns;
+    elem->tree = tree;
+    elem->value = xsltEvalVariable(ctxt, elem,
+       (xsltStylePreCompPtr) comp);
+    if (elem->value != NULL)
+       elem->computed = 1;
+    return(elem);
+}
+
+/**
+ * xsltRegisterVariable:
+ * @ctxt:  the XSLT transformation context
+ * @comp: the compiled XSLT-variable (or param) instruction
+ * @tree:  the tree if select is NULL
+ * @isParam:  indicates if this is a parameter
+ *
+ * Computes and registers a new variable.
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+static int
+xsltRegisterVariable(xsltTransformContextPtr ctxt,
+                    xsltStylePreCompPtr castedComp,
+                    xmlNodePtr tree, int isParam)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleBasicItemVariablePtr comp =
+       (xsltStyleBasicItemVariablePtr) castedComp;
+#else
+    xsltStylePreCompPtr comp = castedComp;
+    int present;
+#endif
+    xsltStackElemPtr variable;    
+    
+#ifdef XSLT_REFACTORED
+    /*
+    * REFACTORED NOTE: Redefinitions of vars/params are checked
+    *  at compilation time in the refactored code.
+    * xsl:with-param parameters are checked in xsltApplyXSLTTemplate().
+    */
+#else
+    present = xsltCheckStackElem(ctxt, comp->name, comp->ns);
+    if (isParam == 0) {        
+       if ((present != 0) && (present != 3)) {
+           /* TODO: report QName. */
+           xsltTransformError(ctxt, NULL, comp->inst,
+               "XSLT-variable: Redefinition of variable '%s'.\n", comp->name);
+           return(0);
+       }
+    } else if (present != 0) {
+       if ((present == 1) || (present == 2)) {
+           /* TODO: report QName. */
+           xsltTransformError(ctxt, NULL, comp->inst,
+               "XSLT-param: Redefinition of parameter '%s'.\n", comp->name);
+           return(0);
+       }
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+       XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+                "param %s defined by caller\n", comp->name));
+#endif
+       return(0);
+    }
+#endif /* else of XSLT_REFACTORED */
+
+    variable = xsltBuildVariable(ctxt, (xsltStylePreCompPtr) comp, tree);
+    xsltAddStackElem(ctxt, variable);
+    return(0);
+}
+
+/**
+ * xsltGlobalVariableLookup:
+ * @ctxt:  the XSLT transformation context
+ * @name:  the variable name
+ * @ns_uri:  the variable namespace URI
+ *
+ * Search in the Variable array of the context for the given
+ * variable value.
+ *
+ * Returns the value or NULL if not found
+ */
+static xmlXPathObjectPtr
+xsltGlobalVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
+                        const xmlChar *ns_uri) {
+    xsltStackElemPtr elem;
+    xmlXPathObjectPtr ret = NULL;
+
+    /*
+     * Lookup the global variables in XPath global variable hash table
+     */
+    if ((ctxt->xpathCtxt == NULL) || (ctxt->globalVars == NULL))
+       return(NULL);
+    elem = (xsltStackElemPtr)
+           xmlHashLookup2(ctxt->globalVars, name, ns_uri);
+    if (elem == NULL) {
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+       XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+                        "global variable not found %s\n", name));
+#endif
+       return(NULL);
+    }
+    /*
+    * URGENT TODO: Move the detection of recursive definitions
+    * to compile-time.
+    */
+    if (elem->computed == 0) {
+       if (elem->name == xsltComputingGlobalVarMarker) {
+           xsltTransformError(ctxt, NULL, elem->comp->inst,
+               "Recursive definition of %s\n", name);
+           return(NULL);
+       }
+       ret = xsltEvalGlobalVariable(elem, ctxt);
+    } else
+       ret = elem->value;
+    return(xmlXPathObjectCopy(ret));
+}
+
+/**
+ * xsltVariableLookup:
+ * @ctxt:  the XSLT transformation context
+ * @name:  the variable name
+ * @ns_uri:  the variable namespace URI
+ *
+ * Search in the Variable array of the context for the given
+ * variable value.
+ *
+ * Returns the value or NULL if not found
+ */
+xmlXPathObjectPtr
+xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
+                  const xmlChar *ns_uri) {
+    xsltStackElemPtr elem;
+
+    if (ctxt == NULL)
+       return(NULL);
+
+    elem = xsltStackLookup(ctxt, name, ns_uri);
+    if (elem == NULL) {
+       return(xsltGlobalVariableLookup(ctxt, name, ns_uri));
+    }
+    if (elem->computed == 0) {
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+       XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+                        "uncomputed variable %s\n", name));
+#endif
+        elem->value = xsltEvalVariable(ctxt, elem, NULL);
+       elem->computed = 1;
+    }
+    if (elem->value != NULL)
+       return(xmlXPathObjectCopy(elem->value));
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+                    "variable not found %s\n", name));
+#endif
+    return(NULL);
+}
+
+/**
+ * xsltParseStylesheetCallerParam:
+ * @ctxt:  the XSLT transformation context 
+ * @inst:  the xsl:with-param instruction element
+ *
+ * Processes an xsl:with-param instruction at transformation time.
+ * The value is compute, but not recorded.
+ * NOTE that this is also called with an *xsl:param* element
+ * from exsltFuncFunctionFunction(). 
+ *
+ * Returns the new xsltStackElemPtr or NULL
+ */
+
+xsltStackElemPtr
+xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr inst)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleBasicItemVariablePtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    xmlNodePtr tree = NULL; /* The first child node of the instruction or
+                               the instruction itself. */
+    xsltStackElemPtr param = NULL;
+    
+    if ((ctxt == NULL) || (inst == NULL))
+       return(NULL);
+
+#ifdef XSLT_REFACTORED
+    comp = (xsltStyleBasicItemVariablePtr) inst->psvi;
+#else
+    comp = (xsltStylePreCompPtr) inst->psvi;
+#endif
+    
+    if (comp == NULL) {
+        xsltTransformError(ctxt, NULL, inst,
+           "Internal error in xsltParseStylesheetCallerParam(): "
+           "The XSLT 'with-param' instruction was not compiled.\n");
+        return(NULL);
+    }
+    if (comp->name == NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+           "Internal error in xsltParseStylesheetCallerParam(): "
+           "XSLT 'with-param': The attribute 'name' was not compiled.\n");
+       return(NULL);
+    }
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+           "Handling xsl:with-param %s\n", comp->name));
+#endif
+
+    if (comp->select == NULL) {
+       tree = inst->children;
+    } else {
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+       XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+           "        select %s\n", comp->select));
+#endif
+       tree = inst;
+    }
+
+    param = xsltBuildVariable(ctxt, (xsltStylePreCompPtr) comp, tree);
+
+    return(param);
+}
+
+/**
+ * xsltParseGlobalVariable:
+ * @style:  the XSLT stylesheet
+ * @cur:  the "variable" element
+ *
+ * Parses a global XSLT 'variable' declaration at compilation time
+ * and registers it
+ */
+void
+xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemVariablePtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((cur == NULL) || (style == NULL))
+       return;
+    
+#ifdef XSLT_REFACTORED
+    /*
+    * Note that xsltStylePreCompute() will be called from
+    * xslt.c only.
+    */
+    comp = (xsltStyleItemVariablePtr) cur->psvi;
+#else
+    xsltStylePreCompute(style, cur);
+    comp = (xsltStylePreCompPtr) cur->psvi;
+#endif
+    if (comp == NULL) {
+       xsltTransformError(NULL, style, cur,
+            "xsl:variable : compilation failed\n");
+       return;
+    }
+
+    if (comp->name == NULL) {
+       xsltTransformError(NULL, style, cur,
+           "xsl:variable : missing name attribute\n");
+       return;
+    }
+
+    /*
+    * Parse the content (a sequence constructor) of xsl:variable.
+    */
+    if (cur->children != NULL) {
+#ifdef XSLT_REFACTORED 
+        xsltParseSequenceConstructor(XSLT_CCTXT(style), cur->children);
+#else
+        xsltParseTemplateContent(style, cur);
+#endif
+    }
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    xsltGenericDebug(xsltGenericDebugContext,
+       "Registering global variable %s\n", comp->name);
+#endif
+
+    xsltRegisterGlobalVariable(style, comp->name, comp->ns,
+       comp->select, cur->children, (xsltStylePreCompPtr) comp,
+       NULL);
+}
+
+/**
+ * xsltParseGlobalParam:
+ * @style:  the XSLT stylesheet
+ * @cur:  the "param" element
+ *
+ * parse an XSLT transformation param declaration and record
+ * its value.
+ */
+
+void
+xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemParamPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((cur == NULL) || (style == NULL))
+       return;
+    
+#ifdef XSLT_REFACTORED
+    /*
+    * Note that xsltStylePreCompute() will be called from
+    * xslt.c only.
+    */
+    comp = (xsltStyleItemParamPtr) cur->psvi;
+#else
+    xsltStylePreCompute(style, cur);
+    comp = (xsltStylePreCompPtr) cur->psvi;
+#endif    
+    if (comp == NULL) {
+       xsltTransformError(NULL, style, cur,
+            "xsl:param : compilation failed\n");
+       return;
+    }
+
+    if (comp->name == NULL) {
+       xsltTransformError(NULL, style, cur,
+           "xsl:param : missing name attribute\n");
+       return;
+    }
+
+    /*
+    * Parse the content (a sequence constructor) of xsl:param.
+    */
+    if (cur->children != NULL) {
+#ifdef XSLT_REFACTORED 
+        xsltParseSequenceConstructor(XSLT_CCTXT(style), cur->children);
+#else
+        xsltParseTemplateContent(style, cur);
+#endif
+    }
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    xsltGenericDebug(xsltGenericDebugContext,
+       "Registering global param %s\n", comp->name);
+#endif
+
+    xsltRegisterGlobalVariable(style, comp->name, comp->ns,
+       comp->select, cur->children, (xsltStylePreCompPtr) comp,
+       NULL);
+}
+
+/**
+ * xsltParseStylesheetVariable:
+ * @ctxt:  the XSLT transformation context
+ * @inst:  the xsl:variable instruction element
+ *
+ * Registers a local XSLT 'variable' instruction at transformation time
+ * and evaluates its value.
+ */
+void
+xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr inst)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemVariablePtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((inst == NULL) || (ctxt == NULL))
+       return;
+
+    comp = inst->psvi;
+    if (comp == NULL) {
+        xsltTransformError(ctxt, NULL, inst,
+           "Internal error in xsltParseStylesheetVariable(): "
+           "The XSLT 'variable' instruction was not compiled.\n");
+        return;
+    }
+    if (comp->name == NULL) {
+       xsltTransformError(ctxt, NULL, inst,
+           "Internal error in xsltParseStylesheetVariable(): "
+           "The attribute 'name' was not compiled.\n");
+       return;
+    }
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+       "Registering variable '%s'\n", comp->name));
+#endif
+
+    xsltRegisterVariable(ctxt, (xsltStylePreCompPtr) comp, inst->children, 0);
+}
+
+/**
+ * xsltParseStylesheetParam:
+ * @ctxt:  the XSLT transformation context
+ * @cur:  the XSLT 'param' element
+ *
+ * Registers a local XSLT 'param' declaration at transformation time and
+ * evaluates its value.
+ */
+void
+xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur)
+{
+#ifdef XSLT_REFACTORED
+    xsltStyleItemParamPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+
+    if ((cur == NULL) || (ctxt == NULL))
+       return;
+
+    comp = cur->psvi;
+    if ((comp == NULL) || (comp->name == NULL)) {
+       xsltTransformError(ctxt, NULL, cur,
+           "Internal error in xsltParseStylesheetParam(): "
+           "The XSLT 'param' declaration was not compiled correctly.\n");
+       return;
+    }
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+       "Registering param %s\n", comp->name));
+#endif
+
+    xsltRegisterVariable(ctxt, (xsltStylePreCompPtr) comp, cur->children, 1);
+}
+
+/**
+ * xsltFreeGlobalVariables:
+ * @ctxt:  the XSLT transformation context
+ *
+ * Free up the data associated to the global variables
+ * its value.
+ */
+
+void
+xsltFreeGlobalVariables(xsltTransformContextPtr ctxt) {
+    xmlHashFree(ctxt->globalVars, (xmlHashDeallocator) xsltFreeStackElem);
+}
+
+/**
+ * xsltXPathVariableLookup:
+ * @ctxt:  a void * but the the XSLT transformation context actually
+ * @name:  the variable name
+ * @ns_uri:  the variable namespace URI
+ *
+ * This is the entry point when a varibale is needed by the XPath
+ * interpretor.
+ *
+ * Returns the value or NULL if not found
+ */
+xmlXPathObjectPtr
+xsltXPathVariableLookup(void *ctxt, const xmlChar *name,
+                       const xmlChar *ns_uri) {
+    xsltTransformContextPtr tctxt;
+    xmlXPathObjectPtr valueObj = NULL;
+
+    if ((ctxt == NULL) || (name == NULL))
+       return(NULL);
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    XSLT_TRACE(((xsltTransformContextPtr)ctxt),XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+           "Lookup variable '%s'\n", name));
+#endif
+    
+    tctxt = (xsltTransformContextPtr) ctxt;
+    /*
+    * Local variables/params ---------------------------------------------
+    *
+    * Do the lookup from the top of the stack, but
+    * don't use params being computed in a call-param
+    * First lookup expects the variable name and URI to
+    * come from the disctionnary and hence pointer comparison.
+    */
+    if (tctxt->varsNr != 0) {
+       int i;
+       xsltStackElemPtr variable = NULL, cur;
+
+       for (i = tctxt->varsNr; i > tctxt->varsBase; i--) {
+           cur = tctxt->varsTab[i-1];
+           if ((cur->name == name) && (cur->nameURI == ns_uri)) {
+#if 0
+               stack_addr++;
+#endif
+               variable = cur;
+               goto local_variable_found;
+           }
+           cur = cur->next;
+       }       
+       /*
+       * Redo the lookup with interned strings to avoid string comparison.
+       *
+       * OPTIMIZE TODO: The problem here is, that if we request a
+       *  global variable, then this will be also executed.
+       */
+       {
+           const xmlChar *tmpName = name, *tmpNsName = ns_uri;
+
+           name = xmlDictLookup(tctxt->dict, name, -1);
+           if (ns_uri)
+               ns_uri = xmlDictLookup(tctxt->dict, ns_uri, -1);
+           if ((tmpName != name) || (tmpNsName != ns_uri)) {           
+               for (i = tctxt->varsNr; i > tctxt->varsBase; i--) {
+                   cur = tctxt->varsTab[i-1];
+                   if ((cur->name == name) && (cur->nameURI == ns_uri)) {
+#if 0
+                       stack_cmp++;
+#endif
+                       variable = cur;
+                       goto local_variable_found;
+                   }
+               }
+           }
+       }
+
+local_variable_found:
+
+       if (variable) {
+           if (variable->computed == 0) {
+               
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+               XSLT_TRACE(tctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+                   "uncomputed variable '%s'\n", name));
+#endif
+               variable->value = xsltEvalVariable(tctxt, variable, NULL);
+               variable->computed = 1;
+           }
+           if (variable->value != NULL) {
+               valueObj = xmlXPathObjectCopy(variable->value); 
+           }
+           return(valueObj);
+       }
+    }
+    /*
+    * Global variables/params --------------------------------------------
+    */    
+    if (tctxt->globalVars) {
+       valueObj = xsltGlobalVariableLookup(tctxt, name, ns_uri);
+    }
+
+    if (valueObj == NULL) {
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+    XSLT_TRACE(tctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+                    "variable not found '%s'\n", name));
+#endif
+
+       if (ns_uri) {
+           xsltTransformError(tctxt, NULL, tctxt->inst,
+               "Variable '{%s}%s' has not been declared.\n", ns_uri, name);
+       } else {
+           xsltTransformError(tctxt, NULL, tctxt->inst,
+               "Variable '%s' has not been declared.\n", name);
+       }
+    } else {
+
+#ifdef WITH_XSLT_DEBUG_VARIABLE
+       XSLT_TRACE(tctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
+           "found variable '%s'\n", name));
+#endif
+    }
+
+    return(valueObj);
+}
+
+
index 67899c1..650a2ca 100644 (file)
-/*\r
- * xslt.c: Implemetation of an XSL Transformation 1.0 engine\r
- *\r
- * Reference:\r
- *   XSLT specification\r
- *   http://www.w3.org/TR/1999/REC-xslt-19991116\r
- *\r
- *   Associating Style Sheets with XML documents\r
- *   http://www.w3.org/1999/06/REC-xml-stylesheet-19990629\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * daniel@veillard.com\r
- */\r
-\r
-#define IN_LIBXSLT\r
-#include "libxslt.h"\r
-\r
-#include <string.h>\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/parser.h>\r
-#include <libxml/tree.h>\r
-#include <libxml/valid.h>\r
-#include <libxml/hash.h>\r
-#include <libxml/uri.h>\r
-#include <libxml/xmlerror.h>\r
-#include <libxml/parserInternals.h>\r
-#include <libxml/xpathInternals.h>\r
-#include <libxml/xpath.h>\r
-#include "xslt.h"\r
-#include "xsltInternals.h"\r
-#include "pattern.h"\r
-#include "variables.h"\r
-#include "namespaces.h"\r
-#include "attributes.h"\r
-#include "xsltutils.h"\r
-#include "imports.h"\r
-#include "keys.h"\r
-#include "documents.h"\r
-#include "extensions.h"\r
-#include "preproc.h"\r
-#include "extra.h"\r
-#include "security.h"\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
-#define WITH_XSLT_DEBUG_PARSING\r
-/* #define WITH_XSLT_DEBUG_BLANKS */\r
-#endif\r
-\r
-const char *xsltEngineVersion = LIBXSLT_VERSION_STRING LIBXSLT_VERSION_EXTRA;\r
-const int xsltLibxsltVersion = LIBXSLT_VERSION;\r
-const int xsltLibxmlVersion = LIBXML_VERSION;\r
-\r
-#ifdef XSLT_REFACTORED\r
-\r
-const xmlChar *xsltConstNamespaceNameXSLT = (const xmlChar *) XSLT_NAMESPACE;\r
-\r
-/*\r
-* xsltLiteralResultMarker:\r
-* Marker for Literal result elements, in order to avoid multiple attempts\r
-* to recognize such elements in the stylesheet's tree.\r
-* This marker is set on node->psvi during the initial traversal\r
-* of a stylesheet's node tree.\r
-*\r
-const xmlChar *xsltLiteralResultMarker =\r
-    (const xmlChar *) "Literal Result Element";\r
-*/\r
-\r
-/*\r
-* xsltXSLTTextMarker:\r
-* Marker for xsl:text elements. Used to recognize xsl:text elements\r
-* for post-processing of the stylesheet's tree, where those\r
-* elements are removed from the tree.\r
-*/\r
-const xmlChar *xsltXSLTTextMarker = (const xmlChar *) "XSLT Text Element";\r
-\r
-/*\r
-* xsltXSLTAttrMarker:\r
-* Marker for XSLT attribute on Literal Result Elements.\r
-*/\r
-const xmlChar *xsltXSLTAttrMarker = (const xmlChar *) "LRE XSLT Attr";\r
-\r
-#endif\r
-\r
-/*\r
- * Harmless but avoiding a problem when compiling against a\r
- * libxml <= 2.3.11 without LIBXML_DEBUG_ENABLED\r
- */\r
-#ifndef LIBXML_DEBUG_ENABLED\r
-double xmlXPathStringEvalNumber(const xmlChar *str);\r
-#endif\r
-/*\r
- * Useful macros\r
- */\r
-\r
-#ifdef  IS_BLANK\r
-#undef IS_BLANK\r
-#endif\r
-#define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \\r
-                     ((c) == 0x0D))\r
-\r
-#ifdef IS_BLANK_NODE\r
-#undef IS_BLANK_NODE\r
-#endif\r
-#define IS_BLANK_NODE(n)                                               \\r
-    (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))\r
-\r
-/**\r
- * xsltParseContentError:\r
- *\r
- * @style: the stylesheet\r
- * @node: the node where the error occured\r
- *\r
- * Compile-time error function.\r
- */\r
-static void\r
-xsltParseContentError(xsltStylesheetPtr style,\r
-                      xmlNodePtr node)\r
-{\r
-    if ((style == NULL) || (node == NULL))\r
-       return;\r
-\r
-    if (IS_XSLT_ELEM(node))\r
-       xsltTransformError(NULL, style, node,\r
-           "The XSLT-element '%s' is not allowed at this position.\n",\r
-           node->name);\r
-    else\r
-       xsltTransformError(NULL, style, node,\r
-           "The element '%s' is not allowed at this position.\n",\r
-           node->name);\r
-    style->errors++;\r
-}\r
-\r
-#ifdef XSLT_REFACTORED\r
-#else\r
-/**\r
- * exclPrefixPush:\r
- * @style: the transformation stylesheet\r
- * @value:  the excluded namespace name to push on the stack\r
- *\r
- * Push an excluded namespace name on the stack\r
- *\r
- * Returns the new index in the stack or 0 in case of error\r
- */\r
-static int\r
-exclPrefixPush(xsltStylesheetPtr style, xmlChar * value)\r
-{\r
-    if (style->exclPrefixMax == 0) {\r
-        style->exclPrefixMax = 4;\r
-        style->exclPrefixTab =\r
-            (xmlChar * *)xmlMalloc(style->exclPrefixMax *\r
-                                   sizeof(style->exclPrefixTab[0]));\r
-        if (style->exclPrefixTab == NULL) {\r
-            xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");\r
-            return (0);\r
-        }\r
-    }\r
-    if (style->exclPrefixNr >= style->exclPrefixMax) {\r
-        style->exclPrefixMax *= 2;\r
-        style->exclPrefixTab =\r
-            (xmlChar * *)xmlRealloc(style->exclPrefixTab,\r
-                                    style->exclPrefixMax *\r
-                                    sizeof(style->exclPrefixTab[0]));\r
-        if (style->exclPrefixTab == NULL) {\r
-            xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");\r
-            return (0);\r
-        }\r
-    }\r
-    style->exclPrefixTab[style->exclPrefixNr] = value;\r
-    style->exclPrefix = value;\r
-    return (style->exclPrefixNr++);\r
-}\r
-/**\r
- * exclPrefixPop:\r
- * @style: the transformation stylesheet\r
- *\r
- * Pop an excluded prefix value from the stack\r
- *\r
- * Returns the stored excluded prefix value\r
- */\r
-static xmlChar *\r
-exclPrefixPop(xsltStylesheetPtr style)\r
-{\r
-    xmlChar *ret;\r
-\r
-    if (style->exclPrefixNr <= 0)\r
-        return (0);\r
-    style->exclPrefixNr--;\r
-    if (style->exclPrefixNr > 0)\r
-        style->exclPrefix = style->exclPrefixTab[style->exclPrefixNr - 1];\r
-    else\r
-        style->exclPrefix = NULL;\r
-    ret = style->exclPrefixTab[style->exclPrefixNr];\r
-    style->exclPrefixTab[style->exclPrefixNr] = 0;\r
-    return (ret);\r
-}\r
-#endif\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Helper functions                                *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltInit:\r
- *\r
- * Initializes the processor (e.g. registers built-in extensions,\r
- * etc.)\r
- */\r
-\r
-static int initialized = 0;\r
-\r
-void\r
-xsltInit (void) {\r
-    if (initialized == 0) {\r
-       initialized = 1;\r
-        xsltRegisterAllExtras();\r
-    }\r
-}\r
-\r
-/**\r
- * xsltUninit\r
- *\r
- * Uninitializes the processor.\r
- */\r
-\r
-void\r
-xsltUninit (void) {\r
-    initialized = 0;\r
-}\r
-\r
-/**\r
- * xsltIsBlank:\r
- * @str:  a string\r
- *\r
- * Check if a string is ignorable\r
- *\r
- * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise\r
- */\r
-int\r
-xsltIsBlank(xmlChar *str) {\r
-    if (str == NULL)\r
-       return(1);\r
-    while (*str != 0) {\r
-       if (!(IS_BLANK(*str))) return(0);\r
-       str++;\r
-    }\r
-    return(1);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Routines to handle XSLT data structures                 *\r
- *                                                                     *\r
- ************************************************************************/\r
-static xsltDecimalFormatPtr\r
-xsltNewDecimalFormat(xmlChar *name)\r
-{\r
-    xsltDecimalFormatPtr self;\r
-    /* UTF-8 for 0x2030 */\r
-    static const xmlChar permille[4] = {0xe2, 0x80, 0xb0, 0};\r
-\r
-    self = xmlMalloc(sizeof(xsltDecimalFormat));\r
-    if (self != NULL) {\r
-       self->next = NULL;\r
-       self->name = name;\r
-       \r
-       /* Default values */\r
-       self->digit = xmlStrdup(BAD_CAST("#"));\r
-       self->patternSeparator = xmlStrdup(BAD_CAST(";"));\r
-       self->decimalPoint = xmlStrdup(BAD_CAST("."));\r
-       self->grouping = xmlStrdup(BAD_CAST(","));\r
-       self->percent = xmlStrdup(BAD_CAST("%"));\r
-       self->permille = xmlStrdup(BAD_CAST(permille));\r
-       self->zeroDigit = xmlStrdup(BAD_CAST("0"));\r
-       self->minusSign = xmlStrdup(BAD_CAST("-"));\r
-       self->infinity = xmlStrdup(BAD_CAST("Infinity"));\r
-       self->noNumber = xmlStrdup(BAD_CAST("NaN"));\r
-    }\r
-    return self;\r
-}\r
-\r
-static void\r
-xsltFreeDecimalFormat(xsltDecimalFormatPtr self)\r
-{\r
-    if (self != NULL) {\r
-       if (self->digit)\r
-           xmlFree(self->digit);\r
-       if (self->patternSeparator)\r
-           xmlFree(self->patternSeparator);\r
-       if (self->decimalPoint)\r
-           xmlFree(self->decimalPoint);\r
-       if (self->grouping)\r
-           xmlFree(self->grouping);\r
-       if (self->percent)\r
-           xmlFree(self->percent);\r
-       if (self->permille)\r
-           xmlFree(self->permille);\r
-       if (self->zeroDigit)\r
-           xmlFree(self->zeroDigit);\r
-       if (self->minusSign)\r
-           xmlFree(self->minusSign);\r
-       if (self->infinity)\r
-           xmlFree(self->infinity);\r
-       if (self->noNumber)\r
-           xmlFree(self->noNumber);\r
-       if (self->name)\r
-           xmlFree(self->name);\r
-       xmlFree(self);\r
-    }\r
-}\r
-\r
-static void\r
-xsltFreeDecimalFormatList(xsltStylesheetPtr self)\r
-{\r
-    xsltDecimalFormatPtr iter;\r
-    xsltDecimalFormatPtr tmp;\r
-\r
-    if (self == NULL)\r
-       return;\r
-    \r
-    iter = self->decimalFormat;\r
-    while (iter != NULL) {\r
-       tmp = iter->next;\r
-       xsltFreeDecimalFormat(iter);\r
-       iter = tmp;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltDecimalFormatGetByName:\r
- * @style: the XSLT stylesheet\r
- * @name: the decimal-format name to find\r
- *\r
- * Find decimal-format by name\r
- *\r
- * Returns the xsltDecimalFormatPtr\r
- */\r
-xsltDecimalFormatPtr\r
-xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name)\r
-{\r
-    xsltDecimalFormatPtr result = NULL;\r
-\r
-    if (name == NULL)\r
-       return style->decimalFormat;\r
-\r
-    while (style != NULL) {\r
-       for (result = style->decimalFormat->next;\r
-            result != NULL;\r
-            result = result->next) {\r
-           if (xmlStrEqual(name, result->name))\r
-               return result;\r
-       }\r
-       style = xsltNextImport(style);\r
-    }\r
-    return result;\r
-}\r
-\r
-\r
-/**\r
- * xsltNewTemplate:\r
- *\r
- * Create a new XSLT Template\r
- *\r
- * Returns the newly allocated xsltTemplatePtr or NULL in case of error\r
- */\r
-static xsltTemplatePtr\r
-xsltNewTemplate(void) {\r
-    xsltTemplatePtr cur;\r
-\r
-    cur = (xsltTemplatePtr) xmlMalloc(sizeof(xsltTemplate));\r
-    if (cur == NULL) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-               "xsltNewTemplate : malloc failed\n");\r
-       return(NULL);\r
-    }\r
-    memset(cur, 0, sizeof(xsltTemplate));\r
-    cur->priority = XSLT_PAT_NO_PRIORITY;\r
-    return(cur);\r
-}\r
-\r
-/**\r
- * xsltFreeTemplate:\r
- * @template:  an XSLT template\r
- *\r
- * Free up the memory allocated by @template\r
- */\r
-static void\r
-xsltFreeTemplate(xsltTemplatePtr template) {\r
-    if (template == NULL)\r
-       return;\r
-    if (template->match) xmlFree(template->match);\r
-/*\r
-*   NOTE: @name and @nameURI are put into the string dict now.\r
-*   if (template->name) xmlFree(template->name);\r
-*   if (template->nameURI) xmlFree(template->nameURI);\r
-*/\r
-/*\r
-    if (template->mode) xmlFree(template->mode);\r
-    if (template->modeURI) xmlFree(template->modeURI);\r
- */\r
-    if (template->inheritedNs) xmlFree(template->inheritedNs);\r
-    memset(template, -1, sizeof(xsltTemplate));\r
-    xmlFree(template);\r
-}\r
-\r
-/**\r
- * xsltFreeTemplateList:\r
- * @template:  an XSLT template list\r
- *\r
- * Free up the memory allocated by all the elements of @template\r
- */\r
-static void\r
-xsltFreeTemplateList(xsltTemplatePtr template) {\r
-    xsltTemplatePtr cur;\r
-\r
-    while (template != NULL) {\r
-       cur = template;\r
-       template = template->next;\r
-       xsltFreeTemplate(cur);\r
-    }\r
-}\r
-\r
-#ifdef XSLT_REFACTORED\r
-\r
-static void\r
-xsltFreeNsAliasList(xsltNsAliasPtr item)\r
-{\r
-    xsltNsAliasPtr tmp;\r
-    \r
-    while (item) {\r
-       tmp = item;\r
-       item = item->next;\r
-       xmlFree(tmp);\r
-    } \r
-    return;\r
-}\r
-\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-static void\r
-xsltFreeNamespaceMap(xsltNsMapPtr item)\r
-{\r
-    xsltNsMapPtr tmp;\r
-    \r
-    while (item) {\r
-       tmp = item;\r
-       item = item->next;\r
-       xmlFree(tmp);\r
-    } \r
-    return;\r
-}\r
-\r
-static xsltNsMapPtr\r
-xsltNewNamespaceMapItem(xsltCompilerCtxtPtr cctxt,\r
-                       xmlDocPtr doc,\r
-                       xmlNsPtr ns,\r
-                       xmlNodePtr elem)\r
-{\r
-    xsltNsMapPtr ret;\r
-\r
-    if ((cctxt == NULL) || (doc == NULL) || (ns == NULL))\r
-       return(NULL);\r
-\r
-    ret = (xsltNsMapPtr) xmlMalloc(sizeof(xsltNsMap));\r
-    if (ret == NULL) {\r
-       xsltTransformError(NULL, cctxt->style, elem,\r
-           "Internal error: (xsltNewNamespaceMapItem) "\r
-           "memory allocation failed.\n");\r
-       return(NULL);\r
-    }\r
-    memset(ret, 0, sizeof(xsltNsMap));\r
-    ret->doc = doc;\r
-    ret->ns = ns;\r
-    ret->origNsName = ns->href;\r
-    /*\r
-    * Store the item at current stylesheet-level.\r
-    */\r
-    if (cctxt->psData->nsMap != NULL)\r
-       ret->next = cctxt->psData->nsMap;\r
-    cctxt->psData->nsMap = ret;\r
-\r
-    return(ret);\r
-}\r
-#endif /* XSLT_REFACTORED_XSLT_NSCOMP */\r
-\r
-/**\r
- * xsltCompilerVarInfoFree: \r
- * @cctxt: the compilation context\r
- * \r
- * Frees the list of information for vars/params.\r
- */\r
-static void\r
-xsltCompilerVarInfoFree(xsltCompilerCtxtPtr cctxt)\r
-{\r
-    xsltVarInfoPtr ivar = cctxt->ivars, ivartmp;    \r
-\r
-    while (ivar) {\r
-       ivartmp = ivar;\r
-       ivar = ivar->next;\r
-       xmlFree(ivartmp);\r
-    }\r
-}\r
-\r
-/**\r
- * xsltCompilerCtxtFree:\r
- *\r
- * Free an XSLT compiler context. \r
- */\r
-static void\r
-xsltCompilationCtxtFree(xsltCompilerCtxtPtr cctxt)\r
-{    \r
-    if (cctxt == NULL)\r
-       return;\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "Freeing compilation context\n");\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "### Max inodes: %d\n", cctxt->maxNodeInfos);\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "### Max LREs  : %d\n", cctxt->maxLREs);\r
-#endif\r
-    /*\r
-    * Free node-infos.\r
-    */\r
-    if (cctxt->inodeList != NULL) {\r
-       xsltCompilerNodeInfoPtr tmp, cur = cctxt->inodeList;\r
-       while (cur != NULL) {\r
-           tmp = cur;\r
-           cur = cur->next;\r
-           xmlFree(tmp);\r
-       }\r
-    }\r
-    if (cctxt->tmpList != NULL)\r
-       xsltPointerListFree(cctxt->tmpList);\r
-#ifdef XSLT_REFACTORED_XPATHCOMP\r
-    if (cctxt->xpathCtxt != NULL)\r
-       xmlXPathFreeContext(cctxt->xpathCtxt);\r
-#endif\r
-    if (cctxt->nsAliases != NULL)\r
-       xsltFreeNsAliasList(cctxt->nsAliases);\r
-\r
-    if (cctxt->ivars)\r
-       xsltCompilerVarInfoFree(cctxt);\r
-\r
-    xmlFree(cctxt);\r
-}\r
-\r
-/**\r
- * xsltCompilerCreate:\r
- *\r
- * Creates an XSLT compiler context.\r
- *\r
- * Returns the pointer to the created xsltCompilerCtxt or\r
- *         NULL in case of an internal error.\r
- */\r
-static xsltCompilerCtxtPtr\r
-xsltCompilationCtxtCreate(xsltStylesheetPtr style) {\r
-    xsltCompilerCtxtPtr ret;\r
-\r
-    ret = (xsltCompilerCtxtPtr) xmlMalloc(sizeof(xsltCompilerCtxt));\r
-    if (ret == NULL) {\r
-       xsltTransformError(NULL, style, NULL,\r
-           "xsltCompilerCreate: allocation of compiler "\r
-           "context failed.\n");\r
-       return(NULL);\r
-    }\r
-    memset(ret, 0, sizeof(xsltCompilerCtxt));\r
-\r
-    ret->errSeverity = XSLT_ERROR_SEVERITY_ERROR;\r
-    ret->tmpList = xsltPointerListCreate(20);\r
-    if (ret->tmpList == NULL) {\r
-       goto internal_err;\r
-    }\r
-#ifdef XSLT_REFACTORED_XPATHCOMP\r
-    /*\r
-    * Create the XPath compilation context in order\r
-    * to speed up precompilation of XPath expressions.\r
-    */\r
-    ret->xpathCtxt = xmlXPathNewContext(NULL);\r
-    if (ret->xpathCtxt == NULL)\r
-       goto internal_err;\r
-#endif\r
-    \r
-    return(ret);\r
-\r
-internal_err:\r
-    xsltCompilationCtxtFree(ret);\r
-    return(NULL);\r
-}\r
-\r
-static void\r
-xsltLREEffectiveNsNodesFree(xsltEffectiveNsPtr first)\r
-{\r
-    xsltEffectiveNsPtr tmp;\r
-\r
-    while (first != NULL) {\r
-       tmp = first;\r
-       first = first->nextInStore;\r
-       xmlFree(tmp);\r
-    }\r
-}\r
-\r
-static void\r
-xsltFreePrincipalStylesheetData(xsltPrincipalStylesheetDataPtr data)\r
-{\r
-    if (data == NULL)\r
-       return;\r
-\r
-    if (data->inScopeNamespaces != NULL) {\r
-       int i;\r
-       xsltNsListContainerPtr nsi;\r
-       xsltPointerListPtr list =\r
-           (xsltPointerListPtr) data->inScopeNamespaces;\r
-\r
-       for (i = 0; i < list->number; i++) {\r
-           /*\r
-           * REVISIT TODO: Free info of in-scope namespaces.\r
-           */\r
-           nsi = (xsltNsListContainerPtr) list->items[i];\r
-           if (nsi->list != NULL)\r
-               xmlFree(nsi->list);\r
-           xmlFree(nsi);\r
-       }\r
-       xsltPointerListFree(list);\r
-       data->inScopeNamespaces = NULL;\r
-    }\r
-\r
-    if (data->exclResultNamespaces != NULL) {\r
-       int i;\r
-       xsltPointerListPtr list = (xsltPointerListPtr)\r
-           data->exclResultNamespaces; \r
-       \r
-       for (i = 0; i < list->number; i++)\r
-           xsltPointerListFree((xsltPointerListPtr) list->items[i]);\r
-       \r
-       xsltPointerListFree(list);\r
-       data->exclResultNamespaces = NULL;\r
-    }\r
-\r
-    if (data->extElemNamespaces != NULL) {\r
-       xsltPointerListPtr list = (xsltPointerListPtr)\r
-           data->extElemNamespaces;\r
-       int i;\r
-\r
-       for (i = 0; i < list->number; i++)\r
-           xsltPointerListFree((xsltPointerListPtr) list->items[i]);\r
-\r
-       xsltPointerListFree(list);\r
-       data->extElemNamespaces = NULL;\r
-    }\r
-    if (data->effectiveNs) {\r
-       xsltLREEffectiveNsNodesFree(data->effectiveNs);\r
-       data->effectiveNs = NULL;\r
-    }\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-    xsltFreeNamespaceMap(data->nsMap);\r
-#endif\r
-    xmlFree(data);\r
-}\r
-\r
-static xsltPrincipalStylesheetDataPtr\r
-xsltNewPrincipalStylesheetData(void)\r
-{\r
-    xsltPrincipalStylesheetDataPtr ret;\r
-\r
-    ret = (xsltPrincipalStylesheetDataPtr)\r
-       xmlMalloc(sizeof(xsltPrincipalStylesheetData));\r
-    if (ret == NULL) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-           "xsltNewPrincipalStylesheetData: memory allocation failed.\n");\r
-       return(NULL);\r
-    }\r
-    memset(ret, 0, sizeof(xsltPrincipalStylesheetData));\r
-    \r
-    /*\r
-    * Global list of in-scope namespaces.\r
-    */    \r
-    ret->inScopeNamespaces = xsltPointerListCreate(-1);\r
-    if (ret->inScopeNamespaces == NULL)\r
-       goto internal_err;\r
-    /*\r
-    * Global list of excluded result ns-decls.\r
-    */\r
-    ret->exclResultNamespaces = xsltPointerListCreate(-1);\r
-    if (ret->exclResultNamespaces == NULL)\r
-       goto internal_err;\r
-    /*\r
-    * Global list of extension instruction namespace names.\r
-    */    \r
-    ret->extElemNamespaces = xsltPointerListCreate(-1);\r
-    if (ret->extElemNamespaces == NULL)\r
-       goto internal_err;\r
-\r
-    return(ret);\r
-\r
-internal_err:\r
-\r
-    return(NULL);\r
-}\r
-\r
-#endif\r
-\r
-/**\r
- * xsltNewStylesheet:\r
- *\r
- * Create a new XSLT Stylesheet\r
- *\r
- * Returns the newly allocated xsltStylesheetPtr or NULL in case of error\r
- */\r
-xsltStylesheetPtr\r
-xsltNewStylesheet(void) {\r
-    xsltStylesheetPtr ret = NULL;    \r
-\r
-    ret = (xsltStylesheetPtr) xmlMalloc(sizeof(xsltStylesheet));\r
-    if (ret == NULL) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-               "xsltNewStylesheet : malloc failed\n");\r
-       goto internal_err;\r
-    }\r
-    memset(ret, 0, sizeof(xsltStylesheet));\r
-\r
-    ret->omitXmlDeclaration = -1;\r
-    ret->standalone = -1;\r
-    ret->decimalFormat = xsltNewDecimalFormat(NULL);\r
-    ret->indent = -1;\r
-    ret->errors = 0;\r
-    ret->warnings = 0;\r
-    ret->exclPrefixNr = 0;\r
-    ret->exclPrefixMax = 0;\r
-    ret->exclPrefixTab = NULL;\r
-    ret->extInfos = NULL;\r
-    ret->extrasNr = 0;\r
-    ret->internalized = 1;\r
-    ret->literal_result = 0;\r
-    ret->dict = xmlDictCreate();\r
-#ifdef WITH_XSLT_DEBUG\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "creating dictionary for stylesheet\n");\r
-#endif\r
-\r
-    xsltInit();\r
-\r
-    return(ret);\r
-\r
-internal_err:\r
-    if (ret != NULL)\r
-       xsltFreeStylesheet(ret);\r
-    return(NULL);\r
-}\r
-\r
-/**\r
- * xsltAllocateExtra:\r
- * @style:  an XSLT stylesheet\r
- *\r
- * Allocate an extra runtime information slot statically while compiling\r
- * the stylesheet and return its number\r
- *\r
- * Returns the number of the slot\r
- */\r
-int\r
-xsltAllocateExtra(xsltStylesheetPtr style)\r
-{\r
-    return(style->extrasNr++);\r
-}\r
-\r
-/**\r
- * xsltAllocateExtraCtxt:\r
- * @ctxt:  an XSLT transformation context\r
- *\r
- * Allocate an extra runtime information slot at run-time\r
- * and return its number\r
- * This make sure there is a slot ready in the transformation context\r
- *\r
- * Returns the number of the slot\r
- */\r
-int\r
-xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)\r
-{\r
-    if (ctxt->extrasNr >= ctxt->extrasMax) {\r
-       int i;\r
-       if (ctxt->extrasNr == 0) {\r
-           ctxt->extrasMax = 20;\r
-           ctxt->extras = (xsltRuntimeExtraPtr)\r
-               xmlMalloc(ctxt->extrasMax * sizeof(xsltRuntimeExtra));\r
-           if (ctxt->extras == NULL) {\r
-               xmlGenericError(xmlGenericErrorContext,\r
-                       "xsltAllocateExtraCtxt: out of memory\n");\r
-               ctxt->state = XSLT_STATE_ERROR;\r
-               return(0);\r
-           }\r
-           for (i = 0;i < ctxt->extrasMax;i++) {\r
-               ctxt->extras[i].info = NULL;\r
-               ctxt->extras[i].deallocate = NULL;\r
-               ctxt->extras[i].val.ptr = NULL;\r
-           }\r
-\r
-       } else {\r
-           xsltRuntimeExtraPtr tmp;\r
-\r
-           ctxt->extrasMax += 100;\r
-           tmp = (xsltRuntimeExtraPtr) xmlRealloc(ctxt->extras,\r
-                           ctxt->extrasMax * sizeof(xsltRuntimeExtra));\r
-           if (tmp == NULL) {\r
-               xmlGenericError(xmlGenericErrorContext,\r
-                       "xsltAllocateExtraCtxt: out of memory\n");\r
-               ctxt->state = XSLT_STATE_ERROR;\r
-               return(0);\r
-           }\r
-           ctxt->extras = tmp;\r
-           for (i = ctxt->extrasNr;i < ctxt->extrasMax;i++) {\r
-               ctxt->extras[i].info = NULL;\r
-               ctxt->extras[i].deallocate = NULL;\r
-               ctxt->extras[i].val.ptr = NULL;\r
-           }\r
-       }\r
-    }\r
-    return(ctxt->extrasNr++);\r
-}\r
-\r
-/**\r
- * xsltFreeStylesheetList:\r
- * @style:  an XSLT stylesheet list\r
- *\r
- * Free up the memory allocated by the list @style\r
- */\r
-static void\r
-xsltFreeStylesheetList(xsltStylesheetPtr style) {\r
-    xsltStylesheetPtr next;\r
-\r
-    while (style != NULL) {\r
-       next = style->next;\r
-       xsltFreeStylesheet(style);\r
-       style = next;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltCleanupStylesheetTree:\r
- *\r
- * @doc: the document-node\r
- * @node: the element where the stylesheet is rooted at\r
- *\r
- * Actually @node need not be the document-element, but\r
- * currently Libxslt does not support embedeed stylesheets.\r
- *\r
- * Returns 0 if OK, -1 on API or internal errors.\r
- */\r
-static int\r
-xsltCleanupStylesheetTree(xmlDocPtr doc, xmlNodePtr rootElem)\r
-{    \r
-#if 0 /* TODO: Currently disabled, since probably not needed. */\r
-    xmlNodePtr cur;\r
-\r
-    if ((doc == NULL) || (rootElem == NULL) ||\r
-       (rootElem->type != XML_ELEMENT_NODE) ||\r
-       (doc != rootElem->doc))\r
-       return(-1);\r
-\r
-    /*\r
-    * Cleanup was suggested by Aleksey Sanin:\r
-    * Clear the PSVI field to avoid problems if the\r
-    * node-tree of the stylesheet is intended to be used for\r
-    * further processing by the user (e.g. for compiling it\r
-    * once again - although not recommended).\r
-    */\r
-\r
-    cur = rootElem;\r
-    while (cur != NULL) {\r
-       if (cur->type == XML_ELEMENT_NODE) {\r
-           /*\r
-           * Clear the PSVI field.\r
-           */\r
-           cur->psvi = NULL;\r
-           if (cur->children) {\r
-               cur = cur->children;\r
-               continue;\r
-           }\r
-       }\r
-\r
-leave_node:\r
-       if (cur == rootElem)\r
-           break;\r
-       if (cur->next != NULL)\r
-           cur = cur->next;\r
-       else {\r
-           cur = cur->parent;\r
-           if (cur == NULL)\r
-               break;\r
-           goto leave_node;\r
-       }\r
-    }\r
-#endif /* #if 0 */\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltFreeStylesheet:\r
- * @style:  an XSLT stylesheet\r
- *\r
- * Free up the memory allocated by @style\r
- */\r
-void\r
-xsltFreeStylesheet(xsltStylesheetPtr style)\r
-{\r
-    if (style == NULL)\r
-        return;\r
-    \r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * Start with a cleanup of the main stylesheet's doc.\r
-    */\r
-    if ((style->principal == style) && (style->doc))\r
-       xsltCleanupStylesheetTree(style->doc,\r
-           xmlDocGetRootElement(style->doc));\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-    /*\r
-    * Restore changed ns-decls before freeing the document.\r
-    */\r
-    if ((style->doc != NULL) &&\r
-       XSLT_HAS_INTERNAL_NSMAP(style))\r
-    {\r
-       xsltRestoreDocumentNamespaces(XSLT_GET_INTERNAL_NSMAP(style),\r
-           style->doc);        \r
-    }\r
-#endif /* XSLT_REFACTORED_XSLT_NSCOMP */\r
-#else\r
-    /*\r
-    * Start with a cleanup of the main stylesheet's doc.\r
-    */\r
-    if ((style->parent == NULL) && (style->doc))\r
-       xsltCleanupStylesheetTree(style->doc,\r
-           xmlDocGetRootElement(style->doc));\r
-#endif /* XSLT_REFACTORED */\r
-\r
-    xsltFreeKeys(style);\r
-    xsltFreeExts(style);\r
-    xsltFreeTemplateHashes(style);\r
-    xsltFreeDecimalFormatList(style);\r
-    xsltFreeTemplateList(style->templates);\r
-    xsltFreeAttributeSetsHashes(style);\r
-    xsltFreeNamespaceAliasHashes(style);\r
-    xsltFreeStylePreComps(style);\r
-    /*\r
-    * Free documents of all included stylsheet modules of this\r
-    * stylesheet level.\r
-    */\r
-    xsltFreeStyleDocuments(style);\r
-    /*\r
-    * TODO: Best time to shutdown extension stuff?\r
-    */\r
-    xsltShutdownExts(style);\r
-       \r
-    if (style->variables != NULL)\r
-        xsltFreeStackElemList(style->variables);\r
-    if (style->cdataSection != NULL)\r
-        xmlHashFree(style->cdataSection, NULL);\r
-    if (style->stripSpaces != NULL)\r
-        xmlHashFree(style->stripSpaces, NULL);\r
-    if (style->nsHash != NULL)\r
-        xmlHashFree(style->nsHash, NULL);\r
-    if (style->exclPrefixTab != NULL)\r
-        xmlFree(style->exclPrefixTab);\r
-    if (style->method != NULL)\r
-        xmlFree(style->method);\r
-    if (style->methodURI != NULL)\r
-        xmlFree(style->methodURI);\r
-    if (style->version != NULL)\r
-        xmlFree(style->version);\r
-    if (style->encoding != NULL)\r
-        xmlFree(style->encoding);\r
-    if (style->doctypePublic != NULL)\r
-        xmlFree(style->doctypePublic);\r
-    if (style->doctypeSystem != NULL)\r
-        xmlFree(style->doctypeSystem);\r
-    if (style->mediaType != NULL)\r
-        xmlFree(style->mediaType);\r
-    if (style->attVTs)\r
-        xsltFreeAVTList(style->attVTs);\r
-    if (style->imports != NULL)\r
-        xsltFreeStylesheetList(style->imports);\r
-\r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * If this is the principal stylesheet, then\r
-    * free its internal data.\r
-    */\r
-    if (style->principal == style) {\r
-       if (style->principalData) {\r
-           xsltFreePrincipalStylesheetData(style->principalData);\r
-           style->principalData = NULL;\r
-       }\r
-    }    \r
-#endif\r
-    /*\r
-    * Better to free the main document of this stylesheet level\r
-    * at the end - so here.\r
-    */\r
-    if (style->doc != NULL) {  \r
-        xmlFreeDoc(style->doc);\r
-    }\r
-\r
-#ifdef WITH_XSLT_DEBUG\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-                     "freeing dictionary from stylesheet\n");\r
-#endif\r
-    xmlDictFree(style->dict);\r
-\r
-    memset(style, -1, sizeof(xsltStylesheet));\r
-    xmlFree(style);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Parsing of an XSLT Stylesheet                           *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * This is now performed in an optimized way in xsltParseXSLTTemplate.\r
-    */\r
-#else\r
-/**\r
- * xsltGetInheritedNsList:\r
- * @style:  the stylesheet\r
- * @template: the template\r
- * @node:  the current node\r
- *\r
- * Search all the namespace applying to a given element except the ones \r
- * from excluded output prefixes currently in scope. Initialize the\r
- * template inheritedNs list with it.\r
- *\r
- * Returns the number of entries found\r
- */\r
-static int\r
-xsltGetInheritedNsList(xsltStylesheetPtr style,\r
-                      xsltTemplatePtr template,\r
-                      xmlNodePtr node)\r
-{\r
-    xmlNsPtr cur;\r
-    xmlNsPtr *ret = NULL;\r
-    int nbns = 0;\r
-    int maxns = 10;\r
-    int i;    \r
-\r
-    if ((style == NULL) || (template == NULL) || (node == NULL) ||\r
-       (template->inheritedNsNr != 0) || (template->inheritedNs != NULL))\r
-       return(0);\r
-    while (node != NULL) {\r
-        if (node->type == XML_ELEMENT_NODE) {\r
-            cur = node->nsDef;\r
-            while (cur != NULL) {\r
-               if (xmlStrEqual(cur->href, XSLT_NAMESPACE))\r
-                   goto skip_ns;\r
-\r
-               if ((cur->prefix != NULL) &&\r
-                   (xsltCheckExtPrefix(style, cur->prefix)))\r
-                   goto skip_ns;\r
-               /*\r
-               * Check if this namespace was excluded.\r
-               * Note that at this point only the exclusions defined\r
-               * on the topmost stylesheet element are in the exclusion-list.\r
-               */\r
-               for (i = 0;i < style->exclPrefixNr;i++) {\r
-                   if (xmlStrEqual(cur->href, style->exclPrefixTab[i]))\r
-                       goto skip_ns;\r
-               }\r
-                if (ret == NULL) {\r
-                    ret =\r
-                        (xmlNsPtr *) xmlMalloc((maxns + 1) *\r
-                                               sizeof(xmlNsPtr));\r
-                    if (ret == NULL) {\r
-                        xmlGenericError(xmlGenericErrorContext,\r
-                                        "xsltGetInheritedNsList : out of memory!\n");\r
-                        return(0);\r
-                    }\r
-                    ret[nbns] = NULL;\r
-                }\r
-               /*\r
-               * Skip shadowed namespace bindings.\r
-               */\r
-                for (i = 0; i < nbns; i++) {\r
-                    if ((cur->prefix == ret[i]->prefix) ||\r
-                        (xmlStrEqual(cur->prefix, ret[i]->prefix)))\r
-                        break;\r
-                }\r
-                if (i >= nbns) {\r
-                    if (nbns >= maxns) {\r
-                        maxns *= 2;\r
-                        ret = (xmlNsPtr *) xmlRealloc(ret,\r
-                                                      (maxns +\r
-                                                       1) *\r
-                                                      sizeof(xmlNsPtr));\r
-                        if (ret == NULL) {\r
-                            xmlGenericError(xmlGenericErrorContext,\r
-                                            "xsltGetInheritedNsList : realloc failed!\n");\r
-                            return(0);\r
-                        }\r
-                    }\r
-                    ret[nbns++] = cur;\r
-                    ret[nbns] = NULL;\r
-                }\r
-skip_ns:\r
-                cur = cur->next;\r
-            }\r
-        }\r
-        node = node->parent;\r
-    }\r
-    if (nbns != 0) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-        xsltGenericDebug(xsltGenericDebugContext,\r
-                         "template has %d inherited namespaces\n", nbns);\r
-#endif\r
-       template->inheritedNsNr = nbns;\r
-       template->inheritedNs = ret;\r
-    }\r
-    return (nbns);\r
-}\r
-#endif /* else of XSLT_REFACTORED */\r
-\r
-/**\r
- * xsltParseStylesheetOutput:\r
- * @style:  the XSLT stylesheet\r
- * @cur:  the "output" element\r
- *\r
- * parse an XSLT stylesheet output element and record\r
- * information related to the stylesheet output\r
- */\r
-\r
-void\r
-xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)\r
-{\r
-    xmlChar *elements,\r
-     *prop;\r
-    xmlChar *element,\r
-     *end;\r
-\r
-    if ((cur == NULL) || (style == NULL))\r
-        return;\r
-   \r
-    prop = xmlGetNsProp(cur, (const xmlChar *) "version", NULL);\r
-    if (prop != NULL) {\r
-        if (style->version != NULL)\r
-            xmlFree(style->version);\r
-        style->version = prop;\r
-    }\r
-\r
-    prop = xmlGetNsProp(cur, (const xmlChar *) "encoding", NULL);\r
-    if (prop != NULL) {\r
-        if (style->encoding != NULL)\r
-            xmlFree(style->encoding);\r
-        style->encoding = prop;\r
-    }\r
-\r
-    /* relaxed to support xt:document\r
-    * TODO KB: What does "relaxed to support xt:document" mean?\r
-    */\r
-    prop = xmlGetNsProp(cur, (const xmlChar *) "method", NULL);\r
-    if (prop != NULL) {\r
-        const xmlChar *URI;\r
-\r
-        if (style->method != NULL)\r
-            xmlFree(style->method);\r
-        style->method = NULL;\r
-        if (style->methodURI != NULL)\r
-            xmlFree(style->methodURI);\r
-        style->methodURI = NULL;\r
-\r
-       /*\r
-       * TODO: Don't use xsltGetQNameURI().\r
-       */\r
-       URI = xsltGetQNameURI(cur, &prop);\r
-       if (prop == NULL) {\r
-           if (style != NULL) style->errors++;\r
-       } else if (URI == NULL) {\r
-            if ((xmlStrEqual(prop, (const xmlChar *) "xml")) ||\r
-                (xmlStrEqual(prop, (const xmlChar *) "html")) ||\r
-                (xmlStrEqual(prop, (const xmlChar *) "text"))) {\r
-                style->method = prop;\r
-            } else {\r
-               xsltTransformError(NULL, style, cur,\r
-                                 "invalid value for method: %s\n", prop);\r
-                if (style != NULL) style->warnings++;\r
-            }\r
-       } else {\r
-           style->method = prop;\r
-           style->methodURI = xmlStrdup(URI);\r
-       }\r
-    }\r
-\r
-    prop = xmlGetNsProp(cur, (const xmlChar *) "doctype-system", NULL);\r
-    if (prop != NULL) {\r
-        if (style->doctypeSystem != NULL)\r
-            xmlFree(style->doctypeSystem);\r
-        style->doctypeSystem = prop;\r
-    }\r
-\r
-    prop = xmlGetNsProp(cur, (const xmlChar *) "doctype-public", NULL);\r
-    if (prop != NULL) {\r
-        if (style->doctypePublic != NULL)\r
-            xmlFree(style->doctypePublic);\r
-        style->doctypePublic = prop;\r
-    }\r
-\r
-    prop = xmlGetNsProp(cur, (const xmlChar *) "standalone", NULL);\r
-    if (prop != NULL) {\r
-        if (xmlStrEqual(prop, (const xmlChar *) "yes")) {\r
-            style->standalone = 1;\r
-        } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {\r
-            style->standalone = 0;\r
-        } else {\r
-           xsltTransformError(NULL, style, cur,\r
-                             "invalid value for standalone: %s\n", prop);\r
-            style->errors++;\r
-        }\r
-        xmlFree(prop);\r
-    }\r
-\r
-    prop = xmlGetNsProp(cur, (const xmlChar *) "indent", NULL);\r
-    if (prop != NULL) {\r
-        if (xmlStrEqual(prop, (const xmlChar *) "yes")) {\r
-            style->indent = 1;\r
-        } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {\r
-            style->indent = 0;\r
-        } else {\r
-           xsltTransformError(NULL, style, cur,\r
-                             "invalid value for indent: %s\n", prop);\r
-            style->errors++;\r
-        }\r
-        xmlFree(prop);\r
-    }\r
-\r
-    prop = xmlGetNsProp(cur, (const xmlChar *) "omit-xml-declaration", NULL);\r
-    if (prop != NULL) {\r
-        if (xmlStrEqual(prop, (const xmlChar *) "yes")) {\r
-            style->omitXmlDeclaration = 1;\r
-        } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {\r
-            style->omitXmlDeclaration = 0;\r
-        } else {\r
-           xsltTransformError(NULL, style, cur,\r
-                             "invalid value for omit-xml-declaration: %s\n",\r
-                             prop);\r
-            style->errors++;\r
-        }\r
-        xmlFree(prop);\r
-    }\r
-\r
-    elements = xmlGetNsProp(cur, (const xmlChar *) "cdata-section-elements",\r
-       NULL);\r
-    if (elements != NULL) {\r
-        if (style->cdataSection == NULL)\r
-            style->cdataSection = xmlHashCreate(10);\r
-        if (style->cdataSection == NULL)\r
-            return;\r
-\r
-        element = elements;\r
-        while (*element != 0) {\r
-            while (IS_BLANK(*element))\r
-                element++;\r
-            if (*element == 0)\r
-                break;\r
-            end = element;\r
-            while ((*end != 0) && (!IS_BLANK(*end)))\r
-                end++;\r
-            element = xmlStrndup(element, end - element);\r
-            if (element) {             \r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-                xsltGenericDebug(xsltGenericDebugContext,\r
-                                 "add cdata section output element %s\n",\r
-                                 element);\r
-#endif\r
-               if (xmlValidateQName(BAD_CAST element, 0) != 0) {\r
-                   xsltTransformError(NULL, style, cur,\r
-                       "Attribute 'cdata-section-elements': The value "\r
-                       "'%s' is not a valid QName.\n", element);\r
-                   xmlFree(element);\r
-                   style->errors++;\r
-               } else {\r
-                   const xmlChar *URI;\r
-\r
-                   /*\r
-                   * TODO: Don't use xsltGetQNameURI().\r
-                   */\r
-                   URI = xsltGetQNameURI(cur, &element);\r
-                   if (element == NULL) {\r
-                       /*\r
-                       * TODO: We'll report additionally an error\r
-                       *  via the stylesheet's error handling.                 \r
-                       */\r
-                       xsltTransformError(NULL, style, cur,\r
-                           "Attribute 'cdata-section-elements': The value "\r
-                           "'%s' is not a valid QName.\n", element);\r
-                       style->errors++;\r
-                   } else {\r
-                       xmlNsPtr ns;\r
-                       \r
-                       /*\r
-                       * XSLT-1.0 "Each QName is expanded into an\r
-                       *  expanded-name using the namespace declarations in\r
-                       *  effect on the xsl:output element in which the QName\r
-                       *  occurs; if there is a default namespace, it is used\r
-                       *  for QNames that do not have a prefix"\r
-                       * NOTE: Fix of bug #339570.\r
-                       */\r
-                       if (URI == NULL) {\r
-                           ns = xmlSearchNs(style->doc, cur, NULL);\r
-                           if (ns != NULL)\r
-                               URI = ns->href;\r
-                       }                  \r
-                       xmlHashAddEntry2(style->cdataSection, element, URI,\r
-                           (void *) "cdata");\r
-                       xmlFree(element);\r
-                   }\r
-               }\r
-            }\r
-            element = end;\r
-        }\r
-        xmlFree(elements);\r
-    }\r
-\r
-    prop = xmlGetNsProp(cur, (const xmlChar *) "media-type", NULL);\r
-    if (prop != NULL) {\r
-       if (style->mediaType)\r
-           xmlFree(style->mediaType);\r
-       style->mediaType = prop;\r
-    }\r
-    if (cur->children != NULL) {\r
-       xsltParseContentError(style, cur->children);\r
-    }\r
-}\r
-\r
-/**\r
- * xsltParseStylesheetDecimalFormat:\r
- * @style:  the XSLT stylesheet\r
- * @cur:  the "decimal-format" element\r
- *\r
- * <!-- Category: top-level-element -->\r
- * <xsl:decimal-format\r
- *   name = qname, decimal-separator = char, grouping-separator = char,\r
- *   infinity = string, minus-sign = char, NaN = string, percent = char\r
- *   per-mille = char, zero-digit = char, digit = char,\r
- * pattern-separator = char />\r
- *\r
- * parse an XSLT stylesheet decimal-format element and\r
- * and record the formatting characteristics\r
- */\r
-static void\r
-xsltParseStylesheetDecimalFormat(xsltStylesheetPtr style, xmlNodePtr cur)\r
-{\r
-    xmlChar *prop;\r
-    xsltDecimalFormatPtr format;\r
-    xsltDecimalFormatPtr iter;\r
-    \r
-    if ((cur == NULL) || (style == NULL))\r
-       return;\r
-\r
-    format = style->decimalFormat;\r
-    \r
-    prop = xmlGetNsProp(cur, BAD_CAST("name"), NULL);\r
-    if (prop != NULL) {\r
-       format = xsltDecimalFormatGetByName(style, prop);\r
-       if (format != NULL) {\r
-           xsltTransformError(NULL, style, cur,\r
-        "xsltParseStylestyleDecimalFormat: %s already exists\n", prop);\r
-           if (style != NULL) style->warnings++;\r
-           return;\r
-       }\r
-       format = xsltNewDecimalFormat(prop);\r
-       if (format == NULL) {\r
-           xsltTransformError(NULL, style, cur,\r
-     "xsltParseStylestyleDecimalFormat: failed creating new decimal-format\n");\r
-           if (style != NULL) style->errors++;\r
-           return;\r
-       }\r
-       /* Append new decimal-format structure */\r
-       for (iter = style->decimalFormat; iter->next; iter = iter->next)\r
-           ;\r
-       if (iter)\r
-           iter->next = format;\r
-    }\r
-\r
-    prop = xmlGetNsProp(cur, (const xmlChar *)"decimal-separator", NULL);\r
-    if (prop != NULL) {\r
-       if (format->decimalPoint != NULL) xmlFree(format->decimalPoint);\r
-       format->decimalPoint  = prop;\r
-    }\r
-    \r
-    prop = xmlGetNsProp(cur, (const xmlChar *)"grouping-separator", NULL);\r
-    if (prop != NULL) {\r
-       if (format->grouping != NULL) xmlFree(format->grouping);\r
-       format->grouping  = prop;\r
-    }\r
-\r
-    prop = xmlGetNsProp(cur, (const xmlChar *)"infinity", NULL);\r
-    if (prop != NULL) {\r
-       if (format->infinity != NULL) xmlFree(format->infinity);\r
-       format->infinity  = prop;\r
-    }\r
-    \r
-    prop = xmlGetNsProp(cur, (const xmlChar *)"minus-sign", NULL);\r
-    if (prop != NULL) {\r
-       if (format->minusSign != NULL) xmlFree(format->minusSign);\r
-       format->minusSign  = prop;\r
-    }\r
-    \r
-    prop = xmlGetNsProp(cur, (const xmlChar *)"NaN", NULL);\r
-    if (prop != NULL) {\r
-       if (format->noNumber != NULL) xmlFree(format->noNumber);\r
-       format->noNumber  = prop;\r
-    }\r
-    \r
-    prop = xmlGetNsProp(cur, (const xmlChar *)"percent", NULL);\r
-    if (prop != NULL) {\r
-       if (format->percent != NULL) xmlFree(format->percent);\r
-       format->percent  = prop;\r
-    }\r
-    \r
-    prop = xmlGetNsProp(cur, (const xmlChar *)"per-mille", NULL);\r
-    if (prop != NULL) {\r
-       if (format->permille != NULL) xmlFree(format->permille);\r
-       format->permille  = prop;\r
-    }\r
-    \r
-    prop = xmlGetNsProp(cur, (const xmlChar *)"zero-digit", NULL);\r
-    if (prop != NULL) {\r
-       if (format->zeroDigit != NULL) xmlFree(format->zeroDigit);\r
-       format->zeroDigit  = prop;\r
-    }\r
-    \r
-    prop = xmlGetNsProp(cur, (const xmlChar *)"digit", NULL);\r
-    if (prop != NULL) {\r
-       if (format->digit != NULL) xmlFree(format->digit);\r
-       format->digit  = prop;\r
-    }\r
-    \r
-    prop = xmlGetNsProp(cur, (const xmlChar *)"pattern-separator", NULL);\r
-    if (prop != NULL) {\r
-       if (format->patternSeparator != NULL) xmlFree(format->patternSeparator);\r
-       format->patternSeparator  = prop;\r
-    }\r
-    if (cur->children != NULL) {\r
-       xsltParseContentError(style, cur->children);\r
-    }\r
-}\r
-\r
-/**\r
- * xsltParseStylesheetPreserveSpace:\r
- * @style:  the XSLT stylesheet\r
- * @cur:  the "preserve-space" element\r
- *\r
- * parse an XSLT stylesheet preserve-space element and record\r
- * elements needing preserving\r
- */\r
-\r
-static void\r
-xsltParseStylesheetPreserveSpace(xsltStylesheetPtr style, xmlNodePtr cur) {\r
-    xmlChar *elements;\r
-    xmlChar *element, *end;\r
-\r
-    if ((cur == NULL) || (style == NULL))\r
-       return;\r
-\r
-    elements = xmlGetNsProp(cur, (const xmlChar *)"elements", NULL);\r
-    if (elements == NULL) {\r
-       xsltTransformError(NULL, style, cur,\r
-           "xsltParseStylesheetPreserveSpace: missing elements attribute\n");\r
-       if (style != NULL) style->warnings++;\r
-       return;\r
-    }\r
-\r
-    if (style->stripSpaces == NULL)\r
-       style->stripSpaces = xmlHashCreate(10);\r
-    if (style->stripSpaces == NULL)\r
-       return;\r
-\r
-    element = elements;\r
-    while (*element != 0) {\r
-       while (IS_BLANK(*element)) element++;\r
-       if (*element == 0)\r
-           break;\r
-        end = element;\r
-       while ((*end != 0) && (!IS_BLANK(*end))) end++;\r
-       element = xmlStrndup(element, end - element);\r
-       if (element) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-               "add preserved space element %s\n", element);\r
-#endif\r
-           if (xmlStrEqual(element, (const xmlChar *)"*")) {\r
-               style->stripAll = -1;\r
-           } else {\r
-               const xmlChar *URI;\r
-\r
-               /*\r
-               * TODO: Don't use xsltGetQNameURI().\r
-               */\r
-                URI = xsltGetQNameURI(cur, &element);\r
-\r
-               xmlHashAddEntry2(style->stripSpaces, element, URI,\r
-                               (xmlChar *) "preserve");\r
-           }\r
-           xmlFree(element);\r
-       }\r
-       element = end;\r
-    }\r
-    xmlFree(elements);\r
-    if (cur->children != NULL) {\r
-       xsltParseContentError(style, cur->children);\r
-    }\r
-}\r
-\r
-#ifdef XSLT_REFACTORED\r
-#else\r
-/**\r
- * xsltParseStylesheetExtPrefix:\r
- * @style:  the XSLT stylesheet\r
- * @template:  the "extension-element-prefixes" prefix\r
- *\r
- * parse an XSLT stylesheet's "extension-element-prefix" attribute value\r
- * and register the namespaces of extension instruction.\r
- * SPEC "A namespace is designated as an extension namespace by using\r
- *   an extension-element-prefixes attribute on:\r
- *   1) an xsl:stylesheet element\r
- *   2) an xsl:extension-element-prefixes attribute on a\r
- *      literal result element \r
- *   3) an extension instruction."\r
- */\r
-static void\r
-xsltParseStylesheetExtPrefix(xsltStylesheetPtr style, xmlNodePtr cur,\r
-                            int isXsltElem) {\r
-    xmlChar *prefixes;\r
-    xmlChar *prefix, *end;\r
-\r
-    if ((cur == NULL) || (style == NULL))\r
-       return;\r
-\r
-    if (isXsltElem) {\r
-       /* For xsl:stylesheet/xsl:transform. */\r
-       prefixes = xmlGetNsProp(cur,\r
-           (const xmlChar *)"extension-element-prefixes", NULL);\r
-    } else {\r
-       /* For literal result elements and extension instructions. */\r
-       prefixes = xmlGetNsProp(cur,\r
-           (const xmlChar *)"extension-element-prefixes", XSLT_NAMESPACE);\r
-    }\r
-    if (prefixes == NULL) {\r
-       return;\r
-    }\r
-\r
-    prefix = prefixes;\r
-    while (*prefix != 0) {\r
-       while (IS_BLANK(*prefix)) prefix++;\r
-       if (*prefix == 0)\r
-           break;\r
-        end = prefix;\r
-       while ((*end != 0) && (!IS_BLANK(*end))) end++;\r
-       prefix = xmlStrndup(prefix, end - prefix);\r
-       if (prefix) {\r
-           xmlNsPtr ns;\r
-\r
-           if (xmlStrEqual(prefix, (const xmlChar *)"#default"))\r
-               ns = xmlSearchNs(style->doc, cur, NULL);\r
-           else\r
-               ns = xmlSearchNs(style->doc, cur, prefix);\r
-           if (ns == NULL) {\r
-               xsltTransformError(NULL, style, cur,\r
-           "xsl:extension-element-prefix : undefined namespace %s\n",\r
-                                prefix);\r
-               if (style != NULL) style->warnings++;\r
-           } else {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-               xsltGenericDebug(xsltGenericDebugContext,\r
-                   "add extension prefix %s\n", prefix);\r
-#endif\r
-               xsltRegisterExtPrefix(style, prefix, ns->href);\r
-           }\r
-           xmlFree(prefix);\r
-       }\r
-       prefix = end;\r
-    }\r
-    xmlFree(prefixes);\r
-}\r
-#endif /* else of XSLT_REFACTORED */\r
-\r
-/**\r
- * xsltParseStylesheetStripSpace:\r
- * @style:  the XSLT stylesheet\r
- * @cur:  the "strip-space" element\r
- *\r
- * parse an XSLT stylesheet's strip-space element and record\r
- * the elements needing stripping\r
- */\r
-\r
-static void\r
-xsltParseStylesheetStripSpace(xsltStylesheetPtr style, xmlNodePtr cur) {\r
-    xmlChar *elements;\r
-    xmlChar *element, *end;\r
-\r
-    if ((cur == NULL) || (style == NULL))\r
-       return;\r
-\r
-    elements = xmlGetNsProp(cur, (const xmlChar *)"elements", NULL);\r
-    if (elements == NULL) {\r
-       xsltTransformError(NULL, style, cur,\r
-           "xsltParseStylesheetStripSpace: missing elements attribute\n");\r
-       if (style != NULL) style->warnings++;\r
-       return;\r
-    }\r
-\r
-    if (style->stripSpaces == NULL)\r
-       style->stripSpaces = xmlHashCreate(10);\r
-    if (style->stripSpaces == NULL)\r
-       return;\r
-\r
-    element = elements;\r
-    while (*element != 0) {\r
-       while (IS_BLANK(*element)) element++;\r
-       if (*element == 0)\r
-           break;\r
-        end = element;\r
-       while ((*end != 0) && (!IS_BLANK(*end))) end++;\r
-       element = xmlStrndup(element, end - element);\r
-       if (element) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-               "add stripped space element %s\n", element);\r
-#endif\r
-           if (xmlStrEqual(element, (const xmlChar *)"*")) {\r
-               style->stripAll = 1;\r
-           } else {\r
-               const xmlChar *URI;\r
-\r
-               /*\r
-               * TODO: Don't use xsltGetQNameURI().\r
-               */\r
-                URI = xsltGetQNameURI(cur, &element);\r
-\r
-               xmlHashAddEntry2(style->stripSpaces, element, URI,\r
-                               (xmlChar *) "strip");\r
-           }\r
-           xmlFree(element);\r
-       }\r
-       element = end;\r
-    }\r
-    xmlFree(elements);\r
-    if (cur->children != NULL) {\r
-       xsltParseContentError(style, cur->children);\r
-    }\r
-}\r
-\r
-#ifdef XSLT_REFACTORED\r
-#else\r
-/**\r
- * xsltParseStylesheetExcludePrefix:\r
- * @style:  the XSLT stylesheet\r
- * @cur:  the current point in the stylesheet\r
- *\r
- * parse an XSLT stylesheet exclude prefix and record\r
- * namespaces needing stripping\r
- *\r
- * Returns the number of Excluded prefixes added at that level\r
- */\r
-\r
-static int\r
-xsltParseStylesheetExcludePrefix(xsltStylesheetPtr style, xmlNodePtr cur,\r
-                                int isXsltElem)\r
-{\r
-    int nb = 0;\r
-    xmlChar *prefixes;\r
-    xmlChar *prefix, *end;\r
-\r
-    if ((cur == NULL) || (style == NULL))\r
-       return(0);\r
-\r
-    if (isXsltElem)\r
-       prefixes = xmlGetNsProp(cur,\r
-           (const xmlChar *)"exclude-result-prefixes", NULL);\r
-    else\r
-       prefixes = xmlGetNsProp(cur,\r
-           (const xmlChar *)"exclude-result-prefixes", XSLT_NAMESPACE);\r
-\r
-    if (prefixes == NULL) {\r
-       return(0);\r
-    }\r
-\r
-    prefix = prefixes;\r
-    while (*prefix != 0) {\r
-       while (IS_BLANK(*prefix)) prefix++;\r
-       if (*prefix == 0)\r
-           break;\r
-        end = prefix;\r
-       while ((*end != 0) && (!IS_BLANK(*end))) end++;\r
-       prefix = xmlStrndup(prefix, end - prefix);\r
-       if (prefix) {\r
-           xmlNsPtr ns;\r
-\r
-           if (xmlStrEqual(prefix, (const xmlChar *)"#default"))\r
-               ns = xmlSearchNs(style->doc, cur, NULL);\r
-           else\r
-               ns = xmlSearchNs(style->doc, cur, prefix);\r
-           if (ns == NULL) {\r
-               xsltTransformError(NULL, style, cur,\r
-           "xsl:exclude-result-prefixes : undefined namespace %s\n",\r
-                                prefix);\r
-               if (style != NULL) style->warnings++;\r
-           } else {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-               xsltGenericDebug(xsltGenericDebugContext,\r
-                   "exclude result prefix %s\n", prefix);\r
-#endif\r
-               exclPrefixPush(style, (xmlChar *) ns->href);\r
-               nb++;\r
-           }\r
-           xmlFree(prefix);\r
-       }\r
-       prefix = end;\r
-    }\r
-    xmlFree(prefixes);\r
-    return(nb);\r
-}\r
-#endif /* else of XSLT_REFACTORED */\r
-\r
-#ifdef XSLT_REFACTORED\r
-\r
-/*\r
-* xsltTreeEnsureXMLDecl:\r
-* @doc: the doc\r
-* \r
-* BIG NOTE:\r
-*  This was copy&pasted from Libxml2's xmlTreeEnsureXMLDecl() in "tree.c".\r
-* Ensures that there is an XML namespace declaration on the doc.\r
-* \r
-* Returns the XML ns-struct or NULL on API and internal errors.\r
-*/\r
-static xmlNsPtr\r
-xsltTreeEnsureXMLDecl(xmlDocPtr doc)\r
-{\r
-    if (doc == NULL)\r
-       return (NULL);\r
-    if (doc->oldNs != NULL)\r
-       return (doc->oldNs);\r
-    {\r
-       xmlNsPtr ns;\r
-       ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));\r
-       if (ns == NULL) {\r
-           xmlGenericError(xmlGenericErrorContext,\r
-               "xsltTreeEnsureXMLDecl: Failed to allocate "\r
-               "the XML namespace.\n");        \r
-           return (NULL);\r
-       }\r
-       memset(ns, 0, sizeof(xmlNs));\r
-       ns->type = XML_LOCAL_NAMESPACE;\r
-       /*\r
-       * URGENT TODO: revisit this.\r
-       */\r
-#ifdef LIBXML_NAMESPACE_DICT\r
-       if (doc->dict)\r
-           ns->href = xmlDictLookup(doc->dict, XML_XML_NAMESPACE, -1);\r
-       else\r
-           ns->href = xmlStrdup(XML_XML_NAMESPACE);\r
-#else\r
-       ns->href = xmlStrdup(XML_XML_NAMESPACE); \r
-#endif\r
-       ns->prefix = xmlStrdup((const xmlChar *)"xml");\r
-       doc->oldNs = ns;\r
-       return (ns);\r
-    }\r
-}\r
-\r
-/*\r
-* xsltTreeAcquireStoredNs:\r
-* @doc: the doc\r
-* @nsName: the namespace name\r
-* @prefix: the prefix\r
-* \r
-* BIG NOTE:\r
-*  This was copy&pasted from Libxml2's xmlDOMWrapStoreNs() in "tree.c".\r
-* Creates or reuses an xmlNs struct on doc->oldNs with\r
-* the given prefix and namespace name.\r
-* \r
-* Returns the aquired ns struct or NULL in case of an API\r
-*         or internal error.\r
-*/\r
-static xmlNsPtr\r
-xsltTreeAcquireStoredNs(xmlDocPtr doc,\r
-                       const xmlChar *nsName,\r
-                       const xmlChar *prefix)\r
-{\r
-    xmlNsPtr ns;\r
-\r
-    if (doc == NULL)\r
-       return (NULL);\r
-    if (doc->oldNs != NULL)\r
-       ns = doc->oldNs;\r
-    else\r
-       ns = xsltTreeEnsureXMLDecl(doc);\r
-    if (ns == NULL)\r
-       return (NULL);\r
-    if (ns->next != NULL) {\r
-       /* Reuse. */\r
-       ns = ns->next;\r
-       while (ns != NULL) {\r
-           if ((ns->prefix == NULL) != (prefix == NULL)) {\r
-               /* NOP */\r
-           } else if (prefix == NULL) {\r
-               if (xmlStrEqual(ns->href, nsName))\r
-                   return (ns);\r
-           } else {\r
-               if ((ns->prefix[0] == prefix[0]) &&\r
-                    xmlStrEqual(ns->prefix, prefix) &&\r
-                    xmlStrEqual(ns->href, nsName))\r
-                   return (ns);\r
-               \r
-           }\r
-           if (ns->next == NULL)\r
-               break;\r
-           ns = ns->next;\r
-       }\r
-    }\r
-    /* Create. */\r
-    ns->next = xmlNewNs(NULL, nsName, prefix);\r
-    return (ns->next);\r
-}\r
-\r
-/**\r
- * xsltLREBuildEffectiveNs:\r
- *\r
- * Apply ns-aliasing on the namespace of the given @elem and\r
- * its attributes.\r
- */\r
-static int\r
-xsltLREBuildEffectiveNs(xsltCompilerCtxtPtr cctxt,\r
-                       xmlNodePtr elem)\r
-{\r
-    xmlNsPtr ns;\r
-    xsltNsAliasPtr alias;\r
-\r
-    if ((cctxt == NULL) || (elem == NULL))\r
-       return(-1);\r
-    if ((cctxt->nsAliases == NULL) || (! cctxt->hasNsAliases))\r
-       return(0);\r
-\r
-    alias = cctxt->nsAliases;                  \r
-    while (alias != NULL) {\r
-       if ( /* If both namespaces are NULL... */\r
-           ( (elem->ns == NULL) &&\r
-           ((alias->literalNs == NULL) ||\r
-           (alias->literalNs->href == NULL)) ) ||\r
-           /* ... or both namespace are equal */\r
-           ( (elem->ns != NULL) &&\r
-           (alias->literalNs != NULL) &&\r
-           xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )\r
-       {\r
-           if ((alias->targetNs != NULL) &&\r
-               (alias->targetNs->href != NULL))\r
-           {\r
-               /*\r
-               * Convert namespace.\r
-               */\r
-               if (elem->doc == alias->docOfTargetNs) {\r
-                   /*\r
-                   * This is the nice case: same docs.\r
-                   * This will eventually assign a ns-decl which\r
-                   * is shadowed, but this has no negative effect on\r
-                   * the generation of the result tree.\r
-                   */\r
-                   elem->ns = alias->targetNs;\r
-               } else {\r
-                   /*\r
-                   * This target xmlNs originates from a different\r
-                   * stylesheet tree. Try to locate it in the\r
-                   * in-scope namespaces.\r
-                   * OPTIMIZE TODO: Use the compiler-node-info inScopeNs.\r
-                   */\r
-                   ns = xmlSearchNs(elem->doc, elem,\r
-                       alias->targetNs->prefix);                   \r
-                   /*\r
-                   * If no matching ns-decl found, then assign a\r
-                   * ns-decl stored in xmlDoc.\r
-                   */\r
-                   if ((ns == NULL) ||\r
-                       (! xmlStrEqual(ns->href, alias->targetNs->href)))\r
-                   {\r
-                       /*\r
-                       * BIG NOTE: The use of xsltTreeAcquireStoredNs()\r
-                       *  is not very efficient, but currently I don't\r
-                       *  see an other way of *safely* changing a node's\r
-                       *  namespace, since the xmlNs struct in\r
-                       *  alias->targetNs might come from an other\r
-                       *  stylesheet tree. So we need to anchor it in the\r
-                       *  current document, without adding it to the tree,\r
-                       *  which would otherwise change the in-scope-ns\r
-                       *  semantic of the tree.\r
-                       */\r
-                       ns = xsltTreeAcquireStoredNs(elem->doc,\r
-                           alias->targetNs->href,\r
-                           alias->targetNs->prefix);\r
-                       \r
-                       if (ns == NULL) {\r
-                           xsltTransformError(NULL, cctxt->style, elem,\r
-                               "Internal error in "\r
-                               "xsltLREBuildEffectiveNs(): "\r
-                               "failed to acquire a stored "\r
-                               "ns-declaration.\n");\r
-                           cctxt->style->errors++;\r
-                           return(-1);\r
-                           \r
-                       }\r
-                   }\r
-                   elem->ns = ns;\r
-               }                  \r
-           } else {\r
-               /*\r
-               * Move into or leave in the NULL namespace.\r
-               */\r
-               elem->ns = NULL;\r
-           }\r
-           break;\r
-       }\r
-       alias = alias->next;\r
-    }\r
-    /*\r
-    * Same with attributes of literal result elements.\r
-    */\r
-    if (elem->properties != NULL) {\r
-       xmlAttrPtr attr = elem->properties;\r
-       \r
-       while (attr != NULL) {\r
-           if (attr->ns == NULL) {\r
-               attr = attr->next;\r
-               continue;\r
-           }\r
-           alias = cctxt->nsAliases;\r
-           while (alias != NULL) {\r
-               if ( /* If both namespaces are NULL... */\r
-                   ( (elem->ns == NULL) &&\r
-                   ((alias->literalNs == NULL) ||\r
-                   (alias->literalNs->href == NULL)) ) ||\r
-                   /* ... or both namespace are equal */\r
-                   ( (elem->ns != NULL) &&\r
-                   (alias->literalNs != NULL) &&\r
-                   xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )\r
-               {\r
-                   if ((alias->targetNs != NULL) &&\r
-                       (alias->targetNs->href != NULL))\r
-                   {               \r
-                       if (elem->doc == alias->docOfTargetNs) {\r
-                           elem->ns = alias->targetNs;\r
-                       } else {\r
-                           ns = xmlSearchNs(elem->doc, elem,\r
-                               alias->targetNs->prefix);\r
-                           if ((ns == NULL) ||\r
-                               (! xmlStrEqual(ns->href, alias->targetNs->href)))\r
-                           {\r
-                               ns = xsltTreeAcquireStoredNs(elem->doc,\r
-                                   alias->targetNs->href,\r
-                                   alias->targetNs->prefix);\r
-                               \r
-                               if (ns == NULL) {\r
-                                   xsltTransformError(NULL, cctxt->style, elem,\r
-                                       "Internal error in "\r
-                                       "xsltLREBuildEffectiveNs(): "\r
-                                       "failed to acquire a stored "\r
-                                       "ns-declaration.\n");\r
-                                   cctxt->style->errors++;\r
-                                   return(-1);\r
-                                   \r
-                               }\r
-                           }\r
-                           elem->ns = ns;\r
-                       }\r
-                   } else {\r
-                   /*\r
-                   * Move into or leave in the NULL namespace.\r
-                       */\r
-                       elem->ns = NULL;\r
-                   }\r
-                   break;\r
-               }\r
-               alias = alias->next;\r
-           }\r
-           \r
-           attr = attr->next;\r
-       }\r
-    }\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltLREBuildEffectiveNsNodes:\r
- *\r
- * Computes the effective namespaces nodes for a literal result\r
- * element.\r
- * @effectiveNs is the set of effective ns-nodes\r
- *  on the literal result element, which will be added to the result\r
- *  element if not already existing in the result tree.\r
- *  This means that excluded namespaces (via exclude-result-prefixes,\r
- *  extension-element-prefixes and the XSLT namespace) not added\r
- *  to the set.\r
- *  Namespace-aliasing was applied on the @effectiveNs.\r
- */\r
-static int\r
-xsltLREBuildEffectiveNsNodes(xsltCompilerCtxtPtr cctxt,\r
-                            xsltStyleItemLRElementInfoPtr item,\r
-                            xmlNodePtr elem,\r
-                            int isLRE)\r
-{\r
-    xmlNsPtr ns, tmpns;\r
-    xsltEffectiveNsPtr effNs, lastEffNs = NULL;\r
-    int i, j, holdByElem;\r
-    xsltPointerListPtr extElemNs = cctxt->inode->extElemNs;\r
-    xsltPointerListPtr exclResultNs = cctxt->inode->exclResultNs;\r
-\r
-    if ((cctxt == NULL) || (cctxt->inode == NULL) || (elem == NULL) ||\r
-       (item == NULL) || (item->effectiveNs != NULL))\r
-       return(-1);\r
-\r
-    if (item->inScopeNs == NULL)    \r
-       return(0);\r
-\r
-    extElemNs = cctxt->inode->extElemNs;\r
-    exclResultNs = cctxt->inode->exclResultNs;\r
-\r
-    for (i = 0; i < item->inScopeNs->totalNumber; i++) {\r
-       ns = item->inScopeNs->list[i];\r
-       /*\r
-       * Skip namespaces designated as excluded namespaces\r
-       * -------------------------------------------------\r
-       *\r
-       * XSLT-20 TODO: In XSLT 2.0 we need to keep namespaces\r
-       *  which are target namespaces of namespace-aliases\r
-       *  regardless if designated as excluded.\r
-       *\r
-       * Exclude the XSLT namespace.\r
-       */\r
-       if (xmlStrEqual(ns->href, XSLT_NAMESPACE))\r
-           goto skip_ns;\r
-\r
-       /*\r
-       * Apply namespace aliasing\r
-       * ------------------------\r
-       *\r
-       * SPEC XSLT 2.0\r
-       *  "- A namespace node whose string value is a literal namespace\r
-       *     URI is not copied to the result tree.\r
-       *   - A namespace node whose string value is a target namespace URI\r
-       *     is copied to the result tree, whether or not the URI\r
-       *     identifies an excluded namespace."\r
-       * \r
-       * NOTE: The ns-aliasing machanism is non-cascading.\r
-       *  (checked with Saxon, Xalan and MSXML .NET).\r
-       * URGENT TODO: is style->nsAliases the effective list of\r
-       *  ns-aliases, or do we need to lookup the whole\r
-       *  import-tree?\r
-       * TODO: Get rid of import-tree lookup.\r
-       */\r
-       if (cctxt->hasNsAliases) {\r
-           xsltNsAliasPtr alias;\r
-           /*\r
-           * First check for being a target namespace.\r
-           */\r
-           alias = cctxt->nsAliases;\r
-           do {\r
-               /*\r
-               * TODO: Is xmlns="" handled already?\r
-               */\r
-               if ((alias->targetNs != NULL) &&\r
-                   (xmlStrEqual(alias->targetNs->href, ns->href)))\r
-               {\r
-                   /*\r
-                   * Recognized as a target namespace; use it regardless\r
-                   * if excluded otherwise.\r
-                   */\r
-                   goto add_effective_ns;\r
-               }\r
-               alias = alias->next;\r
-           } while (alias != NULL);\r
-\r
-           alias = cctxt->nsAliases;\r
-           do {\r
-               /*\r
-               * TODO: Is xmlns="" handled already?\r
-               */\r
-               if ((alias->literalNs != NULL) &&\r
-                   (xmlStrEqual(alias->literalNs->href, ns->href)))\r
-               {\r
-                   /*\r
-                   * Recognized as an namespace alias; do not use it.\r
-                   */\r
-                   goto skip_ns;\r
-               }\r
-               alias = alias->next;\r
-           } while (alias != NULL);\r
-       }\r
-       \r
-       /*\r
-       * Exclude excluded result namespaces.\r
-       */\r
-       if (exclResultNs) {\r
-           for (j = 0; j < exclResultNs->number; j++)\r
-               if (xmlStrEqual(ns->href, BAD_CAST exclResultNs->items[j]))\r
-                   goto skip_ns;\r
-       }\r
-       /*\r
-       * Exclude extension-element namespaces.\r
-       */\r
-       if (extElemNs) {\r
-           for (j = 0; j < extElemNs->number; j++)\r
-               if (xmlStrEqual(ns->href, BAD_CAST extElemNs->items[j]))\r
-                   goto skip_ns;\r
-       }\r
-\r
-add_effective_ns:\r
-       /*\r
-       * OPTIMIZE TODO: This information may not be needed.\r
-       */\r
-       if (isLRE && (elem->nsDef != NULL)) {\r
-           holdByElem = 0;\r
-           tmpns = elem->nsDef;\r
-           do {\r
-               if (tmpns == ns) {\r
-                   holdByElem = 1;\r
-                   break;\r
-               }\r
-               tmpns = tmpns->next;\r
-           } while (tmpns != NULL);        \r
-       } else\r
-           holdByElem = 0;\r
-       \r
-       \r
-       /*\r
-       * Add the effective namespace declaration.\r
-       */\r
-       effNs = (xsltEffectiveNsPtr) xmlMalloc(sizeof(xsltEffectiveNs));\r
-       if (effNs == NULL) {\r
-           xsltTransformError(NULL, cctxt->style, elem,\r
-               "Internal error in xsltLREBuildEffectiveNs(): "\r
-               "failed to allocate memory.\n");\r
-           cctxt->style->errors++;\r
-           return(-1);\r
-       }\r
-       if (cctxt->psData->effectiveNs == NULL) {\r
-           cctxt->psData->effectiveNs = effNs;\r
-           effNs->nextInStore = NULL;   \r
-       } else {\r
-           effNs->nextInStore = cctxt->psData->effectiveNs;\r
-           cctxt->psData->effectiveNs = effNs;\r
-       }\r
-\r
-       effNs->next = NULL;\r
-       effNs->prefix = ns->prefix;\r
-       effNs->nsName = ns->href;\r
-       effNs->holdByElem = holdByElem;\r
-       \r
-       if (lastEffNs == NULL)\r
-           item->effectiveNs = effNs;\r
-       else\r
-           lastEffNs->next = effNs;\r
-       lastEffNs = effNs;\r
-       \r
-skip_ns:\r
-       {}\r
-    }\r
-    return(0);\r
-}\r
-\r
-\r
-/**\r
- * xsltLREInfoCreate:\r
- *\r
- * @isLRE: indicates if the given @elem is a literal result element\r
- *\r
- * Creates a new info for a literal result element.\r
- */\r
-static int\r
-xsltLREInfoCreate(xsltCompilerCtxtPtr cctxt,\r
-                 xmlNodePtr elem,\r
-                 int isLRE)\r
-{\r
-    xsltStyleItemLRElementInfoPtr item;\r
-\r
-    if ((cctxt == NULL) || (cctxt->inode == NULL))\r
-       return(-1);\r
-\r
-    item = (xsltStyleItemLRElementInfoPtr)\r
-       xmlMalloc(sizeof(xsltStyleItemLRElementInfo));\r
-    if (item == NULL) {\r
-       xsltTransformError(NULL, cctxt->style, NULL,\r
-           "Internal error in xsltLREInfoCreate(): "\r
-           "memory allocation failed.\n");\r
-       cctxt->style->errors++;\r
-       return(-1);\r
-    }\r
-    memset(item, 0, sizeof(xsltStyleItemLRElementInfo));\r
-    item->type = XSLT_FUNC_LITERAL_RESULT_ELEMENT;\r
-    /*\r
-    * Store it in the stylesheet.\r
-    */\r
-    item->next = cctxt->style->preComps;\r
-    cctxt->style->preComps = (xsltElemPreCompPtr) item;\r
-    /*\r
-    * @inScopeNs are used for execution of XPath expressions\r
-    *  in AVTs.\r
-    */\r
-    item->inScopeNs = cctxt->inode->inScopeNs;\r
-    \r
-    if (elem)\r
-       xsltLREBuildEffectiveNsNodes(cctxt, item, elem, isLRE);\r
-\r
-    cctxt->inode->litResElemInfo = item;\r
-    cctxt->inode->nsChanged = 0;\r
-    cctxt->maxLREs++;\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltCompilerVarInfoPush: \r
- * @cctxt: the compilation context\r
- * \r
- * Pushes a new var/param info onto the stack.\r
- *\r
- * Returns the acquired variable info.\r
- */ \r
-static xsltVarInfoPtr\r
-xsltCompilerVarInfoPush(xsltCompilerCtxtPtr cctxt,\r
-                                 xmlNodePtr inst,\r
-                                 const xmlChar *name,\r
-                                 const xmlChar *nsName)\r
-{\r
-    xsltVarInfoPtr ivar;\r
-\r
-    if ((cctxt->ivar != NULL) && (cctxt->ivar->next != NULL)) {\r
-       ivar = cctxt->ivar->next;\r
-    } else if ((cctxt->ivar == NULL) && (cctxt->ivars != NULL)) {\r
-       ivar = cctxt->ivars;\r
-    } else {\r
-       ivar = (xsltVarInfoPtr) xmlMalloc(sizeof(xsltVarInfo));\r
-       if (ivar == NULL) {\r
-           xsltTransformError(NULL, cctxt->style, inst,\r
-               "xsltParseInScopeVarPush: xmlMalloc() failed!\n");\r
-           cctxt->style->errors++;\r
-           return(NULL);\r
-       }\r
-       /* memset(retVar, 0, sizeof(xsltInScopeVar)); */\r
-       if (cctxt->ivars == NULL) {\r
-           cctxt->ivars = ivar;\r
-           ivar->prev = NULL;\r
-       } else {\r
-           cctxt->ivar->next = ivar;\r
-           ivar->prev = cctxt->ivar;\r
-       }\r
-       cctxt->ivar = ivar;\r
-       ivar->next = NULL;\r
-    }\r
-    ivar->depth = cctxt->depth;\r
-    ivar->name = name;\r
-    ivar->nsName = nsName;\r
-    return(ivar);\r
-}\r
-\r
-/**\r
- * xsltCompilerVarInfoPop: \r
- * @cctxt: the compilation context\r
- * \r
- * Pops all var/param infos from the stack, which\r
- * have the current depth.\r
- */ \r
-static void\r
-xsltCompilerVarInfoPop(xsltCompilerCtxtPtr cctxt)\r
-{\r
-\r
-    while ((cctxt->ivar != NULL) &&\r
-       (cctxt->ivar->depth > cctxt->depth))\r
-    {\r
-       cctxt->ivar = cctxt->ivar->prev;\r
-    }\r
-}\r
-\r
-/*\r
-* xsltCompilerNodePush:\r
-*\r
-* @cctxt: the compilation context\r
-* @node: the node to be pushed (this can also be the doc-node)\r
-*\r
-* Returns the current node info structure or\r
-*         NULL in case of an internal error.\r
-*/\r
-xsltCompilerNodeInfoPtr\r
-xsltCompilerNodePush(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)\r
-{    \r
-    xsltCompilerNodeInfoPtr inode, iprev;\r
-\r
-    if ((cctxt->inode != NULL) && (cctxt->inode->next != NULL)) {      \r
-       inode = cctxt->inode->next;\r
-    } else if ((cctxt->inode == NULL) && (cctxt->inodeList != NULL)) {\r
-       inode = cctxt->inodeList;       \r
-    } else {\r
-       /*\r
-       * Create a new node-info.\r
-       */\r
-       inode = (xsltCompilerNodeInfoPtr)\r
-           xmlMalloc(sizeof(xsltCompilerNodeInfo));\r
-       if (inode == NULL) {\r
-           xsltTransformError(NULL, cctxt->style, NULL,\r
-               "xsltCompilerNodePush: malloc failed.\n");\r
-           return(NULL);\r
-       }\r
-       memset(inode, 0, sizeof(xsltCompilerNodeInfo));\r
-       if (cctxt->inodeList == NULL)\r
-           cctxt->inodeList = inode;\r
-       else {\r
-           cctxt->inodeLast->next = inode;\r
-           inode->prev = cctxt->inodeLast;\r
-       }\r
-       cctxt->inodeLast = inode;\r
-       cctxt->maxNodeInfos++;  \r
-       if (cctxt->inode == NULL) {\r
-           cctxt->inode = inode;\r
-           /*\r
-           * Create an initial literal result element info for\r
-           * the root of the stylesheet.\r
-           */\r
-           xsltLREInfoCreate(cctxt, NULL, 0);\r
-       } \r
-    }       \r
-    cctxt->depth++;\r
-    cctxt->inode = inode;\r
-    /*\r
-    * REVISIT TODO: Keep the reset always complete.    \r
-    * NOTE: Be carefull with the @node, since it might be\r
-    *  a doc-node.\r
-    */\r
-    inode->node = node;\r
-    inode->depth = cctxt->depth;\r
-    inode->templ = NULL;\r
-    inode->category = XSLT_ELEMENT_CATEGORY_XSLT;\r
-    inode->type = 0;\r
-    inode->item = NULL;\r
-    inode->curChildType = 0;\r
-    inode->extContentHandled = 0;\r
-    inode->isRoot = 0;\r
-    \r
-    if (inode->prev != NULL) {\r
-       iprev = inode->prev;\r
-       /*\r
-       * Inherit the following information:\r
-       * ---------------------------------\r
-       *\r
-       * In-scope namespaces\r
-       */\r
-       inode->inScopeNs = iprev->inScopeNs;\r
-       /*\r
-       * Info for literal result elements\r
-       */\r
-       inode->litResElemInfo = iprev->litResElemInfo;\r
-       inode->nsChanged = iprev->nsChanged;\r
-       /*\r
-       * Excluded result namespaces\r
-       */\r
-       inode->exclResultNs = iprev->exclResultNs;\r
-       /*\r
-       * Extension instruction namespaces\r
-       */\r
-       inode->extElemNs = iprev->extElemNs;\r
-       /*\r
-       * Whitespace preservation\r
-       */\r
-       inode->preserveWhitespace = iprev->preserveWhitespace;\r
-       /*\r
-       * Forwards-compatible mode\r
-       */\r
-       inode->forwardsCompat = iprev->forwardsCompat;  \r
-    } else {\r
-       inode->inScopeNs = NULL;\r
-       inode->exclResultNs = NULL;\r
-       inode->extElemNs = NULL;\r
-       inode->preserveWhitespace = 0;\r
-       inode->forwardsCompat = 0;\r
-    }\r
-    \r
-    return(inode);\r
-}\r
-\r
-/*\r
-* xsltCompilerNodePop:\r
-*\r
-* @cctxt: the compilation context\r
-* @node: the node to be pushed (this can also be the doc-node)\r
-*\r
-* Pops the current node info.\r
-*/\r
-static void\r
-xsltCompilerNodePop(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)\r
-{    \r
-    if (cctxt->inode == NULL) {\r
-       xmlGenericError(xmlGenericErrorContext,\r
-           "xsltCompilerNodePop: Top-node mismatch.\n");\r
-       return;\r
-    }\r
-    /*\r
-    * NOTE: Be carefull with the @node, since it might be\r
-    *  a doc-node.\r
-    */\r
-    if (cctxt->inode->node != node) {\r
-       xmlGenericError(xmlGenericErrorContext,\r
-       "xsltCompilerNodePop: Node mismatch.\n");\r
-       goto mismatch;\r
-    }\r
-    if (cctxt->inode->depth != cctxt->depth) {\r
-       xmlGenericError(xmlGenericErrorContext,\r
-       "xsltCompilerNodePop: Depth mismatch.\n");\r
-       goto mismatch;\r
-    }\r
-    /*\r
-    * Pop information of variables.\r
-    */\r
-    if ((cctxt->ivar) && (cctxt->ivar->depth > cctxt->depth))\r
-       xsltCompilerVarInfoPop(cctxt);\r
-\r
-    cctxt->depth--;\r
-    cctxt->inode = cctxt->inode->prev;\r
-    if (cctxt->inode != NULL)\r
-       cctxt->inode->curChildType = 0;\r
-    return;\r
-\r
-mismatch:\r
-    {\r
-       const xmlChar *nsName = NULL, *name = NULL;\r
-       const xmlChar *infnsName = NULL, *infname = NULL;\r
-       \r
-       if (node) {\r
-           if (node->type == XML_ELEMENT_NODE) {\r
-               name = node->name;\r
-               if (node->ns != NULL)\r
-                   nsName = node->ns->href;\r
-               else\r
-                   nsName = BAD_CAST "";\r
-           } else {\r
-               name = BAD_CAST "#document";\r
-               nsName = BAD_CAST "";\r
-           }\r
-       } else\r
-           name = BAD_CAST "Not given";\r
-\r
-       if (cctxt->inode->node) {\r
-           if (node->type == XML_ELEMENT_NODE) {\r
-               infname = cctxt->inode->node->name;\r
-               if (cctxt->inode->node->ns != NULL)\r
-                   infnsName = cctxt->inode->node->ns->href;\r
-               else\r
-                   infnsName = BAD_CAST "";\r
-           } else {\r
-               infname = BAD_CAST "#document";\r
-               infnsName = BAD_CAST "";\r
-           }\r
-       } else\r
-           infname = BAD_CAST "Not given";\r
-\r
-       \r
-       xmlGenericError(xmlGenericErrorContext,\r
-           "xsltCompilerNodePop: Given   : '%s' URI '%s'\n",\r
-           name, nsName);\r
-       xmlGenericError(xmlGenericErrorContext,\r
-           "xsltCompilerNodePop: Expected: '%s' URI '%s'\n",\r
-           infname, infnsName);\r
-    }\r
-}\r
-\r
-/*\r
-* xsltCompilerBuildInScopeNsList:\r
-*\r
-* Create and store the list of in-scope namespaces for the given\r
-* node in the stylesheet. If there are no changes in the in-scope\r
-* namespaces then the last ns-info of the ancestor axis will be returned.\r
-* Compilation-time only.\r
-*\r
-* Returns the ns-info or NULL if there are no namespaces in scope.\r
-*/\r
-static xsltNsListContainerPtr\r
-xsltCompilerBuildInScopeNsList(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)\r
-{\r
-    xsltNsListContainerPtr nsi = NULL;\r
-    xmlNsPtr *list = NULL, ns;\r
-    int i, maxns = 5;\r
-    /*\r
-    * Create a new ns-list for this position in the node-tree.\r
-    * xmlGetNsList() will return NULL, if there are no ns-decls in the\r
-    * tree. Note that the ns-decl for the XML namespace is not added\r
-    * to the resulting list; the XPath module handles the XML namespace\r
-    * internally.\r
-    */\r
-    while (node != NULL) {\r
-        if (node->type == XML_ELEMENT_NODE) {\r
-            ns = node->nsDef;\r
-            while (ns != NULL) {\r
-                if (nsi == NULL) {\r
-                   nsi = (xsltNsListContainerPtr)\r
-                       xmlMalloc(sizeof(xsltNsListContainer));\r
-                   if (nsi == NULL) {\r
-                       xsltTransformError(NULL, cctxt->style, NULL,\r
-                           "xsltCompilerBuildInScopeNsList: "\r
-                           "malloc failed!\n");\r
-                       goto internal_err;\r
-                   }\r
-                   memset(nsi, 0, sizeof(xsltNsListContainer));\r
-                    nsi->list =\r
-                        (xmlNsPtr *) xmlMalloc(maxns * sizeof(xmlNsPtr));\r
-                    if (nsi->list == NULL) {\r
-                       xsltTransformError(NULL, cctxt->style, NULL,\r
-                           "xsltCompilerBuildInScopeNsList: "\r
-                           "malloc failed!\n");\r
-                       goto internal_err;\r
-                    }\r
-                    nsi->list[0] = NULL;\r
-                }\r
-               /*\r
-               * Skip shadowed namespace bindings.\r
-               */\r
-                for (i = 0; i < nsi->totalNumber; i++) {\r
-                    if ((ns->prefix == nsi->list[i]->prefix) ||\r
-                        (xmlStrEqual(ns->prefix, nsi->list[i]->prefix)))\r
-                   break;\r
-                }\r
-                if (i >= nsi->totalNumber) {\r
-                    if (nsi->totalNumber +1 >= maxns) {\r
-                        maxns *= 2;\r
-                       nsi->list =\r
-                           (xmlNsPtr *) xmlRealloc(nsi->list,\r
-                               maxns * sizeof(xmlNsPtr));\r
-                        if (nsi->list == NULL) {\r
-                            xsltTransformError(NULL, cctxt->style, NULL,\r
-                               "xsltCompilerBuildInScopeNsList: "\r
-                               "realloc failed!\n");\r
-                               goto internal_err;\r
-                        }\r
-                    }\r
-                    nsi->list[nsi->totalNumber++] = ns;\r
-                    nsi->list[nsi->totalNumber] = NULL;\r
-                }\r
-\r
-                ns = ns->next;\r
-            }\r
-        }\r
-        node = node->parent;\r
-    }\r
-    if (nsi == NULL)\r
-       return(NULL);\r
-    /*\r
-    * Move the default namespace to last position.\r
-    */\r
-    nsi->xpathNumber = nsi->totalNumber;\r
-    for (i = 0; i < nsi->totalNumber; i++) {\r
-       if (nsi->list[i]->prefix == NULL) {\r
-           ns = nsi->list[i];\r
-           nsi->list[i] = nsi->list[nsi->totalNumber-1];\r
-           nsi->list[nsi->totalNumber-1] = ns;\r
-           nsi->xpathNumber--;\r
-           break;\r
-       }\r
-    }\r
-    /*\r
-    * Store the ns-list in the stylesheet.\r
-    */\r
-    if (xsltPointerListAddSize(\r
-       (xsltPointerListPtr)cctxt->psData->inScopeNamespaces,\r
-       (void *) nsi, 5) == -1)\r
-    {  \r
-       xmlFree(nsi);\r
-       nsi = NULL;\r
-       xsltTransformError(NULL, cctxt->style, NULL,\r
-           "xsltCompilerBuildInScopeNsList: failed to add ns-info.\n");\r
-       goto internal_err;\r
-    }\r
-    /*\r
-    * Notify of change in status wrt namespaces.\r
-    */\r
-    if (cctxt->inode != NULL)\r
-       cctxt->inode->nsChanged = 1;\r
-\r
-    return(nsi);\r
-\r
-internal_err:\r
-    if (list != NULL)\r
-       xmlFree(list);    \r
-    cctxt->style->errors++;\r
-    return(NULL);\r
-}\r
-\r
-static int\r
-xsltParseNsPrefixList(xsltCompilerCtxtPtr cctxt,\r
-                     xsltPointerListPtr list,\r
-                     xmlNodePtr node,\r
-                     const xmlChar *value)\r
-{\r
-    xmlChar *cur, *end;\r
-    xmlNsPtr ns;\r
-    \r
-    if ((cctxt == NULL) || (value == NULL) || (list == NULL))\r
-       return(-1);\r
-\r
-    list->number = 0;\r
-\r
-    cur = (xmlChar *) value;\r
-    while (*cur != 0) {\r
-       while (IS_BLANK(*cur)) cur++;\r
-       if (*cur == 0)\r
-           break;\r
-       end = cur;\r
-       while ((*end != 0) && (!IS_BLANK(*end))) end++;\r
-       cur = xmlStrndup(cur, end - cur);\r
-       if (cur == NULL) {\r
-           cur = end;\r
-           continue;\r
-       }               \r
-       /*\r
-       * TODO: Export and use xmlSearchNsByPrefixStrict()\r
-       *   in Libxml2, tree.c, since xmlSearchNs() is in most\r
-       *   cases not efficient and in some cases not correct.\r
-       *\r
-       * XSLT-2 TODO: XSLT 2.0 allows an additional "#all" value.\r
-       */\r
-       if ((cur[0] == '#') &&\r
-           xmlStrEqual(cur, (const xmlChar *)"#default"))\r
-           ns = xmlSearchNs(cctxt->style->doc, node, NULL);\r
-       else\r
-           ns = xmlSearchNs(cctxt->style->doc, node, cur);         \r
-\r
-       if (ns == NULL) {\r
-           /*\r
-           * TODO: Better to report the attr-node, otherwise\r
-           *  the user won't know which attribute was invalid.\r
-           */\r
-           xsltTransformError(NULL, cctxt->style, node,\r
-               "No namespace binding in scope for prefix '%s'.\n", cur);\r
-           /*\r
-           * XSLT-1.0: "It is an error if there is no namespace\r
-           *  bound to the prefix on the element bearing the\r
-           *  exclude-result-prefixes or xsl:exclude-result-prefixes\r
-           *  attribute."\r
-           */\r
-           cctxt->style->errors++;\r
-       } else {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-               "resolved prefix '%s'\n", cur);\r
-#endif\r
-           /*\r
-           * Note that we put the namespace name into the dict.\r
-           */\r
-           if (xsltPointerListAddSize(list,\r
-               (void *) xmlDictLookup(cctxt->style->dict,\r
-               ns->href, -1), 5) == -1)\r
-           {\r
-               xmlFree(cur);\r
-               goto internal_err;\r
-           }\r
-       }\r
-       xmlFree(cur);\r
-               \r
-       cur = end;\r
-    }\r
-    return(0);\r
-\r
-internal_err:\r
-    cctxt->style->errors++;\r
-    return(-1);\r
-}\r
-\r
-/**\r
- * xsltCompilerUtilsCreateMergedList:\r
- * @dest: the destination list (optional)\r
- * @first: the first list\r
- * @second: the second list (optional)\r
- *\r
- * Appends the content of @second to @first into @destination.\r
- * If @destination is NULL a new list will be created.\r
- *\r
- * Returns the merged list of items or NULL if there's nothing to merge.\r
- */\r
-static xsltPointerListPtr\r
-xsltCompilerUtilsCreateMergedList(xsltPointerListPtr first,\r
-                           xsltPointerListPtr second)\r
-{\r
-    xsltPointerListPtr ret;\r
-    size_t num;\r
-\r
-    if (first)\r
-       num = first->number;\r
-    else\r
-       num = 0;\r
-    if (second)\r
-       num += second->number;    \r
-    if (num == 0)\r
-       return(NULL);\r
-    ret = xsltPointerListCreate(num);\r
-    if (ret == NULL)\r
-       return(NULL);\r
-    /*\r
-    * Copy contents.\r
-    */\r
-    if ((first != NULL) &&  (first->number != 0)) {\r
-       memcpy(ret->items, first->items,\r
-           first->number * sizeof(void *));\r
-       if ((second != NULL) && (second->number != 0))\r
-           memcpy(ret->items + first->number, second->items,\r
-               second->number * sizeof(void *));\r
-    } else if ((second != NULL) && (second->number != 0))\r
-       memcpy(ret->items, (void *) second->items,\r
-           second->number * sizeof(void *));\r
-    ret->number = num;\r
-    return(ret);\r
-}\r
-\r
-/*\r
-* xsltParseExclResultPrefixes:\r
-*\r
-* Create and store the list of in-scope namespaces for the given\r
-* node in the stylesheet. If there are no changes in the in-scope\r
-* namespaces then the last ns-info of the ancestor axis will be returned.\r
-* Compilation-time only.\r
-*\r
-* Returns the ns-info or NULL if there are no namespaces in scope.\r
-*/\r
-static xsltPointerListPtr\r
-xsltParseExclResultPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,\r
-                           xsltPointerListPtr def,\r
-                           int instrCategory)\r
-{    \r
-    xsltPointerListPtr list = NULL;\r
-    xmlChar *value;\r
-    xmlAttrPtr attr;\r
-\r
-    if ((cctxt == NULL) || (node == NULL))\r
-       return(NULL);\r
-\r
-    if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)\r
-       attr = xmlHasNsProp(node, BAD_CAST "exclude-result-prefixes", NULL);\r
-    else\r
-       attr = xmlHasNsProp(node, BAD_CAST "exclude-result-prefixes",\r
-           XSLT_NAMESPACE);\r
-    if (attr == NULL)  \r
-       return(def);\r
-\r
-    if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {\r
-       /*\r
-       * Mark the XSLT attr.\r
-       */\r
-       attr->psvi = (void *) xsltXSLTAttrMarker;\r
-    }\r
-\r
-    if ((attr->children != NULL) &&    \r
-       (attr->children->content != NULL))\r
-       value = attr->children->content;\r
-    else {\r
-       xsltTransformError(NULL, cctxt->style, node,\r
-           "Attribute 'exclude-result-prefixes': Invalid value.\n");\r
-       cctxt->style->errors++;\r
-       return(def);\r
-    }        \r
-\r
-    if (xsltParseNsPrefixList(cctxt, cctxt->tmpList, node,\r
-       BAD_CAST value) != 0)\r
-       goto exit;\r
-    if (cctxt->tmpList->number == 0)   \r
-       goto exit;    \r
-    /*\r
-    * Merge the list with the inherited list.\r
-    */\r
-    list = xsltCompilerUtilsCreateMergedList(def, cctxt->tmpList);\r
-    if (list == NULL)\r
-       goto exit;    \r
-    /*\r
-    * Store the list in the stylesheet/compiler context.\r
-    */\r
-    if (xsltPointerListAddSize(\r
-       cctxt->psData->exclResultNamespaces, list, 5) == -1)\r
-    {\r
-       xsltPointerListFree(list);\r
-       list = NULL;\r
-       goto exit;\r
-    }\r
-    /*\r
-    * Notify of change in status wrt namespaces.\r
-    */\r
-    if (cctxt->inode != NULL)\r
-       cctxt->inode->nsChanged = 1;\r
-\r
-exit:    \r
-    if (list != NULL)\r
-       return(list);\r
-    else\r
-       return(def);\r
-}\r
-\r
-/*\r
-* xsltParseExtElemPrefixes:\r
-*\r
-* Create and store the list of in-scope namespaces for the given\r
-* node in the stylesheet. If there are no changes in the in-scope\r
-* namespaces then the last ns-info of the ancestor axis will be returned.\r
-* Compilation-time only.\r
-*\r
-* Returns the ns-info or NULL if there are no namespaces in scope.\r
-*/\r
-static xsltPointerListPtr\r
-xsltParseExtElemPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,\r
-                        xsltPointerListPtr def,\r
-                        int instrCategory)\r
-{    \r
-    xsltPointerListPtr list = NULL;\r
-    xmlAttrPtr attr;\r
-    xmlChar *value;\r
-    int i;\r
-\r
-    if ((cctxt == NULL) || (node == NULL))\r
-       return(NULL);\r
-\r
-    if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)\r
-       attr = xmlHasNsProp(node, BAD_CAST "extension-element-prefixes", NULL);\r
-    else\r
-       attr = xmlHasNsProp(node, BAD_CAST "extension-element-prefixes",\r
-           XSLT_NAMESPACE);\r
-    if (attr == NULL)  \r
-       return(def);\r
-\r
-    if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {\r
-       /*\r
-       * Mark the XSLT attr.\r
-       */\r
-       attr->psvi = (void *) xsltXSLTAttrMarker;\r
-    }\r
-\r
-    if ((attr->children != NULL) &&    \r
-       (attr->children->content != NULL))\r
-       value = attr->children->content;\r
-    else {\r
-       xsltTransformError(NULL, cctxt->style, node,\r
-           "Attribute 'extension-element-prefixes': Invalid value.\n");\r
-       cctxt->style->errors++;\r
-       return(def);\r
-    }\r
-\r
-\r
-    if (xsltParseNsPrefixList(cctxt, cctxt->tmpList, node,\r
-       BAD_CAST value) != 0)\r
-       goto exit;\r
-\r
-    if (cctxt->tmpList->number == 0)\r
-       goto exit;    \r
-    /*\r
-    * REVISIT: Register the extension namespaces.\r
-    */\r
-    for (i = 0; i < cctxt->tmpList->number; i++)\r
-       xsltRegisterExtPrefix(cctxt->style, NULL,\r
-       BAD_CAST cctxt->tmpList->items[i]);\r
-    /*\r
-    * Merge the list with the inherited list.\r
-    */\r
-    list = xsltCompilerUtilsCreateMergedList(def, cctxt->tmpList);\r
-    if (list == NULL)\r
-       goto exit;\r
-    /*\r
-    * Store the list in the stylesheet.\r
-    */\r
-    if (xsltPointerListAddSize(\r
-       cctxt->psData->extElemNamespaces, list, 5) == -1)\r
-    {\r
-       xsltPointerListFree(list);\r
-       list = NULL;\r
-       goto exit;\r
-    }\r
-    /*\r
-    * Notify of change in status wrt namespaces.\r
-    */\r
-    if (cctxt->inode != NULL)\r
-       cctxt->inode->nsChanged = 1;\r
-\r
-exit:    \r
-    if (list != NULL)\r
-       return(list);\r
-    else\r
-       return(def);\r
-}\r
-\r
-/*\r
-* xsltParseAttrXSLTVersion:\r
-*\r
-* @cctxt: the compilation context\r
-* @node: the element-node\r
-* @isXsltElem: whether this is an XSLT element\r
-*\r
-* Parses the attribute xsl:version.\r
-*\r
-* Returns 1 if there was such an attribute, 0 if not and\r
-*         -1 if an internal or API error occured.\r
-*/\r
-static int\r
-xsltParseAttrXSLTVersion(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,                    \r
-                        int instrCategory)\r
-{\r
-    xmlChar *value;\r
-    xmlAttrPtr attr;\r
-\r
-    if ((cctxt == NULL) || (node == NULL))\r
-       return(-1);\r
-\r
-    if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)\r
-       attr = xmlHasNsProp(node, BAD_CAST "version", NULL);\r
-    else\r
-       attr = xmlHasNsProp(node, BAD_CAST "version", XSLT_NAMESPACE);\r
-\r
-    if (attr == NULL)  \r
-       return(0);\r
-\r
-    attr->psvi = (void *) xsltXSLTAttrMarker;\r
-\r
-    if ((attr->children != NULL) &&    \r
-       (attr->children->content != NULL))\r
-       value = attr->children->content;\r
-    else {\r
-       xsltTransformError(NULL, cctxt->style, node,\r
-           "Attribute 'version': Invalid value.\n");\r
-       cctxt->style->errors++;\r
-       return(1);\r
-    }\r
-    \r
-    if (! xmlStrEqual(value, (const xmlChar *)"1.0")) {\r
-       cctxt->inode->forwardsCompat = 1;\r
-       /*\r
-       * TODO: To what extent do we support the\r
-       *  forwards-compatible mode?\r
-       */\r
-       /*\r
-       * Report this only once per compilation episode.\r
-       */\r
-       if (! cctxt->hasForwardsCompat) {\r
-           cctxt->hasForwardsCompat = 1;\r
-           cctxt->errSeverity = XSLT_ERROR_SEVERITY_WARNING;\r
-           xsltTransformError(NULL, cctxt->style, node,\r
-               "Warning: the attribute xsl:version specifies a value "\r
-               "different from '1.0'. Switching to forwards-compatible "\r
-               "mode. Only features of XSLT 1.0 are supported by this "\r
-               "processor.\n");\r
-           cctxt->style->warnings++;\r
-           cctxt->errSeverity = XSLT_ERROR_SEVERITY_ERROR;\r
-       }       \r
-    } else {\r
-       cctxt->inode->forwardsCompat = 0;\r
-    }\r
-\r
-    if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {\r
-       /*\r
-       * Set a marker on XSLT attributes.\r
-       */\r
-       attr->psvi = (void *) xsltXSLTAttrMarker;\r
-    }\r
-    return(1);\r
-}\r
-\r
-static int\r
-xsltParsePreprocessStylesheetTree(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)\r
-{\r
-    xmlNodePtr deleteNode, cur, txt, textNode = NULL;\r
-    xmlDocPtr doc;\r
-    xsltStylesheetPtr style;\r
-    int internalize = 0, findSpaceAttr;\r
-    int xsltStylesheetElemDepth;\r
-    xmlAttrPtr attr;\r
-    xmlChar *value;\r
-    const xmlChar *name, *nsNameXSLT = NULL;\r
-    int strictWhitespace, inXSLText = 0;\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-    xsltNsMapPtr nsMapItem;\r
-#endif\r
-\r
-    if ((cctxt == NULL) || (cctxt->style == NULL) ||\r
-       (node == NULL) || (node->type != XML_ELEMENT_NODE))\r
-        return(-1);\r
-\r
-    doc = node->doc;\r
-    if (doc == NULL)\r
-       goto internal_err;\r
-\r
-    style = cctxt->style;\r
-    if ((style->dict != NULL) && (doc->dict == style->dict))\r
-       internalize = 1;\r
-    else\r
-        style->internalized = 0;\r
-\r
-    /*\r
-    * Init value of xml:space. Since this might be an embedded\r
-    * stylesheet, this is needed to be performed on the element\r
-    * where the stylesheet is rooted at, taking xml:space of\r
-    * ancestors into account.\r
-    */\r
-    if (! cctxt->simplified)\r
-       xsltStylesheetElemDepth = cctxt->depth +1;\r
-    else\r
-       xsltStylesheetElemDepth = 0;\r
-\r
-    if (xmlNodeGetSpacePreserve(node) != 1)\r
-       cctxt->inode->preserveWhitespace = 0;\r
-    else\r
-       cctxt->inode->preserveWhitespace = 1; \r
-    \r
-    /*\r
-    * Eval if we should keep the old incorrect behaviour.\r
-    */\r
-    strictWhitespace = (cctxt->strict != 0) ? 1 : 0;\r
-\r
-    nsNameXSLT = xsltConstNamespaceNameXSLT;\r
-\r
-    deleteNode = NULL;\r
-    cur = node;\r
-    while (cur != NULL) {\r
-       if (deleteNode != NULL) {\r
-\r
-#ifdef WITH_XSLT_DEBUG_BLANKS\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltParsePreprocessStylesheetTree: removing node\n");\r
-#endif\r
-           xmlUnlinkNode(deleteNode);\r
-           xmlFreeNode(deleteNode);\r
-           deleteNode = NULL;\r
-       }\r
-       if (cur->type == XML_ELEMENT_NODE) {\r
-           \r
-           /*\r
-           * Clear the PSVI field.\r
-           */\r
-           cur->psvi = NULL;\r
-\r
-           xsltCompilerNodePush(cctxt, cur);\r
-\r
-           inXSLText = 0;\r
-           textNode = NULL;        \r
-           findSpaceAttr = 1;      \r
-           cctxt->inode->stripWhitespace = 0;\r
-           /*\r
-           * TODO: I'd love to use a string pointer comparison here :-/\r
-           */\r
-           if (IS_XSLT_ELEM(cur)) {\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-               if (cur->ns->href != nsNameXSLT) {\r
-                   nsMapItem = xsltNewNamespaceMapItem(cctxt,\r
-                       doc, cur->ns, cur);\r
-                   if (nsMapItem == NULL)\r
-                       goto internal_err;\r
-                   cur->ns->href = nsNameXSLT;\r
-               }\r
-#endif\r
-\r
-               if (cur->name == NULL)\r
-                   goto process_attributes;\r
-               /*\r
-               * Mark the XSLT element for later recognition.\r
-               * TODO: Using the marker is still too dangerous, since if\r
-               *   the parsing mechanism leaves out an XSLT element, then\r
-               *   this might hit the transformation-mechanism, which\r
-               *   will break if it doesn't expect such a marker.\r
-               */\r
-               /* cur->psvi = (void *) xsltXSLTElemMarker; */\r
-\r
-               /*\r
-               * XSLT 2.0: "Any whitespace text node whose parent is\r
-               * one of the following elements is removed from the "\r
-               * tree, regardless of any xml:space attributes:..."\r
-               * xsl:apply-imports, \r
-               * xsl:apply-templates,\r
-               * xsl:attribute-set,\r
-               * xsl:call-template, \r
-               * xsl:choose,\r
-               * xsl:stylesheet, xsl:transform.\r
-               * XSLT 2.0: xsl:analyze-string,\r
-               *           xsl:character-map,\r
-               *           xsl:next-match              \r
-               *\r
-               * TODO: I'd love to use a string pointer comparison here :-/\r
-               */              \r
-               name = cur->name;\r
-               switch (*name) {\r
-                   case 't':\r
-                       if ((name[0] == 't') && (name[1] == 'e') &&\r
-                           (name[2] == 'x') && (name[3] == 't') &&\r
-                           (name[4] == 0))\r
-                       {\r
-                           /*\r
-                           * Process the xsl:text element.\r
-                           * ----------------------------\r
-                           * Mark it for later recognition.\r
-                           */\r
-                           cur->psvi = (void *) xsltXSLTTextMarker;\r
-                           /*\r
-                           * For stylesheets, the set of\r
-                           * whitespace-preserving element names\r
-                           * consists of just xsl:text.\r
-                           */\r
-                           findSpaceAttr = 0;\r
-                           cctxt->inode->preserveWhitespace = 1;\r
-                           inXSLText = 1;\r
-                       }                           \r
-                       break;\r
-                   case 'c':\r
-                       if (xmlStrEqual(name, BAD_CAST "choose") ||\r
-                           xmlStrEqual(name, BAD_CAST "call-template"))\r
-                           cctxt->inode->stripWhitespace = 1;\r
-                       break;\r
-                   case 'a':\r
-                       if (xmlStrEqual(name, BAD_CAST "apply-templates") ||\r
-                           xmlStrEqual(name, BAD_CAST "apply-imports") ||\r
-                           xmlStrEqual(name, BAD_CAST "attribute-set"))\r
-\r
-                           cctxt->inode->stripWhitespace = 1;\r
-                       break;\r
-                   default:\r
-                       if (xsltStylesheetElemDepth == cctxt->depth) {\r
-                           /*\r
-                           * This is a xsl:stylesheet/xsl:transform.\r
-                           */\r
-                           cctxt->inode->stripWhitespace = 1;\r
-                           break;\r
-                       }\r
-\r
-                       if ((cur->prev != NULL) &&\r
-                           (cur->prev->type == XML_TEXT_NODE))\r
-                       {\r
-                           /*\r
-                           * XSLT 2.0 : "Any whitespace text node whose\r
-                           *  following-sibling node is an xsl:param or\r
-                           *  xsl:sort element is removed from the tree,\r
-                           *  regardless of any xml:space attributes."\r
-                           */\r
-                           if (((*name == 'p') || (*name == 's')) &&\r
-                               (xmlStrEqual(name, BAD_CAST "param") ||\r
-                                xmlStrEqual(name, BAD_CAST "sort")))\r
-                           {\r
-                               do {\r
-                                   if (IS_BLANK_NODE(cur->prev)) {\r
-                                       txt = cur->prev;\r
-                                       xmlUnlinkNode(txt);\r
-                                       xmlFreeNode(txt);\r
-                                   } else {\r
-                                       /*\r
-                                       * This will result in a content\r
-                                       * error, when hitting the parsing\r
-                                       * functions.\r
-                                       */\r
-                                       break;\r
-                                   }\r
-                               } while (cur->prev);                                \r
-                           }\r
-                       }\r
-                       break;\r
-               }\r
-           }\r
-\r
-process_attributes:\r
-           /*\r
-           * Process attributes.\r
-           * ------------------\r
-           */\r
-           if (cur->properties != NULL) {\r
-               if (cur->children == NULL)\r
-                   findSpaceAttr = 0;\r
-               attr = cur->properties;\r
-               do {\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-                   if ((attr->ns) && (attr->ns->href != nsNameXSLT) &&\r
-                       xmlStrEqual(attr->ns->href, nsNameXSLT))\r
-                   {                   \r
-                       nsMapItem = xsltNewNamespaceMapItem(cctxt,\r
-                           doc, attr->ns, cur);\r
-                       if (nsMapItem == NULL)\r
-                           goto internal_err;\r
-                       attr->ns->href = nsNameXSLT;\r
-                   }               \r
-#endif\r
-                   if (internalize) {\r
-                       /*\r
-                       * Internalize the attribute's value; the goal is to\r
-                       * speed up operations and minimize used space by\r
-                       * compiled stylesheets.\r
-                       */\r
-                       txt = attr->children;\r
-                       /*\r
-                       * NOTE that this assumes only one\r
-                       *  text-node in the attribute's content.\r
-                       */\r
-                       if ((txt != NULL) && (txt->content != NULL) &&\r
-                           (!xmlDictOwns(style->dict, txt->content)))\r
-                       {\r
-                           value = (xmlChar *) xmlDictLookup(style->dict,\r
-                               txt->content, -1);\r
-                           xmlNodeSetContent(txt, NULL);\r
-                           txt->content = value;\r
-                       }\r
-                   }\r
-                   /*\r
-                   * Process xml:space attributes.\r
-                   * ----------------------------\r
-                   */\r
-                   if ((findSpaceAttr != 0) &&\r
-                       (attr->ns != NULL) &&\r
-                       (attr->name != NULL) &&\r
-                       (attr->name[0] == 's') &&                       \r
-                       (attr->ns->prefix != NULL) &&\r
-                       (attr->ns->prefix[0] == 'x') &&\r
-                       (attr->ns->prefix[1] == 'm') &&\r
-                       (attr->ns->prefix[2] == 'l') &&\r
-                       (attr->ns->prefix[3] == 0))\r
-                   {\r
-                       value = xmlGetNsProp(cur, BAD_CAST "space",\r
-                           XML_XML_NAMESPACE);\r
-                       if (value != NULL) {\r
-                           if (xmlStrEqual(value, BAD_CAST "preserve")) {\r
-                               cctxt->inode->preserveWhitespace = 1;                           \r
-                           } else if (xmlStrEqual(value, BAD_CAST "default")) {\r
-                               cctxt->inode->preserveWhitespace = 0;\r
-                           } else {\r
-                               /* Invalid value for xml:space. */\r
-                               xsltTransformError(NULL, style, cur,\r
-                                   "Attribute xml:space: Invalid value.\n");\r
-                               cctxt->style->warnings++;\r
-                           }\r
-                           findSpaceAttr = 0;\r
-                           xmlFree(value);\r
-                       }\r
-                       \r
-                   }\r
-                   attr = attr->next;\r
-               } while (attr != NULL);\r
-           }\r
-           /*\r
-           * We'll descend into the children of element nodes only.\r
-           */\r
-           if (cur->children != NULL) {\r
-               cur = cur->children;\r
-               continue;\r
-           }\r
-       } else if ((cur->type == XML_TEXT_NODE) ||\r
-               (cur->type == XML_CDATA_SECTION_NODE))\r
-       {\r
-           /*\r
-           * Merge adjacent text/CDATA-section-nodes\r
-           * ---------------------------------------       \r
-           * In order to avoid breaking of existing stylesheets,\r
-           * if the old behaviour is wanted (strictWhitespace == 0),\r
-           * then we *won't* merge adjacent text-nodes\r
-           * (except in xsl:text); this will ensure that whitespace-only\r
-           * text nodes are (incorrectly) not stripped in some cases.\r
-           * \r
-           * Example:               : <foo>  <!-- bar -->zoo</foo>\r
-           * Corrent (strict) result: <foo>  zoo</foo>\r
-           * Incorrect (old) result : <foo>zoo</foo>\r
-           *    \r
-           * NOTE that we *will* merge adjacent text-nodes if\r
-           * they are in xsl:text.\r
-           * Example, the following:\r
-           * <xsl:text>  <!-- bar -->zoo<xsl:text>\r
-           * will result in both cases in:\r
-           * <xsl:text>  zoo<xsl:text>\r
-           */\r
-           cur->type = XML_TEXT_NODE;\r
-           if ((strictWhitespace != 0) || (inXSLText != 0)) {\r
-               /*\r
-               * New behaviour; merge nodes.\r
-               */\r
-               if (textNode == NULL)\r
-                   textNode = cur;\r
-               else {\r
-                   if (cur->content != NULL)\r
-                       xmlNodeAddContent(textNode, cur->content);\r
-                   deleteNode = cur;\r
-               }\r
-               if ((cur->next == NULL) ||\r
-                   (cur->next->type == XML_ELEMENT_NODE))\r
-                   goto end_of_text;\r
-               else\r
-                   goto next_sibling;\r
-           } else {\r
-               /*\r
-               * Old behaviour.\r
-               */\r
-               if (textNode == NULL)\r
-                   textNode = cur;\r
-               goto end_of_text;\r
-           }              \r
-       } else if ((cur->type == XML_COMMENT_NODE) ||\r
-           (cur->type == XML_PI_NODE))\r
-       {           \r
-           /*\r
-           * Remove processing instructions and comments.\r
-           */\r
-           deleteNode = cur;\r
-           if ((cur->next == NULL) ||\r
-               (cur->next->type == XML_ELEMENT_NODE))\r
-               goto end_of_text;\r
-           else\r
-               goto next_sibling;\r
-       } else {\r
-           textNode = NULL;\r
-           /*\r
-           * Invalid node-type for this data-model.\r
-           */\r
-           xsltTransformError(NULL, style, cur,\r
-               "Invalid type of node for the XSLT data model.\n");\r
-           cctxt->style->errors++;\r
-           goto next_sibling;\r
-       }\r
-\r
-end_of_text:\r
-       if (textNode) {\r
-           value = textNode->content;\r
-           /*\r
-           * At this point all adjacent text/CDATA-section nodes\r
-           * have been merged.\r
-           *\r
-           * Strip whitespace-only text-nodes.\r
-           * (cctxt->inode->stripWhitespace)\r
-           */\r
-           if ((value == NULL) || (*value == 0) ||\r
-               (((cctxt->inode->stripWhitespace) ||\r
-                 (! cctxt->inode->preserveWhitespace)) &&\r
-                IS_BLANK(*value) &&\r
-                xsltIsBlank(value)))\r
-           {           \r
-               if (textNode != cur) {\r
-                   xmlUnlinkNode(textNode);\r
-                   xmlFreeNode(textNode);\r
-               } else\r
-                   deleteNode = textNode;\r
-               textNode = NULL;\r
-               goto next_sibling;\r
-           }\r
-           /*\r
-           * Convert CDATA-section nodes to text-nodes.\r
-           * TODO: Can this produce problems?\r
-           */\r
-           if (textNode->type != XML_TEXT_NODE) {\r
-               textNode->type = XML_TEXT_NODE;\r
-               textNode->name = xmlStringText;\r
-           }\r
-           if (internalize &&\r
-               (textNode->content != NULL) &&\r
-               (!xmlDictOwns(style->dict, textNode->content)))\r
-           {\r
-               /*\r
-               * Internalize the string.\r
-               */\r
-               value = (xmlChar *) xmlDictLookup(style->dict,\r
-                   textNode->content, -1);\r
-               xmlNodeSetContent(textNode, NULL);\r
-               textNode->content = value;\r
-           }\r
-           textNode = NULL;\r
-           /*\r
-           * Note that "disable-output-escaping" of the xsl:text\r
-           * element will be applied at a later level, when\r
-           * XSLT elements are processed.\r
-           */\r
-       }\r
-\r
-next_sibling:\r
-       if (cur->type == XML_ELEMENT_NODE) {\r
-           xsltCompilerNodePop(cctxt, cur);\r
-       }\r
-       if (cur == node)\r
-           break;\r
-       if (cur->next != NULL) {\r
-           cur = cur->next;\r
-       } else {\r
-           cur = cur->parent;\r
-           inXSLText = 0;\r
-           goto next_sibling;\r
-       };\r
-    }\r
-    if (deleteNode != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-        "xsltParsePreprocessStylesheetTree: removing node\n");\r
-#endif\r
-       xmlUnlinkNode(deleteNode);\r
-       xmlFreeNode(deleteNode);\r
-    }\r
-    return(0);\r
-\r
-internal_err:\r
-    return(-1);\r
-}\r
-\r
-#endif /* XSLT_REFACTORED */\r
-\r
-#ifdef XSLT_REFACTORED\r
-#else\r
-static void\r
-xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)\r
-{\r
-    xmlNodePtr deleteNode;\r
-    int internalize = 0;\r
-\r
-    if ((style == NULL) || (cur == NULL))\r
-        return;\r
-\r
-    if ((cur->doc != NULL) && (style->dict != NULL) &&\r
-        (cur->doc->dict == style->dict))\r
-       internalize = 1;\r
-    else\r
-        style->internalized = 0;\r
-    /*\r
-     * This content comes from the stylesheet\r
-     * For stylesheets, the set of whitespace-preserving\r
-     * element names consists of just xsl:text.\r
-     */\r
-    deleteNode = NULL;\r
-    while (cur != NULL) {\r
-       if (deleteNode != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_BLANKS\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltPrecomputeStylesheet: removing ignorable blank node\n");\r
-#endif\r
-           xmlUnlinkNode(deleteNode);\r
-           xmlFreeNode(deleteNode);\r
-           deleteNode = NULL;\r
-       }\r
-       if (cur->type == XML_ELEMENT_NODE) {\r
-           int exclPrefixes;\r
-           /*\r
-            * Internalize attributes values.\r
-            */\r
-           if ((internalize) && (cur->properties != NULL)) {\r
-               xmlAttrPtr attr = cur->properties;\r
-               xmlNodePtr txt;\r
-\r
-               while (attr != NULL) {\r
-                   txt = attr->children;\r
-                   if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&\r
-                       (txt->content != NULL) &&\r
-                       (!xmlDictOwns(style->dict, txt->content)))\r
-                   {\r
-                       xmlChar *tmp;\r
-\r
-                       /*\r
-                        * internalize the text string, goal is to speed\r
-                        * up operations and minimize used space by compiled\r
-                        * stylesheets.\r
-                        */\r
-                       tmp = (xmlChar *) xmlDictLookup(style->dict,\r
-                                                       txt->content, -1);\r
-                       if (tmp != txt->content) {\r
-                           xmlNodeSetContent(txt, NULL);\r
-                           txt->content = tmp;\r
-                       }\r
-                   }\r
-                   attr = attr->next;\r
-               }\r
-           }\r
-           if (IS_XSLT_ELEM(cur)) {\r
-               exclPrefixes = 0;\r
-               xsltStylePreCompute(style, cur);\r
-               if (IS_XSLT_NAME(cur, "text")) {\r
-                   for (;exclPrefixes > 0;exclPrefixes--)\r
-                       exclPrefixPop(style);\r
-                   goto skip_children;\r
-               }\r
-           } else {\r
-               exclPrefixes = xsltParseStylesheetExcludePrefix(style, cur, 0);\r
-           }\r
-                    \r
-           if ((cur->nsDef != NULL) && (style->exclPrefixNr > 0)) {\r
-               xmlNsPtr ns = cur->nsDef, prev = NULL, next;\r
-               xmlNodePtr root = NULL;\r
-               int i, moved;\r
-\r
-               root = xmlDocGetRootElement(cur->doc);\r
-               if ((root != NULL) && (root != cur)) {\r
-                   while (ns != NULL) {\r
-                       moved = 0;\r
-                       next = ns->next;\r
-                       for (i = 0;i < style->exclPrefixNr;i++) {\r
-                           if ((ns->prefix != NULL) && \r
-                               (xmlStrEqual(ns->href,\r
-                                            style->exclPrefixTab[i]))) {\r
-                               /*\r
-                                * Move the namespace definition on the root\r
-                                * element to avoid duplicating it without\r
-                                * loosing it.\r
-                                */\r
-                               if (prev == NULL) {\r
-                                   cur->nsDef = ns->next;\r
-                               } else {\r
-                                   prev->next = ns->next;\r
-                               }\r
-                               ns->next = root->nsDef;\r
-                               root->nsDef = ns;\r
-                               moved = 1;\r
-                               break;\r
-                           }\r
-                       }\r
-                       if (moved == 0)\r
-                           prev = ns;\r
-                       ns = next;\r
-                   }\r
-               }\r
-           }\r
-           /*\r
-            * If we have prefixes locally, recurse and pop them up when\r
-            * going back\r
-            */\r
-           if (exclPrefixes > 0) {\r
-               xsltPrecomputeStylesheet(style, cur->children);\r
-               for (;exclPrefixes > 0;exclPrefixes--)\r
-                   exclPrefixPop(style);\r
-               goto skip_children;\r
-           }\r
-       } else if (cur->type == XML_TEXT_NODE) {\r
-           if (IS_BLANK_NODE(cur)) {\r
-               if (xmlNodeGetSpacePreserve(cur) != 1) {\r
-                   deleteNode = cur;\r
-               }\r
-           } else if ((cur->content != NULL) && (internalize) &&\r
-                      (!xmlDictOwns(style->dict, cur->content))) {\r
-               xmlChar *tmp;\r
-\r
-               /*\r
-                * internalize the text string, goal is to speed\r
-                * up operations and minimize used space by compiled\r
-                * stylesheets.\r
-                */\r
-               tmp = (xmlChar *) xmlDictLookup(style->dict, cur->content, -1);\r
-               xmlNodeSetContent(cur, NULL);\r
-               cur->content = tmp;\r
-           }\r
-       } else if ((cur->type != XML_ELEMENT_NODE) &&\r
-                  (cur->type != XML_CDATA_SECTION_NODE)) {\r
-           deleteNode = cur;\r
-           goto skip_children;\r
-       }\r
-\r
-       /*\r
-        * Skip to next node\r
-        */\r
-       if (cur->children != NULL) {\r
-           if ((cur->children->type != XML_ENTITY_DECL) &&\r
-               (cur->children->type != XML_ENTITY_REF_NODE) &&\r
-               (cur->children->type != XML_ENTITY_NODE)) {\r
-               cur = cur->children;\r
-               continue;\r
-           }\r
-       }\r
-\r
-skip_children:\r
-       if (cur->next != NULL) {\r
-           cur = cur->next;\r
-           continue;\r
-       }       \r
-       do {\r
-\r
-           cur = cur->parent;\r
-           if (cur == NULL)\r
-               break;\r
-           if (cur == (xmlNodePtr) style->doc) {\r
-               cur = NULL;\r
-               break;\r
-           }\r
-           if (cur->next != NULL) {\r
-               cur = cur->next;\r
-               break;\r
-           }\r
-       } while (cur != NULL);\r
-    }\r
-    if (deleteNode != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-        "xsltPrecomputeStylesheet: removing ignorable blank node\n");\r
-#endif\r
-       xmlUnlinkNode(deleteNode);\r
-       xmlFreeNode(deleteNode);\r
-    }\r
-}\r
-#endif /* end of else XSLT_REFACTORED */\r
-\r
-/**\r
- * xsltGatherNamespaces:\r
- * @style:  the XSLT stylesheet\r
- *\r
- * Browse the stylesheet and build the namspace hash table which\r
- * will be used for XPath interpretation. If needed do a bit of normalization\r
- */\r
-\r
-static void\r
-xsltGatherNamespaces(xsltStylesheetPtr style) {\r
-    xmlNodePtr cur;\r
-    const xmlChar *URI;\r
-\r
-    if (style == NULL)\r
-        return;\r
-    /* \r
-     * TODO: basically if the stylesheet uses the same prefix for different\r
-     *       patterns, well they may be in problem, hopefully they will get\r
-     *       a warning first.\r
-     */\r
-    /*\r
-    * TODO: Eliminate the use of the hash for XPath expressions.\r
-    *   An expression should be evaluated in the context of the in-scope\r
-    *   namespaces; eliminate the restriction of an XML document to contain\r
-    *   no duplicate prefixes for different namespace names.\r
-    * \r
-    */\r
-    cur = xmlDocGetRootElement(style->doc);\r
-    while (cur != NULL) {\r
-       if (cur->type == XML_ELEMENT_NODE) {\r
-           xmlNsPtr ns = cur->nsDef;\r
-           while (ns != NULL) {\r
-               if (ns->prefix != NULL) {\r
-                   if (style->nsHash == NULL) {\r
-                       style->nsHash = xmlHashCreate(10);\r
-                       if (style->nsHash == NULL) {\r
-                           xsltTransformError(NULL, style, cur,\r
-                "xsltGatherNamespaces: failed to create hash table\n");\r
-                           style->errors++;\r
-                           return;\r
-                       }\r
-                   }\r
-                   URI = xmlHashLookup(style->nsHash, ns->prefix);\r
-                   if ((URI != NULL) && (!xmlStrEqual(URI, ns->href))) {\r
-                       xsltTransformError(NULL, style, cur,\r
-            "Namespaces prefix %s used for multiple namespaces\n",ns->prefix);\r
-                       style->warnings++;\r
-                   } else if (URI == NULL) {\r
-                       xmlHashUpdateEntry(style->nsHash, ns->prefix,\r
-                           (void *) ns->href, (xmlHashDeallocator)xmlFree);\r
-\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-                       xsltGenericDebug(xsltGenericDebugContext,\r
-                "Added namespace: %s mapped to %s\n", ns->prefix, ns->href);\r
-#endif\r
-                   }\r
-               }\r
-               ns = ns->next;\r
-           }\r
-       }\r
-\r
-       /*\r
-        * Skip to next node\r
-        */\r
-       if (cur->children != NULL) {\r
-           if (cur->children->type != XML_ENTITY_DECL) {\r
-               cur = cur->children;\r
-               continue;\r
-           }\r
-       }\r
-       if (cur->next != NULL) {\r
-           cur = cur->next;\r
-           continue;\r
-       }\r
-       \r
-       do {\r
-           cur = cur->parent;\r
-           if (cur == NULL)\r
-               break;\r
-           if (cur == (xmlNodePtr) style->doc) {\r
-               cur = NULL;\r
-               break;\r
-           }\r
-           if (cur->next != NULL) {\r
-               cur = cur->next;\r
-               break;\r
-           }\r
-       } while (cur != NULL);\r
-    }\r
-}\r
-\r
-#ifdef XSLT_REFACTORED\r
-\r
-static xsltStyleType\r
-xsltGetXSLTElementTypeByNode(xsltCompilerCtxtPtr cctxt,\r
-                            xmlNodePtr node)\r
-{\r
-    if ((node == NULL) || (node->type != XML_ELEMENT_NODE) ||\r
-       (node->name == NULL))\r
-       return(0);\r
-\r
-    if (node->name[0] == 'a') {\r
-       if (IS_XSLT_NAME(node, "apply-templates"))\r
-           return(XSLT_FUNC_APPLYTEMPLATES);\r
-       else if (IS_XSLT_NAME(node, "attribute"))\r
-           return(XSLT_FUNC_ATTRIBUTE);\r
-       else if (IS_XSLT_NAME(node, "apply-imports"))\r
-           return(XSLT_FUNC_APPLYIMPORTS);\r
-       else if (IS_XSLT_NAME(node, "attribute-set"))\r
-           return(0);\r
-\r
-    } else if (node->name[0] == 'c') {\r
-       if (IS_XSLT_NAME(node, "choose"))\r
-           return(XSLT_FUNC_CHOOSE);\r
-       else if (IS_XSLT_NAME(node, "copy"))\r
-           return(XSLT_FUNC_COPY);\r
-       else if (IS_XSLT_NAME(node, "copy-of"))\r
-           return(XSLT_FUNC_COPYOF);\r
-       else if (IS_XSLT_NAME(node, "call-template"))\r
-           return(XSLT_FUNC_CALLTEMPLATE);\r
-       else if (IS_XSLT_NAME(node, "comment"))\r
-           return(XSLT_FUNC_COMMENT);\r
-\r
-    } else if (node->name[0] == 'd') {\r
-       if (IS_XSLT_NAME(node, "document"))\r
-           return(XSLT_FUNC_DOCUMENT);\r
-       else if (IS_XSLT_NAME(node, "decimal-format"))\r
-           return(0);\r
-\r
-    } else if (node->name[0] == 'e') {\r
-       if (IS_XSLT_NAME(node, "element"))\r
-           return(XSLT_FUNC_ELEMENT);\r
-\r
-    } else if (node->name[0] == 'f') {\r
-       if (IS_XSLT_NAME(node, "for-each"))\r
-           return(XSLT_FUNC_FOREACH);\r
-       else if (IS_XSLT_NAME(node, "fallback"))\r
-           return(XSLT_FUNC_FALLBACK);\r
-\r
-    } else if (*(node->name) == 'i') {\r
-       if (IS_XSLT_NAME(node, "if"))\r
-           return(XSLT_FUNC_IF);\r
-       else if (IS_XSLT_NAME(node, "include"))\r
-           return(0);\r
-       else if (IS_XSLT_NAME(node, "import"))\r
-           return(0);\r
-\r
-    } else if (*(node->name) == 'k') {\r
-       if (IS_XSLT_NAME(node, "key"))\r
-           return(0);\r
-\r
-    } else if (*(node->name) == 'm') {\r
-       if (IS_XSLT_NAME(node, "message"))\r
-           return(XSLT_FUNC_MESSAGE);\r
-\r
-    } else if (*(node->name) == 'n') {\r
-       if (IS_XSLT_NAME(node, "number"))\r
-           return(XSLT_FUNC_NUMBER);\r
-       else if (IS_XSLT_NAME(node, "namespace-alias"))\r
-           return(0);\r
-\r
-    } else if (*(node->name) == 'o') {\r
-       if (IS_XSLT_NAME(node, "otherwise"))\r
-           return(XSLT_FUNC_OTHERWISE);\r
-       else if (IS_XSLT_NAME(node, "output"))\r
-           return(0);\r
-\r
-    } else if (*(node->name) == 'p') {\r
-       if (IS_XSLT_NAME(node, "param"))\r
-           return(XSLT_FUNC_PARAM);\r
-       else if (IS_XSLT_NAME(node, "processing-instruction"))\r
-           return(XSLT_FUNC_PI);\r
-       else if (IS_XSLT_NAME(node, "preserve-space"))\r
-           return(0);\r
-\r
-    } else if (*(node->name) == 's') {\r
-       if (IS_XSLT_NAME(node, "sort"))\r
-           return(XSLT_FUNC_SORT);\r
-       else if (IS_XSLT_NAME(node, "strip-space"))\r
-           return(0);\r
-       else if (IS_XSLT_NAME(node, "stylesheet"))\r
-           return(0);\r
-\r
-    } else if (node->name[0] == 't') {\r
-       if (IS_XSLT_NAME(node, "text"))\r
-           return(XSLT_FUNC_TEXT);\r
-       else if (IS_XSLT_NAME(node, "template"))\r
-           return(0);\r
-       else if (IS_XSLT_NAME(node, "transform"))\r
-           return(0);\r
-\r
-    } else if (*(node->name) == 'v') {\r
-       if (IS_XSLT_NAME(node, "value-of"))\r
-           return(XSLT_FUNC_VALUEOF);\r
-       else if (IS_XSLT_NAME(node, "variable"))\r
-           return(XSLT_FUNC_VARIABLE);\r
-\r
-    } else if (*(node->name) == 'w') {\r
-       if (IS_XSLT_NAME(node, "when"))\r
-           return(XSLT_FUNC_WHEN);\r
-       if (IS_XSLT_NAME(node, "with-param"))\r
-           return(XSLT_FUNC_WITHPARAM);\r
-    }\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltParseAnyXSLTElem:\r
- *\r
- * @cctxt: the compilation context\r
- * @elem: the element node of the XSLT instruction\r
- *\r
- * Parses, validates the content models and compiles XSLT instructions.\r
- *\r
- * Returns 0 if everything's fine;\r
- *         -1 on API or internal errors.\r
- */ \r
-int\r
-xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)\r
-{\r
-    if ((cctxt == NULL) || (elem == NULL) ||\r
-       (elem->type != XML_ELEMENT_NODE))\r
-       return(-1);\r
-\r
-    elem->psvi = NULL;\r
-\r
-    if (! (IS_XSLT_ELEM_FAST(elem)))\r
-       return(-1);\r
-    /*\r
-    * Detection of handled content of extension instructions.\r
-    */\r
-    if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {\r
-       cctxt->inode->extContentHandled = 1;\r
-    }\r
-    \r
-    xsltCompilerNodePush(cctxt, elem);\r
-    /*\r
-    * URGENT TODO: Find a way to speed up this annoying redundant\r
-    *  textual node-name and namespace comparison.\r
-    */\r
-    if (cctxt->inode->prev->curChildType != 0)\r
-       cctxt->inode->type = cctxt->inode->prev->curChildType;\r
-    else\r
-       cctxt->inode->type = xsltGetXSLTElementTypeByNode(cctxt, elem);    \r
-    /*\r
-    * Update the in-scope namespaces if needed.\r
-    */\r
-    if (elem->nsDef != NULL)\r
-       cctxt->inode->inScopeNs =\r
-           xsltCompilerBuildInScopeNsList(cctxt, elem);\r
-    /*\r
-    * xsltStylePreCompute():\r
-    *  This will compile the information found on the current\r
-    *  element's attributes. NOTE that this won't process the\r
-    *  children of the instruction.\r
-    */\r
-    xsltStylePreCompute(cctxt->style, elem);\r
-    /*\r
-    * TODO: How to react on errors in xsltStylePreCompute() ?\r
-    */\r
-\r
-    /*\r
-    * Validate the content model of the XSLT-element.\r
-    */\r
-    switch (cctxt->inode->type) {      \r
-       case XSLT_FUNC_APPLYIMPORTS:\r
-           /* EMPTY */\r
-           goto empty_content;\r
-       case XSLT_FUNC_APPLYTEMPLATES:\r
-           /* <!-- Content: (xsl:sort | xsl:with-param)* --> */\r
-           goto apply_templates;           \r
-       case XSLT_FUNC_ATTRIBUTE:           \r
-           /* <!-- Content: template --> */\r
-           goto sequence_constructor;\r
-       case XSLT_FUNC_CALLTEMPLATE:\r
-           /* <!-- Content: xsl:with-param* --> */\r
-           goto call_template;\r
-       case XSLT_FUNC_CHOOSE:      \r
-           /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */\r
-           goto choose;\r
-       case XSLT_FUNC_COMMENT:\r
-           /* <!-- Content: template --> */\r
-           goto sequence_constructor;      \r
-       case XSLT_FUNC_COPY:\r
-           /* <!-- Content: template --> */\r
-           goto sequence_constructor;      \r
-       case XSLT_FUNC_COPYOF:\r
-           /* EMPTY */\r
-           goto empty_content;    \r
-       case XSLT_FUNC_DOCUMENT: /* Extra one */\r
-           /* ?? template ?? */\r
-           goto sequence_constructor;\r
-       case XSLT_FUNC_ELEMENT:\r
-           /* <!-- Content: template --> */\r
-           goto sequence_constructor;\r
-       case XSLT_FUNC_FALLBACK:\r
-           /* <!-- Content: template --> */\r
-           goto sequence_constructor;\r
-       case XSLT_FUNC_FOREACH:\r
-           /* <!-- Content: (xsl:sort*, template) --> */\r
-           goto for_each;\r
-       case XSLT_FUNC_IF:\r
-           /* <!-- Content: template --> */\r
-           goto sequence_constructor;\r
-       case XSLT_FUNC_OTHERWISE:\r
-           /* <!-- Content: template --> */\r
-           goto sequence_constructor;\r
-       case XSLT_FUNC_MESSAGE:\r
-           /* <!-- Content: template --> */\r
-           goto sequence_constructor;\r
-       case XSLT_FUNC_NUMBER:\r
-           /* EMPTY */\r
-           goto empty_content;\r
-       case XSLT_FUNC_PARAM:\r
-           /*\r
-           * Check for redefinition.\r
-           */\r
-           if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {\r
-               xsltVarInfoPtr ivar = cctxt->ivar;\r
-\r
-               do {\r
-                   if ((ivar->name ==\r
-                        ((xsltStyleItemParamPtr) elem->psvi)->name) &&\r
-                       (ivar->nsName ==\r
-                        ((xsltStyleItemParamPtr) elem->psvi)->ns))\r
-                   {\r
-                       elem->psvi = NULL;\r
-                       xsltTransformError(NULL, cctxt->style, elem,\r
-                           "Redefinition of variable or parameter '%s'.\n",\r
-                           ivar->name);\r
-                       cctxt->style->errors++;\r
-                       goto error;\r
-                   }\r
-                   ivar = ivar->prev;\r
-               } while (ivar != NULL);\r
-           }\r
-           /*  <!-- Content: template --> */\r
-           goto sequence_constructor;\r
-       case XSLT_FUNC_PI:\r
-           /*  <!-- Content: template --> */\r
-           goto sequence_constructor;\r
-       case XSLT_FUNC_SORT:\r
-           /* EMPTY */\r
-           goto empty_content;\r
-       case XSLT_FUNC_TEXT:\r
-           /* <!-- Content: #PCDATA --> */\r
-           goto text;\r
-       case XSLT_FUNC_VALUEOF:\r
-           /* EMPTY */\r
-           goto empty_content;\r
-       case XSLT_FUNC_VARIABLE:\r
-           /*\r
-           * Check for redefinition.\r
-           */\r
-           if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {\r
-               xsltVarInfoPtr ivar = cctxt->ivar;              \r
-\r
-               do {\r
-                   if ((ivar->name ==\r
-                        ((xsltStyleItemVariablePtr) elem->psvi)->name) &&\r
-                       (ivar->nsName ==\r
-                        ((xsltStyleItemVariablePtr) elem->psvi)->ns))\r
-                   {\r
-                       elem->psvi = NULL;\r
-                       xsltTransformError(NULL, cctxt->style, elem,\r
-                           "Redefinition of variable or parameter '%s'.\n",\r
-                           ivar->name);\r
-                       cctxt->style->errors++;\r
-                       goto error;\r
-                   }\r
-                   ivar = ivar->prev;\r
-               } while (ivar != NULL);\r
-           }\r
-           /* <!-- Content: template --> */\r
-           goto sequence_constructor;\r
-       case XSLT_FUNC_WHEN:\r
-           /* <!-- Content: template --> */\r
-           goto sequence_constructor;\r
-       case XSLT_FUNC_WITHPARAM:\r
-           /* <!-- Content: template --> */\r
-           goto sequence_constructor;\r
-       default:\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsltParseXSLTNode: Unhandled XSLT element '%s'.\n",\r
-               elem->name);        \r
-#endif\r
-           xsltTransformError(NULL, cctxt->style, elem,\r
-               "xsltParseXSLTNode: Internal error; "\r
-               "unhandled XSLT element '%s'.\n", elem->name);\r
-           cctxt->style->errors++;\r
-           goto internal_err;\r
-    }\r
-\r
-apply_templates:\r
-    /* <!-- Content: (xsl:sort | xsl:with-param)* --> */\r
-    if (elem->children != NULL) {\r
-       xmlNodePtr child = elem->children;\r
-       do {\r
-           if (child->type == XML_ELEMENT_NODE) {\r
-               if (IS_XSLT_ELEM_FAST(child)) {\r
-                   if (xmlStrEqual(child->name, BAD_CAST "with-param")) {\r
-                       cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;\r
-                       xsltParseAnyXSLTElem(cctxt, child);\r
-                   } else if (xmlStrEqual(child->name, BAD_CAST "sort")) {\r
-                       cctxt->inode->curChildType = XSLT_FUNC_SORT;\r
-                       xsltParseAnyXSLTElem(cctxt, child);\r
-                   } else\r
-                       xsltParseContentError(cctxt->style, child);\r
-               } else\r
-                   xsltParseContentError(cctxt->style, child);\r
-           }\r
-           child = child->next;\r
-       } while (child != NULL);\r
-    }    \r
-    goto exit;\r
-\r
-call_template:\r
-    /* <!-- Content: xsl:with-param* --> */\r
-    if (elem->children != NULL) {\r
-       xmlNodePtr child = elem->children;\r
-       do {\r
-           if (child->type == XML_ELEMENT_NODE) {\r
-               if (IS_XSLT_ELEM_FAST(child)) {\r
-                   xsltStyleType type;\r
-\r
-                   type = xsltGetXSLTElementTypeByNode(cctxt, child);\r
-                   if (type == XSLT_FUNC_WITHPARAM) {\r
-                       cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;\r
-                       xsltParseAnyXSLTElem(cctxt, child);\r
-                   } else {\r
-                       xsltParseContentError(cctxt->style, child);\r
-                   }\r
-               } else\r
-                   xsltParseContentError(cctxt->style, child);\r
-           }\r
-           child = child->next;\r
-       } while (child != NULL);\r
-    }    \r
-    goto exit;\r
-\r
-text:\r
-    if (elem->children != NULL) {\r
-       xmlNodePtr child = elem->children;\r
-       do {\r
-           if ((child->type != XML_TEXT_NODE) &&\r
-               (child->type != XML_CDATA_SECTION_NODE))\r
-           {\r
-               xsltTransformError(NULL, cctxt->style, elem,\r
-                   "The XSLT 'text' element must have only character "\r
-                   "data as content.\n");\r
-           }\r
-           child = child->next;\r
-       } while (child != NULL);\r
-    }\r
-    goto exit;\r
-\r
-empty_content:\r
-    if (elem->children != NULL) {\r
-       xmlNodePtr child = elem->children;\r
-       /*\r
-       * Relaxed behaviour: we will allow whitespace-only text-nodes.\r
-       */\r
-       do {\r
-           if (((child->type != XML_TEXT_NODE) &&\r
-                (child->type != XML_CDATA_SECTION_NODE)) ||\r
-               (! IS_BLANK_NODE(child)))\r
-           {\r
-               xsltTransformError(NULL, cctxt->style, elem,\r
-                   "This XSLT element must have no content.\n");\r
-               cctxt->style->errors++;\r
-               break;\r
-           }\r
-           child = child->next;\r
-       } while (child != NULL);                \r
-    }\r
-    goto exit;\r
-\r
-choose:\r
-    /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */\r
-    /*\r
-    * TODO: text-nodes in between are *not* allowed in XSLT 1.0.\r
-    *   The old behaviour did not check this.\r
-    * NOTE: In XSLT 2.0 they are stripped beforehand\r
-    *  if whitespace-only (regardless of xml:space).\r
-    */\r
-    if (elem->children != NULL) {\r
-       xmlNodePtr child = elem->children;\r
-       int nbWhen = 0, nbOtherwise = 0, err = 0;\r
-       do {\r
-           if (child->type == XML_ELEMENT_NODE) {\r
-               if (IS_XSLT_ELEM_FAST(child)) {\r
-                   xsltStyleType type;\r
-               \r
-                   type = xsltGetXSLTElementTypeByNode(cctxt, child);\r
-                   if (type == XSLT_FUNC_WHEN) {\r
-                       nbWhen++;\r
-                       if (nbOtherwise) {\r
-                           xsltParseContentError(cctxt->style, child);\r
-                           err = 1;\r
-                           break;\r
-                       }\r
-                       cctxt->inode->curChildType = XSLT_FUNC_WHEN;\r
-                       xsltParseAnyXSLTElem(cctxt, child);\r
-                   } else if (type == XSLT_FUNC_OTHERWISE) {\r
-                       if (! nbWhen) {\r
-                           xsltParseContentError(cctxt->style, child);\r
-                           err = 1;\r
-                           break;\r
-                       }                       \r
-                       if (nbOtherwise) {\r
-                           xsltTransformError(NULL, cctxt->style, elem,\r
-                               "The XSLT 'choose' element must not contain "\r
-                               "more than one XSLT 'otherwise' element.\n");\r
-                           cctxt->style->errors++;\r
-                           err = 1;\r
-                           break;\r
-                       }\r
-                       nbOtherwise++;\r
-                       cctxt->inode->curChildType = XSLT_FUNC_OTHERWISE;\r
-                       xsltParseAnyXSLTElem(cctxt, child);\r
-                   } else\r
-                       xsltParseContentError(cctxt->style, child);\r
-               } else\r
-                   xsltParseContentError(cctxt->style, child);\r
-           } \r
-           /*\r
-               else\r
-                   xsltParseContentError(cctxt, child);\r
-           */\r
-           child = child->next;\r
-       } while (child != NULL);\r
-       if ((! err) && (! nbWhen)) {\r
-           xsltTransformError(NULL, cctxt->style, elem,\r
-               "The XSLT element 'choose' must contain at least one "\r
-               "XSLT element 'when'.\n");\r
-               cctxt->style->errors++;\r
-       }       \r
-    }    \r
-    goto exit;\r
-\r
-for_each:\r
-    /* <!-- Content: (xsl:sort*, template) --> */\r
-    /*\r
-    * NOTE: Text-nodes before xsl:sort are *not* allowed in XSLT 1.0.\r
-    *   The old behaviour did not allow this, but it catched this\r
-    *   only at transformation-time.\r
-    *   In XSLT 2.0 they are stripped beforehand if whitespace-only\r
-    *   (regardless of xml:space).\r
-    */\r
-    if (elem->children != NULL) {\r
-       xmlNodePtr child = elem->children;\r
-       /*\r
-       * Parse xsl:sort first.\r
-       */\r
-       do {        \r
-           if ((child->type == XML_ELEMENT_NODE) &&\r
-               IS_XSLT_ELEM_FAST(child))\r
-           {           \r
-               if (xsltGetXSLTElementTypeByNode(cctxt, child) ==\r
-                   XSLT_FUNC_SORT)\r
-               {               \r
-                   cctxt->inode->curChildType = XSLT_FUNC_SORT;\r
-                   xsltParseAnyXSLTElem(cctxt, child);\r
-               } else\r
-                   break;\r
-           } else\r
-               break;\r
-           child = child->next;\r
-       } while (child != NULL);\r
-       /*\r
-       * Parse the sequece constructor.\r
-       */\r
-       if (child != NULL)\r
-           xsltParseSequenceConstructor(cctxt, child);\r
-    }    \r
-    goto exit;\r
-\r
-sequence_constructor:\r
-    /*\r
-    * Parse the sequence constructor.\r
-    */\r
-    if (elem->children != NULL)\r
-       xsltParseSequenceConstructor(cctxt, elem->children);\r
-\r
-    /*\r
-    * Register information for vars/params. Only needed if there\r
-    * are any following siblings.\r
-    */\r
-    if ((elem->next != NULL) &&\r
-       ((cctxt->inode->type == XSLT_FUNC_VARIABLE) ||\r
-        (cctxt->inode->type == XSLT_FUNC_PARAM)))\r
-    {  \r
-       if ((elem->psvi != NULL) &&\r
-           (((xsltStyleBasicItemVariablePtr) elem->psvi)->name))\r
-       {       \r
-           xsltCompilerVarInfoPush(cctxt, elem,\r
-               ((xsltStyleBasicItemVariablePtr) elem->psvi)->name,\r
-               ((xsltStyleBasicItemVariablePtr) elem->psvi)->ns);\r
-       }\r
-    }\r
-\r
-error:\r
-exit:\r
-    xsltCompilerNodePop(cctxt, elem);\r
-    return(0);\r
-\r
-internal_err:\r
-    xsltCompilerNodePop(cctxt, elem);\r
-    return(-1);\r
-}\r
-\r
-/**\r
- * xsltForwardsCompatUnkownItemCreate:\r
- *\r
- * @cctxt: the compilation context \r
- *\r
- * Creates a compiled representation of the unknown\r
- * XSLT instruction.\r
- *\r
- * Returns the compiled representation.\r
- */ \r
-static xsltStyleItemUknownPtr\r
-xsltForwardsCompatUnkownItemCreate(xsltCompilerCtxtPtr cctxt)\r
-{\r
-    xsltStyleItemUknownPtr item;\r
-\r
-    item = (xsltStyleItemUknownPtr) xmlMalloc(sizeof(xsltStyleItemUknown));\r
-    if (item == NULL) {\r
-       xsltTransformError(NULL, cctxt->style, NULL,\r
-           "Internal error in xsltForwardsCompatUnkownItemCreate(): "\r
-           "Failed to allocate memory.\n");\r
-       cctxt->style->errors++;\r
-       return(NULL);\r
-    }\r
-    memset(item, 0, sizeof(xsltStyleItemUknown));\r
-    item->type = XSLT_FUNC_UNKOWN_FORWARDS_COMPAT;\r
-    /*\r
-    * Store it in the stylesheet.\r
-    */\r
-    item->next = cctxt->style->preComps;\r
-    cctxt->style->preComps = (xsltElemPreCompPtr) item;\r
-    return(item);\r
-}\r
-\r
-/**\r
- * xsltParseUnknownXSLTElem:\r
- *\r
- * @cctxt: the compilation context\r
- * @node: the element of the unknown XSLT instruction\r
- *\r
- * Parses an unknown XSLT element.\r
- * If forwards compatible mode is enabled this will allow\r
- * such an unknown XSLT and; otherwise it is rejected.\r
- *\r
- * Returns 1 in the unknown XSLT instruction is rejected,\r
- *         0 if everything's fine and\r
- *         -1 on API or internal errors.\r
- */ \r
-static int\r
-xsltParseUnknownXSLTElem(xsltCompilerCtxtPtr cctxt,\r
-                           xmlNodePtr node)\r
-{\r
-    if ((cctxt == NULL) || (node == NULL))\r
-       return(-1);\r
-\r
-    /*\r
-    * Detection of handled content of extension instructions.\r
-    */\r
-    if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {\r
-       cctxt->inode->extContentHandled = 1;\r
-    }    \r
-    if (cctxt->inode->forwardsCompat == 0) {   \r
-       /*\r
-       * We are not in forwards-compatible mode, so raise an error.\r
-       */\r
-       xsltTransformError(NULL, cctxt->style, node,\r
-           "Unknown XSLT element '%s'.\n", node->name);\r
-       cctxt->style->errors++;\r
-       return(1);\r
-    }\r
-    /*\r
-    * Forwards-compatible mode.\r
-    * ------------------------\r
-    *    \r
-    * Parse/compile xsl:fallback elements.\r
-    *\r
-    * QUESTION: Do we have to raise an error if there's no xsl:fallback?\r
-    * ANSWER: No, since in the stylesheet the fallback behaviour might\r
-    *  also be provided by using the XSLT function "element-available".\r
-    */\r
-    if (cctxt->unknownItem == NULL) {\r
-       /*\r
-       * Create a singleton for all unknown XSLT instructions.\r
-       */\r
-       cctxt->unknownItem = xsltForwardsCompatUnkownItemCreate(cctxt);\r
-       if (cctxt->unknownItem == NULL) {\r
-           node->psvi = NULL;\r
-           return(-1);\r
-       }\r
-    }\r
-    node->psvi = cctxt->unknownItem;\r
-    if (node->children == NULL)\r
-       return(0);\r
-    else {\r
-       xmlNodePtr child = node->children;\r
-\r
-       xsltCompilerNodePush(cctxt, node);\r
-       /*\r
-       * Update the in-scope namespaces if needed.\r
-       */\r
-       if (node->nsDef != NULL)\r
-           cctxt->inode->inScopeNs =\r
-               xsltCompilerBuildInScopeNsList(cctxt, node);\r
-       /*\r
-       * Parse all xsl:fallback children.\r
-       */\r
-       do {\r
-           if ((child->type == XML_ELEMENT_NODE) &&\r
-               IS_XSLT_ELEM_FAST(child) &&\r
-               IS_XSLT_NAME(child, "fallback"))\r
-           {\r
-               cctxt->inode->curChildType = XSLT_FUNC_FALLBACK;\r
-               xsltParseAnyXSLTElem(cctxt, child);\r
-           }\r
-           child = child->next;\r
-       } while (child != NULL);\r
-       \r
-       xsltCompilerNodePop(cctxt, node);\r
-    }\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltParseSequenceConstructor:\r
- *\r
- * @cctxt: the compilation context\r
- * @cur: the start-node of the content to be parsed\r
- *\r
- * Parses a "template" content (or "sequence constructor" in XSLT 2.0 terms).\r
- * This will additionally remove xsl:text elements from the tree.\r
- */ \r
-void\r
-xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)\r
-{\r
-    xsltStyleType type;\r
-    xmlNodePtr deleteNode = NULL;\r
-\r
-    if (cctxt == NULL) {\r
-       xmlGenericError(xmlGenericErrorContext,\r
-           "xsltParseSequenceConstructor: Bad arguments\n");\r
-       cctxt->style->errors++;\r
-       return;\r
-    }\r
-    /*\r
-    * Detection of handled content of extension instructions.\r
-    */\r
-    if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {\r
-       cctxt->inode->extContentHandled = 1;\r
-    }\r
-    if (cur == NULL)\r
-       return;\r
-    /*\r
-    * This is the content reffered to as a "template".\r
-    * E.g. an xsl:element has such content model:\r
-    * <xsl:element\r
-    *   name = { qname }\r
-    *   namespace = { uri-reference }\r
-    *   use-attribute-sets = qnames>\r
-    * <!-- Content: template -->\r
-    *\r
-    * NOTE that in XSLT-2 the term "template" was abandoned due to\r
-    *  confusion with xsl:template and the term "sequence constructor"\r
-    *  was introduced instead.\r
-    *\r
-    * The following XSLT-instructions are allowed to appear:\r
-    *  xsl:apply-templates, xsl:call-template, xsl:apply-imports,\r
-    *  xsl:for-each, xsl:value-of, xsl:copy-of, xsl:number,\r
-    *  xsl:choose, xsl:if, xsl:text, xsl:copy, xsl:variable,\r
-    *  xsl:message, xsl:fallback,\r
-    *  xsl:processing-instruction, xsl:comment, xsl:element\r
-    *  xsl:attribute. \r
-    * Additional allowed content:\r
-    * 1) extension instructions\r
-    * 2) literal result elements\r
-    * 3) PCDATA\r
-    *\r
-    * NOTE that this content model does *not* allow xsl:param.\r
-    */    \r
-    while (cur != NULL) {\r
-       if (deleteNode != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_BLANKS\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltParseSequenceConstructor: removing xsl:text element\n");\r
-#endif\r
-           xmlUnlinkNode(deleteNode);\r
-           xmlFreeNode(deleteNode);\r
-           deleteNode = NULL;\r
-       }\r
-       if (cur->type == XML_ELEMENT_NODE) {        \r
-           \r
-           if (cur->psvi == xsltXSLTTextMarker) {\r
-               /*\r
-               * xsl:text elements\r
-               * --------------------------------------------------------\r
-               */\r
-               xmlNodePtr tmp;\r
-\r
-               cur->psvi = NULL;\r
-               /*\r
-               * Mark the xsl:text element for later deletion.\r
-               */\r
-               deleteNode = cur;\r
-               /*\r
-               * Validate content.\r
-               */\r
-               tmp = cur->children;\r
-               if (tmp) {\r
-                   /*\r
-                   * We don't expect more than one text-node in the\r
-                   * content, since we already merged adjacent\r
-                   * text/CDATA-nodes and eliminated PI/comment-nodes.\r
-                   */\r
-                   if ((tmp->type == XML_TEXT_NODE) ||\r
-                       (tmp->next == NULL))\r
-                   {\r
-                       /*\r
-                       * Leave the contained text-node in the tree.\r
-                       */\r
-                       xmlUnlinkNode(tmp);\r
-                       xmlAddPrevSibling(cur, tmp);\r
-                   } else {\r
-                       tmp = NULL;\r
-                       xsltTransformError(NULL, cctxt->style, cur,\r
-                           "Element 'xsl:text': Invalid type "\r
-                           "of node found in content.\n");\r
-                       cctxt->style->errors++;\r
-                   } \r
-               }\r
-               if (cur->properties) {\r
-                   xmlAttrPtr attr;\r
-                   /*\r
-                   * TODO: We need to report errors for\r
-                   *  invalid attrs.\r
-                   */\r
-                   attr = cur->properties;\r
-                   do {\r
-                       if ((attr->ns == NULL) &&\r
-                           (attr->name != NULL) &&\r
-                           (attr->name[0] == 'd') &&\r
-                           xmlStrEqual(attr->name,\r
-                           BAD_CAST "disable-output-escaping"))\r
-                       {\r
-                           /*\r
-                           * Attr "disable-output-escaping".\r
-                           * XSLT-2: This attribute is deprecated.\r
-                           */\r
-                           if ((attr->children != NULL) &&\r
-                               xmlStrEqual(attr->children->content,\r
-                               BAD_CAST "yes"))\r
-                           {\r
-                               /*\r
-                               * Disable output escaping for this\r
-                               * text node.\r
-                               */\r
-                               if (tmp)\r
-                                   tmp->name = xmlStringTextNoenc;\r
-                           } else if ((attr->children == NULL) ||\r
-                               (attr->children->content == NULL) ||\r
-                               (!xmlStrEqual(attr->children->content,\r
-                               BAD_CAST "no")))\r
-                           {\r
-                               xsltTransformError(NULL, cctxt->style,\r
-                                   cur,\r
-                                   "Attribute 'disable-output-escaping': "\r
-                                   "Invalid value. Expected is "\r
-                                   "'yes' or 'no'.\n");\r
-                               cctxt->style->errors++;\r
-                           }\r
-                           break;\r
-                       }\r
-                       attr = attr->next;\r
-                   } while (attr != NULL);\r
-               }\r
-           } else if (IS_XSLT_ELEM_FAST(cur)) {\r
-               /*\r
-               * TODO: Using the XSLT-marker is still not stable yet.\r
-               */\r
-               /* if (cur->psvi == xsltXSLTElemMarker) { */        \r
-               /*\r
-               * XSLT instructions\r
-               * --------------------------------------------------------\r
-               */\r
-               cur->psvi = NULL;\r
-               type = xsltGetXSLTElementTypeByNode(cctxt, cur);\r
-               switch (type) {\r
-                   case XSLT_FUNC_APPLYIMPORTS:\r
-                   case XSLT_FUNC_APPLYTEMPLATES:\r
-                   case XSLT_FUNC_ATTRIBUTE:\r
-                   case XSLT_FUNC_CALLTEMPLATE:\r
-                   case XSLT_FUNC_CHOOSE:\r
-                   case XSLT_FUNC_COMMENT:\r
-                   case XSLT_FUNC_COPY:\r
-                   case XSLT_FUNC_COPYOF:\r
-                   case XSLT_FUNC_DOCUMENT: /* Extra one */\r
-                   case XSLT_FUNC_ELEMENT:\r
-                   case XSLT_FUNC_FALLBACK:\r
-                   case XSLT_FUNC_FOREACH:\r
-                   case XSLT_FUNC_IF:\r
-                   case XSLT_FUNC_MESSAGE:\r
-                   case XSLT_FUNC_NUMBER:\r
-                   case XSLT_FUNC_PI:\r
-                   case XSLT_FUNC_TEXT:\r
-                   case XSLT_FUNC_VALUEOF:\r
-                   case XSLT_FUNC_VARIABLE:\r
-                       /*\r
-                       * Parse the XSLT element.\r
-                       */\r
-                       cctxt->inode->curChildType = type;\r
-                       xsltParseAnyXSLTElem(cctxt, cur);\r
-                       break;\r
-                   default:\r
-                       xsltParseUnknownXSLTElem(cctxt, cur);                   \r
-                       cur = cur->next;\r
-                       continue;\r
-               }\r
-           } else {\r
-               /*\r
-               * Non-XSLT elements\r
-               * -----------------\r
-               */\r
-               xsltCompilerNodePush(cctxt, cur);\r
-               /*\r
-               * Update the in-scope namespaces if needed.\r
-               */\r
-               if (cur->nsDef != NULL)\r
-                   cctxt->inode->inScopeNs =\r
-                       xsltCompilerBuildInScopeNsList(cctxt, cur);\r
-               /*\r
-               * The current element is either a literal result element\r
-               * or an extension instruction.\r
-               *\r
-               * Process attr "xsl:extension-element-prefixes".\r
-               * FUTURE TODO: IIRC in XSLT 2.0 this attribute must be\r
-               * processed by the implementor of the extension function;\r
-               * i.e., it won't be handled by the XSLT processor.\r
-               */\r
-               /* SPEC 1.0:\r
-               *   "exclude-result-prefixes" is only allowed on literal\r
-               *   result elements and "xsl:exclude-result-prefixes"\r
-               *   on xsl:stylesheet/xsl:transform.\r
-               * SPEC 2.0:\r
-               *   "There are a number of standard attributes\r
-               *   that may appear on any XSLT element: specifically\r
-               *   version, exclude-result-prefixes,\r
-               *   extension-element-prefixes, xpath-default-namespace,\r
-               *   default-collation, and use-when."\r
-               *\r
-               * SPEC 2.0:\r
-               *   For literal result elements:\r
-               *   "xsl:version, xsl:exclude-result-prefixes,\r
-               *    xsl:extension-element-prefixes,\r
-               *    xsl:xpath-default-namespace,\r
-               *    xsl:default-collation, or xsl:use-when."\r
-               */\r
-               if (cur->properties)\r
-                   cctxt->inode->extElemNs =\r
-                       xsltParseExtElemPrefixes(cctxt,\r
-                           cur, cctxt->inode->extElemNs,\r
-                           XSLT_ELEMENT_CATEGORY_LRE);\r
-               /*\r
-               * Eval if we have an extension instruction here.\r
-               */\r
-               if ((cur->ns != NULL) &&\r
-                   (cctxt->inode->extElemNs != NULL) &&\r
-                   (xsltCheckExtPrefix(cctxt->style, cur->ns->href) == 1))\r
-               {\r
-                   /*\r
-                   * Extension instructions\r
-                   * ----------------------------------------------------\r
-                   * Mark the node information.\r
-                   */\r
-                   cctxt->inode->category = XSLT_ELEMENT_CATEGORY_EXTENSION;\r
-                   cctxt->inode->extContentHandled = 0;\r
-                   if (cur->psvi != NULL) {\r
-                       cur->psvi = NULL;\r
-                       /*\r
-                       * TODO: Temporary sanity check.\r
-                       */\r
-                       xsltTransformError(NULL, cctxt->style, cur,\r
-                           "Internal error in xsltParseSequenceConstructor(): "\r
-                           "Occupied PSVI field.\n");\r
-                       cctxt->style->errors++;\r
-                       cur = cur->next;\r
-                       continue;\r
-                   }\r
-                   cur->psvi = (void *)\r
-                       xsltPreComputeExtModuleElement(cctxt->style, cur);\r
-                   \r
-                   if (cur->psvi == NULL) {\r
-                       /*\r
-                       * OLD COMMENT: "Unknown element, maybe registered\r
-                       *  at the context level. Mark it for later\r
-                       *  recognition."\r
-                       * QUESTION: What does the xsltExtMarker mean?\r
-                       *  ANSWER: It is used in\r
-                       *   xsltApplySequenceConstructor() at\r
-                       *   transformation-time to look out for extension\r
-                       *   registered in the transformation context.\r
-                       */\r
-                       cur->psvi = (void *) xsltExtMarker;\r
-                   }\r
-                   /*\r
-                   * BIG NOTE: Now the ugly part. In previous versions\r
-                   *  of Libxslt (until 1.1.16), all the content of an\r
-                   *  extension instruction was processed and compiled without\r
-                   *  the need of the extension-author to explicitely call\r
-                   *  such a processing;.We now need to mimic this old\r
-                   *  behaviour in order to avoid breaking old code\r
-                   *  on the extension-author's side.\r
-                   * The mechanism:\r
-                   *  1) If the author does *not* set the\r
-                   *    compile-time-flag @extContentHandled, then we'll\r
-                   *    parse the content assuming that it's a "template"\r
-                   *    (or "sequence constructor in XSLT 2.0 terms).\r
-                   *    NOTE: If the extension is registered at\r
-                   *    transformation-time only, then there's no way of\r
-                   *    knowing that content shall be valid, and we'll\r
-                   *    process the content the same way.\r
-                   *  2) If the author *does* set the flag, then we'll assume\r
-                   *   that the author has handled the parsing him/herself\r
-                   *   (e.g. called xsltParseSequenceConstructor(), etc.\r
-                   *   explicitely in his/her code).\r
-                   */\r
-                   if ((cur->children != NULL) &&\r
-                       (cctxt->inode->extContentHandled == 0))\r
-                   {\r
-                       /*\r
-                       * Default parsing of the content using the\r
-                       * sequence-constructor model.\r
-                       */\r
-                       xsltParseSequenceConstructor(cctxt, cur->children);\r
-                   }\r
-               } else {\r
-                   /*\r
-                   * Literal result element\r
-                   * ----------------------------------------------------\r
-                   * Allowed XSLT attributes:\r
-                   *  xsl:extension-element-prefixes CDATA #IMPLIED\r
-                   *  xsl:exclude-result-prefixes CDATA #IMPLIED\r
-                   *  TODO: xsl:use-attribute-sets %qnames; #IMPLIED\r
-                   *  xsl:version NMTOKEN #IMPLIED\r
-                   */\r
-                   cur->psvi = NULL;\r
-                   cctxt->inode->category = XSLT_ELEMENT_CATEGORY_LRE;\r
-                   if (cur->properties != NULL) {\r
-                       xmlAttrPtr attr = cur->properties;\r
-                       /*\r
-                       * Attribute "xsl:exclude-result-prefixes".\r
-                       */\r
-                       cctxt->inode->exclResultNs =\r
-                           xsltParseExclResultPrefixes(cctxt, cur,\r
-                               cctxt->inode->exclResultNs,\r
-                               XSLT_ELEMENT_CATEGORY_LRE);\r
-                       /*\r
-                       * Attribute "xsl:version".\r
-                       */\r
-                       xsltParseAttrXSLTVersion(cctxt, cur,\r
-                           XSLT_ELEMENT_CATEGORY_LRE);\r
-                       /*\r
-                       * Report invalid XSLT attributes.                       \r
-                       * For XSLT 1.0 only xsl:use-attribute-sets is allowed\r
-                       * next to xsl:version, xsl:exclude-result-prefixes and\r
-                       * xsl:extension-element-prefixes.\r
-                       *\r
-                       * Mark all XSLT attributes, in order to skip such\r
-                       * attributes when instantiating the LRE.\r
-                       */\r
-                       do {\r
-                           if ((attr->psvi != xsltXSLTAttrMarker) &&\r
-                               IS_XSLT_ATTR_FAST(attr))\r
-                           {                               \r
-                               if (! xmlStrEqual(attr->name,\r
-                                   BAD_CAST "use-attribute-sets"))\r
-                               {                               \r
-                                   xsltTransformError(NULL, cctxt->style,\r
-                                       cur,\r
-                                       "Unknown XSLT attribute '%s'.\n",\r
-                                       attr->name);\r
-                                   cctxt->style->errors++;\r
-                               } else {\r
-                                   /*\r
-                                   * XSLT attr marker.\r
-                                   */\r
-                                   attr->psvi = (void *) xsltXSLTAttrMarker;\r
-                               }\r
-                           }\r
-                           attr = attr->next;\r
-                       } while (attr != NULL);\r
-                   }\r
-                   /*\r
-                   * Create/reuse info for the literal result element.\r
-                   */\r
-                   if (cctxt->inode->nsChanged)\r
-                       xsltLREInfoCreate(cctxt, cur, 1);\r
-                   cur->psvi = cctxt->inode->litResElemInfo;\r
-                   /*\r
-                   * Apply ns-aliasing on the element and on its attributes.\r
-                   */\r
-                   if (cctxt->hasNsAliases)\r
-                       xsltLREBuildEffectiveNs(cctxt, cur);\r
-                   /*\r
-                   * Compile attribute value templates (AVT).\r
-                   */\r
-                   if (cur->properties) {\r
-                       xmlAttrPtr attr = cur->properties;\r
-                       \r
-                       while (attr != NULL) {\r
-                           xsltCompileAttr(cctxt->style, attr);\r
-                           attr = attr->next;\r
-                       }\r
-                   }\r
-                   /*\r
-                   * Parse the content, which is defined to be a "template"\r
-                   * (or "sequence constructor" in XSLT 2.0 terms).\r
-                   */\r
-                   if (cur->children != NULL) {\r
-                       xsltParseSequenceConstructor(cctxt, cur->children);\r
-                   }\r
-               }\r
-               /*\r
-               * Leave the non-XSLT element.\r
-               */\r
-               xsltCompilerNodePop(cctxt, cur);\r
-           }\r
-       }\r
-       cur = cur->next;\r
-    }\r
-    if (deleteNode != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_BLANKS\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-           "xsltParseSequenceConstructor: removing xsl:text element\n");\r
-#endif\r
-       xmlUnlinkNode(deleteNode);\r
-       xmlFreeNode(deleteNode);\r
-       deleteNode = NULL;\r
-    }\r
-}\r
-\r
-/**\r
- * xsltParseTemplateContent:\r
- * @style:  the XSLT stylesheet\r
- * @templ:  the node containing the content to be parsed\r
- *\r
- * Parses and compiles the content-model of an xsl:template element.\r
- * Note that this is *not* the "template" content model (or "sequence\r
- *  constructor" in XSLT 2.0); it it allows addional xsl:param\r
- *  elements as immediate children of @templ.\r
- *\r
- * Called by: \r
- *   exsltFuncFunctionComp() (EXSLT, functions.c)\r
- *   So this is intended to be called from extension functions.\r
- */\r
-void\r
-xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {\r
-    if ((style == NULL) || (templ == NULL))\r
-       return;\r
-\r
-    /*\r
-    * Detection of handled content of extension instructions.\r
-    */\r
-    if (XSLT_CCTXT(style)->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {\r
-       XSLT_CCTXT(style)->inode->extContentHandled = 1;\r
-    }\r
-\r
-    if (templ->children != NULL) {     \r
-       xmlNodePtr child = templ->children;\r
-       /*\r
-       * Process xsl:param elements, which can only occur as the\r
-       * immediate children of xsl:template (well, and of any\r
-       * user-defined extension instruction if needed).\r
-       */      \r
-       do {\r
-           if ((child->type == XML_ELEMENT_NODE) &&\r
-               IS_XSLT_ELEM_FAST(child) &&\r
-               IS_XSLT_NAME(child, "param"))\r
-           {\r
-               XSLT_CCTXT(style)->inode->curChildType = XSLT_FUNC_PARAM;\r
-               xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);\r
-           } else\r
-               break;\r
-           child = child->next;\r
-       } while (child != NULL);\r
-       /*\r
-       * Parse the content and register the pattern.\r
-       */\r
-       xsltParseSequenceConstructor(XSLT_CCTXT(style), child);\r
-    }\r
-}\r
-\r
-#else /* XSLT_REFACTORED */\r
-\r
-/**\r
- * xsltParseTemplateContent:\r
- * @style:  the XSLT stylesheet\r
- * @templ:  the container node (can be a document for literal results)\r
- *\r
- * parse a template content-model\r
- * Clean-up the template content from unwanted ignorable blank nodes\r
- * and process xslt:text\r
- */\r
-void\r
-xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {\r
-    xmlNodePtr cur, delete;\r
-    /*\r
-     * This content comes from the stylesheet\r
-     * For stylesheets, the set of whitespace-preserving\r
-     * element names consists of just xsl:text.\r
-     */\r
-    cur = templ->children;\r
-    delete = NULL;\r
-    while (cur != NULL) {\r
-       if (delete != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_BLANKS\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltParseTemplateContent: removing text\n");\r
-#endif\r
-           xmlUnlinkNode(delete);\r
-           xmlFreeNode(delete);\r
-           delete = NULL;\r
-       }\r
-       if (IS_XSLT_ELEM(cur)) {\r
-           if (IS_XSLT_NAME(cur, "text")) {\r
-               /*\r
-               * TODO: Processing of xsl:text should be moved to\r
-               *   xsltPrecomputeStylesheet(), since otherwise this\r
-               *   will be performed for every multiply included\r
-               *   stylesheet; i.e. this here is not skipped with\r
-               *   the use of the style->nopreproc flag.\r
-               */\r
-               if (cur->children != NULL) {\r
-                   xmlChar *prop;\r
-                   xmlNodePtr text = cur->children, next;\r
-                   int noesc = 0;\r
-                       \r
-                   prop = xmlGetNsProp(cur,\r
-                       (const xmlChar *)"disable-output-escaping",\r
-                       NULL);\r
-                   if (prop != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-                       xsltGenericDebug(xsltGenericDebugContext,\r
-                            "Disable escaping: %s\n", text->content);\r
-#endif\r
-                       if (xmlStrEqual(prop, (const xmlChar *)"yes")) {\r
-                           noesc = 1;\r
-                       } else if (!xmlStrEqual(prop,\r
-                                               (const xmlChar *)"no")){\r
-                           xsltTransformError(NULL, style, cur,\r
-            "xsl:text: disable-output-escaping allows only yes or no\n");\r
-                           style->warnings++;\r
-\r
-                       }\r
-                       xmlFree(prop);\r
-                   }\r
-\r
-                   while (text != NULL) {\r
-                       if (text->type == XML_COMMENT_NODE) {\r
-                           text = text->next;\r
-                           continue;\r
-                       }\r
-                       if ((text->type != XML_TEXT_NODE) &&\r
-                            (text->type != XML_CDATA_SECTION_NODE)) {\r
-                           xsltTransformError(NULL, style, cur,\r
-                "xsltParseTemplateContent: xslt:text content problem\n");\r
-                           style->errors++;\r
-                           break;\r
-                       }\r
-                       if ((noesc) && (text->type != XML_CDATA_SECTION_NODE))\r
-                           text->name = xmlStringTextNoenc;\r
-                       text = text->next;\r
-                   }\r
-\r
-                   /*\r
-                    * replace xsl:text by the list of childs\r
-                    */\r
-                   if (text == NULL) {\r
-                       text = cur->children;\r
-                       while (text != NULL) {\r
-                           if ((style->internalized) &&\r
-                               (text->content != NULL) &&\r
-                               (!xmlDictOwns(style->dict, text->content))) {\r
-\r
-                               /*\r
-                                * internalize the text string\r
-                                */\r
-                               if (text->doc->dict != NULL) {\r
-                                   const xmlChar *tmp;\r
-                                   \r
-                                   tmp = xmlDictLookup(text->doc->dict,\r
-                                                       text->content, -1);\r
-                                   if (tmp != text->content) {\r
-                                       xmlNodeSetContent(text, NULL);\r
-                                       text->content = (xmlChar *) tmp;\r
-                                   }\r
-                               }\r
-                           }\r
-\r
-                           next = text->next;\r
-                           xmlUnlinkNode(text);\r
-                           xmlAddPrevSibling(cur, text);\r
-                           text = next;\r
-                       }\r
-                   }\r
-               }\r
-               delete = cur;\r
-               goto skip_children;\r
-           }\r
-       }\r
-       else if ((cur->ns != NULL) && (style->nsDefs != NULL) &&\r
-           (xsltCheckExtPrefix(style, cur->ns->prefix)))\r
-       {\r
-           /*\r
-            * okay this is an extension element compile it too\r
-            */\r
-           xsltStylePreCompute(style, cur);\r
-       } else {\r
-           /*\r
-            * This is an element which will be output as part of the\r
-            * template exectution, precompile AVT if found.\r
-            */\r
-           if ((cur->ns == NULL) && (style->defaultAlias != NULL) &&\r
-                       (cur->type == XML_ELEMENT_NODE)) {\r
-               cur->ns = xmlSearchNsByHref(cur->doc, cur,\r
-                       style->defaultAlias);\r
-           }\r
-           if (cur->properties != NULL) {\r
-               xmlAttrPtr attr = cur->properties;\r
-\r
-               while (attr != NULL) {\r
-                   xsltCompileAttr(style, attr);\r
-                   attr = attr->next;\r
-               }\r
-           }\r
-       }\r
-       /*\r
-        * Skip to next node\r
-        */\r
-       if (cur->children != NULL) {\r
-           if (cur->children->type != XML_ENTITY_DECL) {\r
-               cur = cur->children;\r
-               continue;\r
-           }\r
-       }\r
-skip_children:\r
-       if (cur->next != NULL) {\r
-           cur = cur->next;\r
-           continue;\r
-       }\r
-       \r
-       do {\r
-           cur = cur->parent;\r
-           if (cur == NULL)\r
-               break;\r
-           if (cur == templ) {\r
-               cur = NULL;\r
-               break;\r
-           }\r
-           if (cur->next != NULL) {\r
-               cur = cur->next;\r
-               break;\r
-           }\r
-       } while (cur != NULL);\r
-    }\r
-    if (delete != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-        "xsltParseTemplateContent: removing text\n");\r
-#endif\r
-       xmlUnlinkNode(delete);\r
-       xmlFreeNode(delete);\r
-       delete = NULL;\r
-    }\r
-\r
-    /*\r
-     * Skip the first params\r
-     */\r
-    cur = templ->children;\r
-    while (cur != NULL) {\r
-       if ((IS_XSLT_ELEM(cur)) && (!(IS_XSLT_NAME(cur, "param"))))\r
-           break;\r
-       cur = cur->next;\r
-    }\r
-\r
-    /*\r
-     * Browse the remainder of the template\r
-     */\r
-    while (cur != NULL) {\r
-       if ((IS_XSLT_ELEM(cur)) && (IS_XSLT_NAME(cur, "param"))) {\r
-           xmlNodePtr param = cur;\r
-\r
-           xsltTransformError(NULL, style, cur,\r
-               "xsltParseTemplateContent: ignoring misplaced param element\n");\r
-           if (style != NULL) style->warnings++;\r
-            cur = cur->next;\r
-           xmlUnlinkNode(param);\r
-           xmlFreeNode(param);\r
-       } else\r
-           break;\r
-    }\r
-}\r
-\r
-#endif /* else XSLT_REFACTORED */\r
-\r
-/**\r
- * xsltParseStylesheetKey:\r
- * @style:  the XSLT stylesheet\r
- * @key:  the "key" element\r
- *\r
- * <!-- Category: top-level-element -->\r
- * <xsl:key name = qname, match = pattern, use = expression />\r
- *\r
- * parse an XSLT stylesheet key definition and register it\r
- */\r
-\r
-static void\r
-xsltParseStylesheetKey(xsltStylesheetPtr style, xmlNodePtr key) {\r
-    xmlChar *prop = NULL;\r
-    xmlChar *use = NULL;\r
-    xmlChar *match = NULL;\r
-    xmlChar *name = NULL;\r
-    xmlChar *nameURI = NULL;\r
-\r
-    if ((style == NULL) || (key == NULL))\r
-       return;\r
-\r
-    /*\r
-     * Get arguments\r
-     */\r
-    prop = xmlGetNsProp(key, (const xmlChar *)"name", NULL);\r
-    if (prop != NULL) {\r
-        const xmlChar *URI;\r
-\r
-       /*\r
-       * TODO: Don't use xsltGetQNameURI().\r
-       */\r
-       URI = xsltGetQNameURI(key, &prop);\r
-       if (prop == NULL) {\r
-           if (style != NULL) style->errors++;\r
-           goto error;\r
-       } else {\r
-           name = prop;\r
-           if (URI != NULL)\r
-               nameURI = xmlStrdup(URI);\r
-       }\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltParseStylesheetKey: name %s\n", name);\r
-#endif\r
-    } else {\r
-       xsltTransformError(NULL, style, key,\r
-           "xsl:key : error missing name\n");\r
-       if (style != NULL) style->errors++;\r
-       goto error;\r
-    }\r
-\r
-    match = xmlGetNsProp(key, (const xmlChar *)"match", NULL);\r
-    if (match == NULL) {\r
-       xsltTransformError(NULL, style, key,\r
-           "xsl:key : error missing match\n");\r
-       if (style != NULL) style->errors++;\r
-       goto error;\r
-    }\r
-\r
-    use = xmlGetNsProp(key, (const xmlChar *)"use", NULL);\r
-    if (use == NULL) {\r
-       xsltTransformError(NULL, style, key,\r
-           "xsl:key : error missing use\n");\r
-       if (style != NULL) style->errors++;\r
-       goto error;\r
-    }\r
-\r
-    /*\r
-     * register the keys\r
-     */\r
-    xsltAddKey(style, name, nameURI, match, use, key);\r
-\r
-\r
-error:\r
-    if (use != NULL)\r
-       xmlFree(use);\r
-    if (match != NULL)\r
-       xmlFree(match);\r
-    if (name != NULL)\r
-       xmlFree(name);\r
-    if (nameURI != NULL)\r
-       xmlFree(nameURI);\r
-\r
-    if (key->children != NULL) {\r
-       xsltParseContentError(style, key->children);\r
-    }\r
-}\r
-\r
-#ifdef XSLT_REFACTORED\r
-/**\r
- * xsltParseXSLTTemplate:\r
- * @style:  the XSLT stylesheet\r
- * @template:  the "template" element\r
- *\r
- * parse an XSLT stylesheet template building the associated structures\r
- * TODO: Is @style ever expected to be NULL?\r
- *\r
- * Called from:\r
- *   xsltParseXSLTStylesheet()\r
- *   xsltParseStylesheetTop()\r
- */\r
-\r
-static void\r
-xsltParseXSLTTemplate(xsltCompilerCtxtPtr cctxt, xmlNodePtr templNode) {\r
-    xsltTemplatePtr templ;\r
-    xmlChar *prop;    \r
-    double  priority;    \r
-\r
-    if ((cctxt == NULL) || (templNode == NULL))\r
-       return;\r
-\r
-    /*\r
-     * Create and link the structure\r
-     */\r
-    templ = xsltNewTemplate();\r
-    if (templ == NULL)\r
-       return;\r
-\r
-    xsltCompilerNodePush(cctxt, templNode);\r
-    if (templNode->nsDef != NULL)\r
-       cctxt->inode->inScopeNs =\r
-           xsltCompilerBuildInScopeNsList(cctxt, templNode);\r
-\r
-    templ->next = cctxt->style->templates;\r
-    cctxt->style->templates = templ;\r
-    templ->style = cctxt->style;  \r
-\r
-    /*\r
-    * Attribute "mode".\r
-    */\r
-    prop = xmlGetNsProp(templNode, (const xmlChar *)"mode", NULL);\r
-    if (prop != NULL) {        \r
-        const xmlChar *modeURI;\r
-\r
-       /*\r
-       * TODO: We need a standardized function for extraction\r
-       *  of namespace names and local names from QNames.\r
-       *  Don't use xsltGetQNameURI() as it cannot channeö\r
-       *  reports through the context.\r
-       */\r
-       modeURI = xsltGetQNameURI(templNode, &prop);\r
-       if (prop == NULL) {\r
-           cctxt->style->errors++;\r
-           goto error;\r
-       }\r
-       templ->mode = xmlDictLookup(cctxt->style->dict, prop, -1);\r
-       xmlFree(prop);\r
-       prop = NULL;\r
-       if (xmlValidateNCName(templ->mode, 0)) {\r
-           xsltTransformError(NULL, cctxt->style, templNode,\r
-               "xsl:template: Attribute 'mode': The local part '%s' "\r
-               "of the value is not a valid NCName.\n", templ->name);\r
-           cctxt->style->errors++;\r
-           goto error;\r
-       }\r
-       if (modeURI != NULL)\r
-           templ->modeURI = xmlDictLookup(cctxt->style->dict, modeURI, -1);\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltParseXSLTTemplate: mode %s\n", templ->mode);\r
-#endif\r
-    }\r
-    /*\r
-    * Attribute "match".\r
-    */\r
-    prop = xmlGetNsProp(templNode, (const xmlChar *)"match", NULL);\r
-    if (prop != NULL) {\r
-       templ->match  = prop;\r
-       prop = NULL;\r
-    }\r
-    /*\r
-    * Attribute "priority".\r
-    */\r
-    prop = xmlGetNsProp(templNode, (const xmlChar *)"priority", NULL);\r
-    if (prop != NULL) {\r
-       priority = xmlXPathStringEvalNumber(prop);\r
-       templ->priority = (float) priority;\r
-       xmlFree(prop);\r
-       prop = NULL;\r
-    }\r
-    /*\r
-    * Attribute "name".\r
-    */\r
-    prop = xmlGetNsProp(templNode, (const xmlChar *)"name", NULL);\r
-    if (prop != NULL) {\r
-        const xmlChar *nameURI;\r
-       xsltTemplatePtr curTempl;\r
-       \r
-       /*\r
-       * TODO: Don't use xsltGetQNameURI().\r
-       */\r
-       nameURI = xsltGetQNameURI(templNode, &prop);\r
-       if (prop == NULL) {\r
-           cctxt->style->errors++;\r
-           goto error;\r
-       }\r
-       templ->name = xmlDictLookup(cctxt->style->dict, prop, -1);\r
-       xmlFree(prop);\r
-       prop = NULL;\r
-       if (xmlValidateNCName(templ->name, 0)) {\r
-           xsltTransformError(NULL, cctxt->style, templNode,\r
-               "xsl:template: Attribute 'name': The local part '%s' of "\r
-               "the value is not a valid NCName.\n", templ->name);\r
-           cctxt->style->errors++;\r
-           goto error;\r
-       }       \r
-       if (nameURI != NULL)\r
-           templ->nameURI = xmlDictLookup(cctxt->style->dict, nameURI, -1);\r
-       curTempl = templ->next;\r
-       while (curTempl != NULL) {\r
-           if ((nameURI != NULL && xmlStrEqual(curTempl->name, templ->name) &&\r
-               xmlStrEqual(curTempl->nameURI, nameURI) ) ||\r
-               (nameURI == NULL && curTempl->nameURI == NULL &&\r
-               xmlStrEqual(curTempl->name, templ->name)))\r
-           {\r
-               xsltTransformError(NULL, cctxt->style, templNode,\r
-                   "xsl:template: error duplicate name '%s'\n", templ->name);\r
-               cctxt->style->errors++;\r
-               goto error;\r
-           }\r
-           curTempl = curTempl->next;\r
-       }\r
-    }\r
-    if (templNode->children != NULL) {\r
-       xsltParseTemplateContent(cctxt->style, templNode);      \r
-       /*\r
-       * MAYBE TODO: Custom behaviour: In order to stay compatible with\r
-       * Xalan and MSXML(.NET), we could allow whitespace\r
-       * to appear before an xml:param element; this whitespace\r
-       * will additionally become part of the "template".\r
-       * NOTE that this is totally deviates from the spec, but\r
-       * is the de facto behaviour of Xalan and MSXML(.NET).\r
-       * Personally I wouldn't allow this, since if we have:\r
-       * <xsl:template ...xml:space="preserve">\r
-       *   <xsl:param name="foo"/>\r
-       *   <xsl:param name="bar"/>\r
-       *   <xsl:param name="zoo"/>\r
-       * ... the whitespace between every xsl:param would be\r
-       * added to the result tree.\r
-       */              \r
-    }    \r
-    \r
-    templ->elem = templNode;\r
-    templ->content = templNode->children;\r
-    xsltAddTemplate(cctxt->style, templ, templ->mode, templ->modeURI);\r
-\r
-error:\r
-    xsltCompilerNodePop(cctxt, templNode);\r
-    return;\r
-}\r
-\r
-#else /* XSLT_REFACTORED */\r
-\r
-/**\r
- * xsltParseStylesheetTemplate:\r
- * @style:  the XSLT stylesheet\r
- * @template:  the "template" element\r
- *\r
- * parse an XSLT stylesheet template building the associated structures\r
- */\r
-\r
-static void\r
-xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {\r
-    xsltTemplatePtr ret;\r
-    xmlChar *prop;\r
-    xmlChar *mode = NULL;\r
-    xmlChar *modeURI = NULL;\r
-    double  priority;\r
-\r
-    if (template == NULL)\r
-       return;\r
-\r
-    /*\r
-     * Create and link the structure\r
-     */\r
-    ret = xsltNewTemplate();\r
-    if (ret == NULL)\r
-       return;\r
-    ret->next = style->templates;\r
-    style->templates = ret;\r
-    ret->style = style;\r
-   \r
-    /*\r
-     * Get inherited namespaces\r
-     */\r
-    /*\r
-    * TODO: Apply the optimized in-scope-namespace mechanism\r
-    *   as for the other XSLT instructions.\r
-    */\r
-    xsltGetInheritedNsList(style, ret, template);\r
-\r
-    /*\r
-     * Get arguments\r
-     */\r
-    prop = xmlGetNsProp(template, (const xmlChar *)"mode", NULL);\r
-    if (prop != NULL) {\r
-        const xmlChar *URI;\r
-\r
-       /*\r
-       * TODO: Don't use xsltGetQNameURI().\r
-       */\r
-       URI = xsltGetQNameURI(template, &prop);\r
-       if (prop == NULL) {\r
-           if (style != NULL) style->errors++;\r
-           goto error;\r
-       } else {\r
-           mode = prop;\r
-           if (URI != NULL)\r
-               modeURI = xmlStrdup(URI);\r
-       }\r
-       ret->mode = xmlDictLookup(style->dict, mode, -1);\r
-       ret->modeURI = xmlDictLookup(style->dict, modeURI, -1);\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-            "xsltParseStylesheetTemplate: mode %s\n", mode);\r
-#endif\r
-        if (mode != NULL) xmlFree(mode);\r
-       if (modeURI != NULL) xmlFree(modeURI);\r
-    }\r
-    prop = xmlGetNsProp(template, (const xmlChar *)"match", NULL);\r
-    if (prop != NULL) {\r
-       if (ret->match != NULL) xmlFree(ret->match);\r
-       ret->match  = prop;\r
-    }\r
-\r
-    prop = xmlGetNsProp(template, (const xmlChar *)"priority", NULL);\r
-    if (prop != NULL) {\r
-       priority = xmlXPathStringEvalNumber(prop);\r
-       ret->priority = (float) priority;\r
-       xmlFree(prop);\r
-    }\r
-\r
-    prop = xmlGetNsProp(template, (const xmlChar *)"name", NULL);\r
-    if (prop != NULL) {\r
-        const xmlChar *URI;\r
-       xsltTemplatePtr cur;\r
-       \r
-       /*\r
-       * TODO: Don't use xsltGetQNameURI().\r
-       */\r
-       URI = xsltGetQNameURI(template, &prop);\r
-       if (prop == NULL) {\r
-           if (style != NULL) style->errors++;\r
-           goto error;\r
-       } else {\r
-           if (xmlValidateNCName(prop,0)) {\r
-               xsltTransformError(NULL, style, template,\r
-                   "xsl:template : error invalid name '%s'\n", prop);\r
-               if (style != NULL) style->errors++;\r
-               goto error;\r
-           }\r
-           ret->name = xmlDictLookup(style->dict, BAD_CAST prop, -1);\r
-           xmlFree(prop);\r
-           prop = NULL;\r
-           if (URI != NULL)\r
-               ret->nameURI = xmlDictLookup(style->dict, BAD_CAST URI, -1);\r
-           else\r
-               ret->nameURI = NULL;\r
-           cur = ret->next;\r
-           while (cur != NULL) {\r
-               if ((URI != NULL && xmlStrEqual(cur->name, ret->name) &&\r
-                               xmlStrEqual(cur->nameURI, URI) ) ||\r
-                   (URI == NULL && cur->nameURI == NULL &&\r
-                               xmlStrEqual(cur->name, ret->name))) {\r
-                   xsltTransformError(NULL, style, template,\r
-                       "xsl:template: error duplicate name '%s'\n", ret->name);\r
-                   style->errors++;\r
-                   goto error;\r
-               }\r
-               cur = cur->next;\r
-           }\r
-       }\r
-    }\r
-\r
-    /*\r
-     * parse the content and register the pattern\r
-     */\r
-    xsltParseTemplateContent(style, template);\r
-    ret->elem = template;\r
-    ret->content = template->children;\r
-    xsltAddTemplate(style, ret, ret->mode, ret->modeURI);\r
-\r
-error:\r
-    return;\r
-}\r
-\r
-#endif /* else XSLT_REFACTORED */\r
-\r
-#ifdef XSLT_REFACTORED\r
-\r
-/**\r
- * xsltIncludeComp:\r
- * @cctxt: the compilation contenxt\r
- * @node:  the xsl:include node\r
- *\r
- * Process the xslt include node on the source node\r
- */\r
-static xsltStyleItemIncludePtr\r
-xsltCompileXSLTIncludeElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node) {\r
-    xsltStyleItemIncludePtr item;\r
-\r
-    if ((cctxt == NULL) || (node == NULL))\r
-       return(NULL);\r
-\r
-    node->psvi = NULL;\r
-    item = (xsltStyleItemIncludePtr) xmlMalloc(sizeof(xsltStyleItemInclude));\r
-    if (item == NULL) {\r
-       xsltTransformError(NULL, cctxt->style, node,\r
-               "xsltIncludeComp : malloc failed\n");\r
-       cctxt->style->errors++;\r
-       return(NULL);\r
-    }\r
-    memset(item, 0, sizeof(xsltStyleItemInclude));\r
-\r
-    node->psvi = item;\r
-    item->inst = node;\r
-    item->type = XSLT_FUNC_INCLUDE;\r
-\r
-    item->next = cctxt->style->preComps;\r
-    cctxt->style->preComps = (xsltElemPreCompPtr) item;\r
-\r
-    return(item);\r
-}\r
-\r
-/**\r
- * xsltParseFindTopLevelElem:\r
- */\r
-static int\r
-xsltParseFindTopLevelElem(xsltCompilerCtxtPtr cctxt,\r
-                             xmlNodePtr cur,\r
-                             const xmlChar *name,\r
-                             const xmlChar *namespaceURI,\r
-                             int breakOnOtherElem,                           \r
-                             xmlNodePtr *resultNode)\r
-{\r
-    if (name == NULL)\r
-       return(-1);\r
-\r
-    *resultNode = NULL;\r
-    while (cur != NULL) {\r
-       if (cur->type == XML_ELEMENT_NODE) {\r
-           if ((cur->ns != NULL) && (cur->name != NULL)) {\r
-               if ((*(cur->name) == *name) &&\r
-                   xmlStrEqual(cur->name, name) &&\r
-                   xmlStrEqual(cur->ns->href, namespaceURI))               \r
-               {\r
-                   *resultNode = cur;\r
-                   return(1);\r
-               }\r
-           }\r
-           if (breakOnOtherElem)\r
-               break;\r
-       }\r
-       cur = cur->next;\r
-    }\r
-    *resultNode = cur;\r
-    return(0);\r
-}\r
-\r
-static int\r
-xsltParseTopLevelXSLTElem(xsltCompilerCtxtPtr cctxt,\r
-                         xmlNodePtr node,\r
-                         xsltStyleType type)\r
-{\r
-    int ret = 0;\r
-\r
-    /*\r
-    * TODO: The reason why this function exists:\r
-    *  due to historical reasons some of the\r
-    *  top-level declarations are processed by functions\r
-    *  in other files. Since we need still to set\r
-    *  up the node-info and generate information like\r
-    *  in-scope namespaces, this is a wrapper around\r
-    *  those old parsing functions.\r
-    */\r
-    xsltCompilerNodePush(cctxt, node);\r
-    if (node->nsDef != NULL)\r
-       cctxt->inode->inScopeNs =\r
-           xsltCompilerBuildInScopeNsList(cctxt, node);\r
-    cctxt->inode->type = type;\r
-\r
-    switch (type) {\r
-       case XSLT_FUNC_INCLUDE:\r
-           {\r
-               int oldIsInclude;\r
-\r
-               if (xsltCompileXSLTIncludeElem(cctxt, node) == NULL)\r
-                   goto exit;          \r
-               /*\r
-               * Mark this stylesheet tree as being currently included.\r
-               */\r
-               oldIsInclude = cctxt->isInclude;\r
-               cctxt->isInclude = 1;\r
-                                               \r
-               if (xsltParseStylesheetInclude(cctxt->style, node) != 0) {\r
-                   cctxt->style->errors++;\r
-               }\r
-               cctxt->isInclude = oldIsInclude;\r
-           }\r
-           break;\r
-       case XSLT_FUNC_PARAM:\r
-           xsltStylePreCompute(cctxt->style, node);\r
-           xsltParseGlobalParam(cctxt->style, node);\r
-           break;\r
-       case XSLT_FUNC_VARIABLE:\r
-           xsltStylePreCompute(cctxt->style, node);\r
-           xsltParseGlobalVariable(cctxt->style, node);\r
-           break;\r
-       case XSLT_FUNC_ATTRSET:\r
-           xsltParseStylesheetAttributeSet(cctxt->style, node);\r
-           break;\r
-       default:\r
-           xsltTransformError(NULL, cctxt->style, node,\r
-               "Internal error: (xsltParseTopLevelXSLTElem) "\r
-               "Cannot handle this top-level declaration.\n");\r
-           cctxt->style->errors++;\r
-           ret = -1;\r
-    }\r
-\r
-exit:\r
-    xsltCompilerNodePop(cctxt, node);\r
-\r
-    return(ret);\r
-}\r
-\r
-#if 0\r
-static int\r
-xsltParseRemoveWhitespace(xmlNodePtr node)\r
-{\r
-    if ((node == NULL) || (node->children == NULL))\r
-       return(0);\r
-    else {\r
-       xmlNodePtr delNode = NULL, child = node->children;\r
-\r
-       do {\r
-           if (delNode) {\r
-               xmlUnlinkNode(delNode);\r
-               xmlFreeNode(delNode);\r
-               delNode = NULL;\r
-           }\r
-           if (((child->type == XML_TEXT_NODE) ||\r
-                (child->type == XML_CDATA_SECTION_NODE)) &&\r
-               (IS_BLANK_NODE(child)))\r
-               delNode = child;            \r
-           child = child->next;\r
-       } while (child != NULL);\r
-       if (delNode) {\r
-           xmlUnlinkNode(delNode);\r
-           xmlFreeNode(delNode);\r
-           delNode = NULL;\r
-       }\r
-    }\r
-    return(0);\r
-}\r
-#endif\r
-\r
-static int\r
-xsltParseXSLTStylesheetElemCore(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)\r
-{\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-    int templates = 0;\r
-#endif\r
-    xmlNodePtr cur, start = NULL;\r
-    xsltStylesheetPtr style;\r
-\r
-    if ((cctxt == NULL) || (node == NULL) ||\r
-       (node->type != XML_ELEMENT_NODE))\r
-       return(-1);    \r
-\r
-    style = cctxt->style;    \r
-    /*\r
-    * At this stage all import declarations of all stylesheet modules\r
-    * with the same stylesheet level have been processed.\r
-    * Now we can safely parse the rest of the declarations.\r
-    */\r
-    if (IS_XSLT_ELEM_FAST(node) && IS_XSLT_NAME(node, "include"))\r
-    {\r
-       xsltDocumentPtr include;\r
-       /*\r
-       * URGENT TODO: Make this work with simplified stylesheets!\r
-       *   I.e., when we won't find an xsl:stylesheet element.\r
-       */\r
-       /*\r
-       * This is as include declaration.\r
-       */\r
-       include = ((xsltStyleItemIncludePtr) node->psvi)->include;\r
-       if (include == NULL) {\r
-           /* TODO: raise error? */\r
-           return(-1);\r
-       }\r
-       /*\r
-       * TODO: Actually an xsl:include should locate an embedded\r
-       *  stylesheet as well; so the document-element won't always\r
-       *  be the element where the actual stylesheet is rooted at.\r
-       *  But such embedded stylesheets are not supported by Libxslt yet.\r
-       */\r
-       node = xmlDocGetRootElement(include->doc);\r
-       if (node == NULL) {\r
-           return(-1);\r
-       }\r
-    }    \r
-    \r
-    if (node->children == NULL)\r
-       return(0);\r
-    /*\r
-    * Push the xsl:stylesheet/xsl:transform element.\r
-    */  \r
-    xsltCompilerNodePush(cctxt, node);\r
-    cctxt->inode->isRoot = 1;\r
-    cctxt->inode->nsChanged = 0;\r
-    /*\r
-    * Start with the naked dummy info for literal result elements.\r
-    */\r
-    cctxt->inode->litResElemInfo = cctxt->inodeList->litResElemInfo;\r
-\r
-    /*\r
-    * In every case, we need to have\r
-    * the in-scope namespaces of the element, where the\r
-    * stylesheet is rooted at, regardless if it's an XSLT\r
-    * instruction or a literal result instruction (or if\r
-    * this is an embedded stylesheet).\r
-    */         \r
-    cctxt->inode->inScopeNs =\r
-       xsltCompilerBuildInScopeNsList(cctxt, node);\r
-\r
-    /*\r
-    * Process attributes of xsl:stylesheet/xsl:transform.\r
-    * --------------------------------------------------\r
-    * Allowed are:\r
-    *  id = id\r
-    *  extension-element-prefixes = tokens\r
-    *  exclude-result-prefixes = tokens\r
-    *  version = number (mandatory)    \r
-    */\r
-    if (xsltParseAttrXSLTVersion(cctxt, node,\r
-       XSLT_ELEMENT_CATEGORY_XSLT) == 0)\r
-    {    \r
-       /*\r
-       * Attribute "version".\r
-       * XSLT 1.0: "An xsl:stylesheet element *must* have a version\r
-       *  attribute, indicating the version of XSLT that the\r
-       *  stylesheet requires".\r
-       * The root element of a simplified stylesheet must also have\r
-       * this attribute.\r
-       */\r
-#ifdef XSLT_REFACTORED_MANDATORY_VERSION\r
-       if (isXsltElem)\r
-           xsltTransformError(NULL, cctxt->style, node,\r
-               "The attribute 'version' is missing.\n");\r
-       cctxt->style->errors++; \r
-#else\r
-       /* OLD behaviour. */\r
-       xsltTransformError(NULL, cctxt->style, node,\r
-           "xsl:version is missing: document may not be a stylesheet\n");\r
-       cctxt->style->warnings++;\r
-#endif\r
-    }    \r
-    /*\r
-    * The namespaces declared by the attributes\r
-    *  "extension-element-prefixes" and\r
-    *  "exclude-result-prefixes" are local to *this*\r
-    *  stylesheet tree; i.e., they are *not* visible to\r
-    *  other stylesheet-modules, whether imported or included.\r
-    * \r
-    * Attribute "extension-element-prefixes".\r
-    */\r
-    cctxt->inode->extElemNs =\r
-       xsltParseExtElemPrefixes(cctxt, node, NULL,\r
-           XSLT_ELEMENT_CATEGORY_XSLT);\r
-    /*\r
-    * Attribute "exclude-result-prefixes".\r
-    */\r
-    cctxt->inode->exclResultNs =\r
-       xsltParseExclResultPrefixes(cctxt, node, NULL,\r
-           XSLT_ELEMENT_CATEGORY_XSLT);\r
-    /*\r
-    * Create/reuse info for the literal result element.\r
-    */\r
-    if (cctxt->inode->nsChanged)\r
-       xsltLREInfoCreate(cctxt, node, 0);\r
-    /*\r
-    * Processed top-level elements:\r
-    * ----------------------------\r
-    *  xsl:variable, xsl:param (QName, in-scope ns,\r
-    *    expression (vars allowed))\r
-    *  xsl:attribute-set (QName, in-scope ns)\r
-    *  xsl:strip-space, xsl:preserve-space (XPath NameTests,\r
-    *    in-scope ns)\r
-    *    I *think* global scope, merge with includes\r
-    *  xsl:output (QName, in-scope ns)\r
-    *  xsl:key (QName, in-scope ns, pattern,\r
-    *    expression (vars *not* allowed))\r
-    *  xsl:decimal-format (QName, needs in-scope ns)\r
-    *  xsl:namespace-alias (in-scope ns)\r
-    *    global scope, merge with includes\r
-    *  xsl:template (last, QName, pattern)\r
-    *\r
-    * (whitespace-only text-nodes have *not* been removed\r
-    *  yet; this will be done in xsltParseSequenceConstructor)\r
-    *\r
-    * Report misplaced child-nodes first.\r
-    */\r
-    cur = node->children;\r
-    while (cur != NULL) {\r
-       if (cur->type == XML_TEXT_NODE) {\r
-           xsltTransformError(NULL, style, cur,\r
-               "Misplaced text node (content: '%s').\n",\r
-               (cur->content != NULL) ? cur->content : BAD_CAST "");\r
-           style->errors++;\r
-       } else if (cur->type != XML_ELEMENT_NODE) {\r
-           xsltTransformError(NULL, style, cur, "Misplaced node.\n");\r
-           style->errors++;\r
-       }\r
-       cur = cur->next;\r
-    }\r
-    /*\r
-    * Skip xsl:import elements; they have been processed\r
-    * already.\r
-    */\r
-    cur = node->children;\r
-    while ((cur != NULL) && xsltParseFindTopLevelElem(cctxt, cur,\r
-           BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)\r
-       cur = cur->next;\r
-    if (cur == NULL)\r
-       goto exit;\r
-\r
-    start = cur;\r
-    /*\r
-    * Process all top-level xsl:param elements.\r
-    */\r
-    while ((cur != NULL) &&\r
-       xsltParseFindTopLevelElem(cctxt, cur,\r
-       BAD_CAST "param", XSLT_NAMESPACE, 0, &cur) == 1)\r
-    {\r
-       xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_PARAM); \r
-       cur = cur->next;\r
-    }  \r
-    /*\r
-    * Process all top-level xsl:variable elements.\r
-    */\r
-    cur = start;\r
-    while ((cur != NULL) &&\r
-       xsltParseFindTopLevelElem(cctxt, cur,\r
-       BAD_CAST "variable", XSLT_NAMESPACE, 0, &cur) == 1)\r
-    {\r
-       xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_VARIABLE);\r
-       cur = cur->next;\r
-    }   \r
-    /*\r
-    * Process all the rest of top-level elements.\r
-    */\r
-    cur = start;\r
-    while (cur != NULL) {      \r
-       /*\r
-       * Process element nodes.\r
-       */\r
-       if (cur->type == XML_ELEMENT_NODE) {        \r
-           if (cur->ns == NULL) {\r
-               xsltTransformError(NULL, style, cur,\r
-                   "Unexpected top-level element in no namespace.\n");\r
-               style->errors++;\r
-               cur = cur->next;\r
-               continue;\r
-           }\r
-           /*\r
-           * Process all XSLT elements.\r
-           */\r
-           if (IS_XSLT_ELEM_FAST(cur)) {\r
-               /*\r
-               * xsl:import is only allowed at the beginning.\r
-               */\r
-               if (IS_XSLT_NAME(cur, "import")) {\r
-                   xsltTransformError(NULL, style, cur,\r
-                       "Misplaced xsl:import element.\n");\r
-                   style->errors++;\r
-                   cur = cur->next;\r
-                   continue;\r
-               }\r
-               /* \r
-               * TODO: Change the return type of the parsing functions\r
-               *  to int.\r
-               */\r
-               if (IS_XSLT_NAME(cur, "template")) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-                   templates++;\r
-#endif\r
-                   /*\r
-                   * TODO: Is the position of xsl:template in the\r
-                   *  tree significant? If not it would be easier to\r
-                   *  parse them at a later stage.\r
-                   */\r
-                   xsltParseXSLTTemplate(cctxt, cur);\r
-               } else if (IS_XSLT_NAME(cur, "variable")) {\r
-                   /* NOP; done already */\r
-               } else if (IS_XSLT_NAME(cur, "param")) {\r
-                   /* NOP; done already */\r
-               } else if (IS_XSLT_NAME(cur, "include")) {                  \r
-                   if (cur->psvi != NULL)                  \r
-                       xsltParseXSLTStylesheetElemCore(cctxt, cur);\r
-                   else {\r
-                       xsltTransformError(NULL, style, cur,\r
-                           "Internal error: "\r
-                           "(xsltParseXSLTStylesheetElemCore) "\r
-                           "The xsl:include element was not compiled.\n");\r
-                       style->errors++;\r
-                   }\r
-               } else if (IS_XSLT_NAME(cur, "strip-space")) {\r
-                   /* No node info needed. */\r
-                   xsltParseStylesheetStripSpace(style, cur);\r
-               } else if (IS_XSLT_NAME(cur, "preserve-space")) {\r
-                   /* No node info needed. */\r
-                   xsltParseStylesheetPreserveSpace(style, cur);\r
-               } else if (IS_XSLT_NAME(cur, "output")) {\r
-                   /* No node-info needed. */\r
-                   xsltParseStylesheetOutput(style, cur);\r
-               } else if (IS_XSLT_NAME(cur, "key")) {\r
-                   /* TODO: node-info needed for expressions ? */\r
-                   xsltParseStylesheetKey(style, cur);\r
-               } else if (IS_XSLT_NAME(cur, "decimal-format")) {\r
-                   /* No node-info needed. */               \r
-                   xsltParseStylesheetDecimalFormat(style, cur);\r
-               } else if (IS_XSLT_NAME(cur, "attribute-set")) {                    \r
-                   xsltParseTopLevelXSLTElem(cctxt, cur,\r
-                       XSLT_FUNC_ATTRSET);             \r
-               } else if (IS_XSLT_NAME(cur, "namespace-alias")) {\r
-                   /* NOP; done already */                 \r
-               } else {\r
-                   if (cctxt->inode->forwardsCompat) {\r
-                       /*\r
-                       * Forwards-compatible mode:\r
-                       *\r
-                       * XSLT-1: "if it is a top-level element and\r
-                       *  XSLT 1.0 does not allow such elements as top-level\r
-                       *  elements, then the element must be ignored along\r
-                       *  with its content;"\r
-                       */\r
-                       /*\r
-                       * TODO: I don't think we should generate a warning.\r
-                       */\r
-                       xsltTransformError(NULL, style, cur,\r
-                           "Forwards-compatible mode: Ignoring unknown XSLT "\r
-                           "element '%s'.\n", cur->name);\r
-                       style->warnings++;\r
-                   } else {\r
-                       xsltTransformError(NULL, style, cur,\r
-                           "Unknown XSLT element '%s'.\n", cur->name);\r
-                       style->errors++;\r
-                   }\r
-               }\r
-           } else {\r
-               xsltTopLevelFunction function;\r
-\r
-               /*\r
-               * Process non-XSLT elements, which are in a\r
-               *  non-NULL namespace.\r
-               */\r
-               /*\r
-               * QUESTION: What does xsltExtModuleTopLevelLookup()\r
-               *  do exactly?\r
-               */\r
-               function = xsltExtModuleTopLevelLookup(cur->name,\r
-                   cur->ns->href);\r
-               if (function != NULL)\r
-                   function(style, cur);\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-               xsltGenericDebug(xsltGenericDebugContext,\r
-                   "xsltParseXSLTStylesheetElemCore : User-defined "\r
-                   "data element '%s'.\n", cur->name);\r
-#endif\r
-           }\r
-       }\r
-       cur = cur->next;\r
-    }\r
-\r
-exit:\r
-\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "### END of parsing top-level elements of doc '%s'.\n",\r
-       node->doc->URL);\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "### Templates: %d\n", templates);\r
-#ifdef XSLT_REFACTORED\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "### Max inodes: %d\n", cctxt->maxNodeInfos);\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "### Max LREs  : %d\n", cctxt->maxLREs);\r
-#endif /* XSLT_REFACTORED */\r
-#endif /* WITH_XSLT_DEBUG_PARSING */\r
-\r
-    xsltCompilerNodePop(cctxt, node);\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltParseXSLTStylesheet:\r
- * @cctxt: the compiler context\r
- * @node: the xsl:stylesheet/xsl:transform element-node\r
- *\r
- * Parses the xsl:stylesheet and xsl:transform element. \r
- *\r
- * <xsl:stylesheet\r
- *  id = id\r
- *  extension-element-prefixes = tokens\r
- *  exclude-result-prefixes = tokens\r
- *  version = number>\r
- *  <!-- Content: (xsl:import*, top-level-elements) -->\r
- * </xsl:stylesheet>\r
- *\r
- * BIG TODO: The xsl:include stuff.\r
- * \r
- * Called by xsltParseStylesheetTree()\r
- *\r
- * Returns 0 on success, a positive result on errors and\r
- *         -1 on API or internal errors.\r
- */\r
-static int\r
-xsltParseXSLTStylesheetElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)\r
-{\r
-    xmlNodePtr cur, start;\r
-\r
-    if ((cctxt == NULL) || (node == NULL))\r
-       return(-1);\r
-    \r
-    if (node->children == NULL)\r
-       goto exit;\r
-\r
-    /*\r
-    * Process top-level elements:\r
-    *  xsl:import (must be first)\r
-    *  xsl:include (this is just a pre-processing)\r
-    */\r
-    cur = node->children;\r
-    /*\r
-    * Process xsl:import elements.\r
-    * XSLT 1.0: "The xsl:import element children must precede all\r
-    *  other element children of an xsl:stylesheet element,\r
-    *  including any xsl:include element children."\r
-    */    \r
-    while ((cur != NULL) &&\r
-       xsltParseFindTopLevelElem(cctxt, cur,\r
-           BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)\r
-    {\r
-       if (xsltParseStylesheetImport(cctxt->style, cur) != 0) {\r
-           cctxt->style->errors++;\r
-       }\r
-       cur = cur->next;\r
-    }\r
-    if (cur == NULL)\r
-       goto exit;\r
-    start = cur;\r
-    /*\r
-    * Pre-process all xsl:include elements.\r
-    */\r
-    cur = start;\r
-    while ((cur != NULL) &&\r
-       xsltParseFindTopLevelElem(cctxt, cur,\r
-           BAD_CAST "include", XSLT_NAMESPACE, 0, &cur) == 1)\r
-    {\r
-       xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_INCLUDE);\r
-       cur = cur->next;\r
-    }\r
-    /*\r
-    * Pre-process all xsl:namespace-alias elements.\r
-    * URGENT TODO: This won't work correctly: the order of included\r
-    *  aliases and aliases defined here is significant.\r
-    */\r
-    cur = start;\r
-    while ((cur != NULL) &&\r
-       xsltParseFindTopLevelElem(cctxt, cur,\r
-           BAD_CAST "namespace-alias", XSLT_NAMESPACE, 0, &cur) == 1)\r
-    {\r
-       xsltNamespaceAlias(cctxt->style, cur);\r
-       cur = cur->next;\r
-    }\r
-\r
-    if (cctxt->isInclude) {\r
-       /*\r
-       * If this stylesheet is intended for inclusion, then\r
-       * we will process only imports and includes. \r
-       */\r
-       goto exit;\r
-    } \r
-    /*\r
-    * Now parse the rest of the top-level elements.\r
-    */\r
-    xsltParseXSLTStylesheetElemCore(cctxt, node);      \r
-exit:\r
-\r
-    return(0);\r
-}\r
-\r
-#else /* XSLT_REFACTORED */\r
-\r
-/**\r
- * xsltParseStylesheetTop:\r
- * @style:  the XSLT stylesheet\r
- * @top:  the top level "stylesheet" or "transform" element\r
- *\r
- * scan the top level elements of an XSL stylesheet\r
- */\r
-static void\r
-xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {\r
-    xmlNodePtr cur;\r
-    xmlChar *prop;\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-    int templates = 0;\r
-#endif\r
-\r
-    if (top == NULL)\r
-       return;\r
-\r
-    prop = xmlGetNsProp(top, (const xmlChar *)"version", NULL);\r
-    if (prop == NULL) {\r
-       xsltTransformError(NULL, style, top,\r
-           "xsl:version is missing: document may not be a stylesheet\n");\r
-       if (style != NULL) style->warnings++;\r
-    } else {\r
-       if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&\r
-            (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {\r
-           xsltTransformError(NULL, style, top,\r
-               "xsl:version: only 1.0 features are supported\n");\r
-            /* TODO set up compatibility when not XSLT 1.0 */\r
-           if (style != NULL) style->warnings++;\r
-       }\r
-       xmlFree(prop);\r
-    }\r
-\r
-    cur = top->children;\r
-\r
-    /*\r
-     * process xsl:import elements\r
-     */\r
-    while (cur != NULL) {\r
-           if (IS_BLANK_NODE(cur)) {\r
-                   cur = cur->next;\r
-                   continue;\r
-           }\r
-           if (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "import")) {\r
-                   if (xsltParseStylesheetImport(style, cur) != 0)\r
-                           if (style != NULL) style->errors++;\r
-           } else\r
-                   break;\r
-           cur = cur->next;\r
-    }\r
-\r
-    /*\r
-     * process other top-level elements\r
-     */\r
-    while (cur != NULL) {\r
-       if (IS_BLANK_NODE(cur)) {\r
-           cur = cur->next;\r
-           continue;\r
-       }\r
-       if (cur->type == XML_TEXT_NODE) {\r
-           if (cur->content != NULL) {\r
-               xsltTransformError(NULL, style, cur,\r
-                   "misplaced text node: '%s'\n", cur->content);\r
-           }\r
-           if (style != NULL) style->errors++;\r
-            cur = cur->next;\r
-           continue;\r
-       }\r
-       if ((cur->type == XML_ELEMENT_NODE) && (cur->ns == NULL)) {\r
-           xsltGenericError(xsltGenericErrorContext,\r
-                    "Found a top-level element %s with null namespace URI\n",\r
-                    cur->name);\r
-           if (style != NULL) style->errors++;\r
-           cur = cur->next;\r
-           continue;\r
-       }\r
-       if ((cur->type == XML_ELEMENT_NODE) && (!(IS_XSLT_ELEM(cur)))) {\r
-           xsltTopLevelFunction function;\r
-\r
-           function = xsltExtModuleTopLevelLookup(cur->name,\r
-                                                  cur->ns->href);\r
-           if (function != NULL)\r
-               function(style, cur);\r
-\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-                   "xsltParseStylesheetTop : found foreign element %s\n",\r
-                   cur->name);\r
-#endif\r
-            cur = cur->next;\r
-           continue;\r
-       }\r
-       if (IS_XSLT_NAME(cur, "import")) {\r
-           xsltTransformError(NULL, style, cur,\r
-                       "xsltParseStylesheetTop: ignoring misplaced import element\n");\r
-           if (style != NULL) style->errors++;\r
-    } else if (IS_XSLT_NAME(cur, "include")) {\r
-           if (xsltParseStylesheetInclude(style, cur) != 0)\r
-               if (style != NULL) style->errors++;\r
-    } else if (IS_XSLT_NAME(cur, "strip-space")) {\r
-           xsltParseStylesheetStripSpace(style, cur);\r
-    } else if (IS_XSLT_NAME(cur, "preserve-space")) {\r
-           xsltParseStylesheetPreserveSpace(style, cur);\r
-    } else if (IS_XSLT_NAME(cur, "output")) {\r
-           xsltParseStylesheetOutput(style, cur);\r
-    } else if (IS_XSLT_NAME(cur, "key")) {\r
-           xsltParseStylesheetKey(style, cur);\r
-    } else if (IS_XSLT_NAME(cur, "decimal-format")) {\r
-           xsltParseStylesheetDecimalFormat(style, cur);\r
-    } else if (IS_XSLT_NAME(cur, "attribute-set")) {\r
-           xsltParseStylesheetAttributeSet(style, cur);\r
-    } else if (IS_XSLT_NAME(cur, "variable")) {\r
-           xsltParseGlobalVariable(style, cur);\r
-    } else if (IS_XSLT_NAME(cur, "param")) {\r
-           xsltParseGlobalParam(style, cur);\r
-    } else if (IS_XSLT_NAME(cur, "template")) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-           templates++;\r
-#endif\r
-           xsltParseStylesheetTemplate(style, cur);\r
-    } else if (IS_XSLT_NAME(cur, "namespace-alias")) {\r
-           xsltNamespaceAlias(style, cur);\r
-       } else {\r
-           /*\r
-           * BUG TODO: The version of the *doc* is irrelevant for\r
-           *  the forwards-compatible mode.\r
-           */\r
-            if ((style != NULL) && (style->doc->version != NULL) &&\r
-               (!strncmp((const char *) style->doc->version, "1.0", 3))) {\r
-               xsltTransformError(NULL, style, cur,\r
-                       "xsltParseStylesheetTop: unknown %s element\n",\r
-                       cur->name);\r
-               if (style != NULL) style->errors++;\r
-           }\r
-           else {\r
-                /* do Forwards-Compatible Processing */\r
-               xsltTransformError(NULL, style, cur,\r
-                       "xsltParseStylesheetTop: ignoring unknown %s element\n",\r
-                       cur->name);\r
-               if (style != NULL) style->warnings++;\r
-            }\r
-       }\r
-       cur = cur->next;\r
-    }\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-                   "parsed %d templates\n", templates);\r
-#endif\r
-}\r
-\r
-#endif /* else of XSLT_REFACTORED */\r
-\r
-#ifdef XSLT_REFACTORED\r
-/**\r
- * xsltParseSimplifiedStylesheetTree:\r
- *\r
- * @style: the stylesheet (TODO: Change this to the compiler context)\r
- * @doc: the document containing the stylesheet.\r
- * @node: the node where the stylesheet is rooted at\r
- *\r
- * Returns 0 in case of success, a positive result if an error occurred\r
- *         and -1 on API and internal errors.\r
- */\r
-static int\r
-xsltParseSimplifiedStylesheetTree(xsltCompilerCtxtPtr cctxt,\r
-                                 xmlDocPtr doc,\r
-                                 xmlNodePtr node)\r
-{\r
-    xsltTemplatePtr templ;\r
-    \r
-    if ((cctxt == NULL) || (node == NULL))\r
-       return(-1);\r
-\r
-    if (xsltParseAttrXSLTVersion(cctxt, node, 0) == XSLT_ELEMENT_CATEGORY_LRE)\r
-    {\r
-       /*\r
-       * TODO: Adjust report, since this might be an\r
-       * embedded stylesheet.\r
-       */\r
-       xsltTransformError(NULL, cctxt->style, node,\r
-           "The attribute 'xsl:version' is missing; cannot identify "\r
-           "this document as an XSLT stylesheet document.\n");\r
-       cctxt->style->errors++;\r
-       return(1);\r
-    }\r
-    \r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-       "xsltParseSimplifiedStylesheetTree: document is stylesheet\n");\r
-#endif        \r
-    \r
-    /*\r
-    * Create and link the template\r
-    */\r
-    templ = xsltNewTemplate();\r
-    if (templ == NULL) {\r
-       return(-1);\r
-    }\r
-    templ->next = cctxt->style->templates;\r
-    cctxt->style->templates = templ;\r
-    templ->match = xmlStrdup(BAD_CAST "/");\r
-\r
-    /*\r
-    * Note that we push the document-node in this special case.\r
-    */\r
-    xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);\r
-    /*\r
-    * In every case, we need to have\r
-    * the in-scope namespaces of the element, where the\r
-    * stylesheet is rooted at, regardless if it's an XSLT\r
-    * instruction or a literal result instruction (or if\r
-    * this is an embedded stylesheet).\r
-    */\r
-    cctxt->inode->inScopeNs =\r
-       xsltCompilerBuildInScopeNsList(cctxt, node);\r
-    /*\r
-    * Parse the content and register the match-pattern.\r
-    */\r
-    xsltParseSequenceConstructor(cctxt, node);\r
-    xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);\r
-\r
-    templ->elem = (xmlNodePtr) doc;\r
-    templ->content = node;\r
-    xsltAddTemplate(cctxt->style, templ, NULL, NULL);\r
-    cctxt->style->literal_result = 1;\r
-    return(0);\r
-}\r
-\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-int\r
-xsltRestoreDocumentNamespaces(xsltNsMapPtr ns, xmlDocPtr doc)\r
-{\r
-    if (doc == NULL)\r
-       return(-1);\r
-    /*\r
-    * Revert the changes we have applied to the namespace-URIs of\r
-    * ns-decls.\r
-    */    \r
-    while (ns != NULL) {\r
-       if ((ns->doc == doc) && (ns->ns != NULL)) {\r
-           ns->ns->href = ns->origNsName;\r
-           ns->origNsName = NULL;\r
-           ns->ns = NULL;          \r
-       }\r
-       ns = ns->next;\r
-    }\r
-    return(0);\r
-}\r
-#endif /* XSLT_REFACTORED_XSLT_NSCOMP */\r
-\r
-/**\r
- * xsltParseStylesheetProcess:\r
- * @style:  the XSLT stylesheet (the current stylesheet-level)\r
- * @doc:  and xmlDoc parsed XML\r
- *\r
- * Parses an XSLT stylesheet, adding the associated structures.\r
- * Called by:\r
- *  xsltParseStylesheetImportedDoc() (xslt.c)\r
- *  xsltParseStylesheetInclude() (imports.c)\r
- *\r
- * Returns the value of the @style parameter if everything\r
- * went right, NULL if something went amiss.\r
- */\r
-xsltStylesheetPtr\r
-xsltParseStylesheetProcess(xsltStylesheetPtr style, xmlDocPtr doc)\r
-{\r
-    xsltCompilerCtxtPtr cctxt;\r
-    xmlNodePtr cur;\r
-    int oldIsSimplifiedStylesheet;\r
-\r
-\r
-    if ((style == NULL) || (doc == NULL))\r
-       return(NULL);\r
-\r
-    cctxt = XSLT_CCTXT(style);\r
-\r
-    cur = xmlDocGetRootElement(doc);\r
-    if (cur == NULL) {\r
-       xsltTransformError(NULL, style, (xmlNodePtr) doc,\r
-               "xsltParseStylesheetProcess : empty stylesheet\n");\r
-       return(NULL);\r
-    }\r
-    oldIsSimplifiedStylesheet = cctxt->simplified;\r
-\r
-    if ((IS_XSLT_ELEM(cur)) && \r
-       ((IS_XSLT_NAME(cur, "stylesheet")) ||\r
-        (IS_XSLT_NAME(cur, "transform")))) {   \r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsltParseStylesheetProcess : found stylesheet\n");\r
-#endif\r
-       cctxt->simplified = 0;\r
-       style->literal_result = 0;\r
-    } else {\r
-       cctxt->simplified = 1;\r
-       style->literal_result = 1;\r
-    }\r
-    /*\r
-    * Pre-process the stylesheet if not already done before.\r
-    *  This will remove PIs and comments, merge adjacent\r
-    *  text nodes, internalize strings, etc.\r
-    */\r
-    if (! style->nopreproc)\r
-       xsltParsePreprocessStylesheetTree(cctxt, cur);\r
-    /*\r
-    * Parse and compile the stylesheet.\r
-    */\r
-    if (style->literal_result == 0) {\r
-       if (xsltParseXSLTStylesheetElem(cctxt, cur) != 0)\r
-           return(NULL);\r
-    } else {\r
-       if (xsltParseSimplifiedStylesheetTree(cctxt, doc, cur) != 0)\r
-           return(NULL);\r
-    }    \r
-\r
-    cctxt->simplified = oldIsSimplifiedStylesheet;\r
-\r
-    return(style);\r
-}\r
-\r
-#else /* XSLT_REFACTORED */\r
-\r
-xsltStylesheetPtr\r
-xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {\r
-    xmlNodePtr cur;\r
-\r
-    if (doc == NULL)\r
-       return(NULL);\r
-    if (ret == NULL)\r
-       return(ret);\r
-    \r
-    /*\r
-     * First steps, remove blank nodes,\r
-     * locate the xsl:stylesheet element and the\r
-     * namespace declaration.\r
-     */\r
-    cur = xmlDocGetRootElement(doc);\r
-    if (cur == NULL) {\r
-       xsltTransformError(NULL, ret, (xmlNodePtr) doc,\r
-               "xsltParseStylesheetProcess : empty stylesheet\n");\r
-       return(NULL);\r
-    }\r
-\r
-    if ((IS_XSLT_ELEM(cur)) && \r
-       ((IS_XSLT_NAME(cur, "stylesheet")) ||\r
-        (IS_XSLT_NAME(cur, "transform")))) {   \r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsltParseStylesheetProcess : found stylesheet\n");\r
-#endif\r
-       ret->literal_result = 0;\r
-       xsltParseStylesheetExcludePrefix(ret, cur, 1);\r
-       xsltParseStylesheetExtPrefix(ret, cur, 1);\r
-    } else {\r
-       xsltParseStylesheetExcludePrefix(ret, cur, 0);\r
-       xsltParseStylesheetExtPrefix(ret, cur, 0);\r
-       ret->literal_result = 1;\r
-    }\r
-    if (!ret->nopreproc) {\r
-       xsltPrecomputeStylesheet(ret, cur);\r
-    }\r
-    if (ret->literal_result == 0) {\r
-       xsltParseStylesheetTop(ret, cur);\r
-    } else {\r
-       xmlChar *prop;\r
-       xsltTemplatePtr template;\r
-\r
-       /*\r
-        * the document itself might be the template, check xsl:version\r
-        */\r
-       prop = xmlGetNsProp(cur, (const xmlChar *)"version", XSLT_NAMESPACE);\r
-       if (prop == NULL) {\r
-           xsltTransformError(NULL, ret, cur,\r
-               "xsltParseStylesheetProcess : document is not a stylesheet\n");\r
-           return(NULL);\r
-       }\r
-\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-        xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsltParseStylesheetProcess : document is stylesheet\n");\r
-#endif\r
-       \r
-       if (!xmlStrEqual(prop, (const xmlChar *)"1.0")) {\r
-           xsltTransformError(NULL, ret, cur,\r
-               "xsl:version: only 1.0 features are supported\n");\r
-            /* TODO set up compatibility when not XSLT 1.0 */\r
-           ret->warnings++;\r
-       }\r
-       xmlFree(prop);\r
-\r
-       /*\r
-        * Create and link the template\r
-        */\r
-       template = xsltNewTemplate();\r
-       if (template == NULL) {\r
-           return(NULL);\r
-       }\r
-       template->next = ret->templates;\r
-       ret->templates = template;\r
-       template->match = xmlStrdup((const xmlChar *)"/");\r
-\r
-       /*\r
-        * parse the content and register the pattern\r
-        */\r
-       xsltParseTemplateContent(ret, (xmlNodePtr) doc);\r
-       template->elem = (xmlNodePtr) doc;\r
-       template->content = doc->children;\r
-       xsltAddTemplate(ret, template, NULL, NULL);\r
-       ret->literal_result = 1;        \r
-    }\r
-\r
-    return(ret);\r
-}\r
-\r
-#endif /* else of XSLT_REFACTORED */\r
-\r
-/**\r
- * xsltParseStylesheetImportedDoc:\r
- * @doc:  an xmlDoc parsed XML\r
- * @style: pointer to the parent stylesheet (if it exists)\r
- *\r
- * parse an XSLT stylesheet building the associated structures\r
- * except the processing not needed for imported documents.\r
- *\r
- * Returns a new XSLT stylesheet structure.\r
- */\r
-\r
-xsltStylesheetPtr\r
-xsltParseStylesheetImportedDoc(xmlDocPtr doc,\r
-                              xsltStylesheetPtr parentStyle) {\r
-    xsltStylesheetPtr retStyle;\r
-\r
-    if (doc == NULL)\r
-       return(NULL);\r
-\r
-    retStyle = xsltNewStylesheet();\r
-    if (retStyle == NULL)\r
-       return(NULL);\r
-    /*\r
-    * Set the importing stylesheet module; also used to detect recursion.\r
-    */\r
-    retStyle->parent = parentStyle;\r
-    /*\r
-    * Adjust the string dict.\r
-    */\r
-    if (doc->dict != NULL) {\r
-        xmlDictFree(retStyle->dict);\r
-       retStyle->dict = doc->dict;\r
-#ifdef WITH_XSLT_DEBUG\r
-        xsltGenericDebug(xsltGenericDebugContext,\r
-           "reusing dictionary from %s for stylesheet\n",\r
-           doc->URL);\r
-#endif\r
-       xmlDictReference(retStyle->dict);\r
-    }          \r
-    \r
-    /*\r
-    * TODO: Eliminate xsltGatherNamespaces(); we must not restrict\r
-    *  the stylesheet to containt distinct namespace prefixes.\r
-    */\r
-    xsltGatherNamespaces(retStyle);\r
-\r
-#ifdef XSLT_REFACTORED\r
-    {\r
-       xsltCompilerCtxtPtr cctxt;\r
-       xsltStylesheetPtr oldCurSheet;\r
-           \r
-       if (parentStyle == NULL) {\r
-           xsltPrincipalStylesheetDataPtr principalData;\r
-           /*\r
-           * Principal stylesheet\r
-           * --------------------\r
-           */\r
-           retStyle->principal = retStyle;\r
-           /*\r
-           * Create extra data for the principal stylesheet.\r
-           */\r
-           principalData = xsltNewPrincipalStylesheetData();\r
-           if (principalData == NULL) {\r
-               xsltFreeStylesheet(retStyle);\r
-               return(NULL);\r
-           }\r
-           retStyle->principalData = principalData;\r
-           /*\r
-           * Create the compilation context\r
-           * ------------------------------\r
-           * (only once; for the principal stylesheet).\r
-           * This is currently the only function where the\r
-           * compilation context is created.\r
-           */\r
-           cctxt = xsltCompilationCtxtCreate(retStyle);\r
-           if (cctxt == NULL) {\r
-               xsltFreeStylesheet(retStyle);\r
-               return(NULL);\r
-           }               \r
-           retStyle->compCtxt = (void *) cctxt;\r
-           cctxt->style = retStyle;\r
-           cctxt->dict = retStyle->dict;\r
-           cctxt->psData = principalData;\r
-           /*\r
-           * Push initial dummy node info.\r
-           */\r
-           cctxt->depth = -1;\r
-           xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);\r
-       } else {\r
-           /*\r
-           * Imported stylesheet.\r
-           */\r
-           retStyle->principal = parentStyle->principal;\r
-           cctxt = parentStyle->compCtxt;\r
-           retStyle->compCtxt = cctxt;\r
-       }\r
-       /*\r
-       * Save the old and set the current stylesheet structure in the\r
-       * compilation context.\r
-       */\r
-       oldCurSheet = cctxt->style;\r
-       cctxt->style = retStyle;\r
-       \r
-       retStyle->doc = doc;\r
-       xsltParseStylesheetProcess(retStyle, doc);\r
-       \r
-       cctxt->style = oldCurSheet;\r
-       if (parentStyle == NULL) {\r
-           /*\r
-           * Pop the initial dummy node info.\r
-           */\r
-           xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);\r
-       } else {\r
-           /*\r
-           * Clear the compilation context of imported\r
-           * stylesheets.\r
-           * TODO: really?\r
-           */\r
-           /* retStyle->compCtxt = NULL; */\r
-       }\r
-       /*\r
-       * Free the stylesheet if there were errors.\r
-       */\r
-       if (retStyle != NULL) {\r
-           if (retStyle->errors != 0) {\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-               /*\r
-               * Restore all changes made to namespace URIs of ns-decls.\r
-               */\r
-               if (cctxt->psData->nsMap)               \r
-                   xsltRestoreDocumentNamespaces(cctxt->psData->nsMap, doc);\r
-#endif\r
-               /*\r
-               * Detach the doc from the stylesheet; otherwise the doc\r
-               * will be freed in xsltFreeStylesheet().\r
-               */\r
-               retStyle->doc = NULL;\r
-               /*\r
-               * Cleanup the doc if its the main stylesheet.\r
-               */\r
-               if (parentStyle == NULL) {\r
-                   xsltCleanupStylesheetTree(doc, xmlDocGetRootElement(doc));\r
-                   if (retStyle->compCtxt != NULL) {                   \r
-                       xsltCompilationCtxtFree(retStyle->compCtxt);\r
-                       retStyle->compCtxt = NULL;\r
-                   }\r
-               }\r
-\r
-               xsltFreeStylesheet(retStyle);\r
-               retStyle = NULL;\r
-           }\r
-       }\r
-    }\r
-        \r
-#else /* XSLT_REFACTORED */\r
-    /*\r
-    * Old behaviour.\r
-    */\r
-    retStyle->doc = doc;\r
-    xsltParseStylesheetProcess(retStyle, doc);\r
-    if (retStyle != NULL) {\r
-       if (retStyle->errors != 0) {\r
-           retStyle->doc = NULL;\r
-           if (parentStyle == NULL)\r
-               xsltCleanupStylesheetTree(doc,\r
-                   xmlDocGetRootElement(doc));\r
-           xsltFreeStylesheet(retStyle);\r
-           retStyle = NULL;\r
-       }\r
-    }\r
-#endif /* else of XSLT_REFACTORED */\r
-        \r
-    return(retStyle);\r
-}\r
-\r
-/**\r
- * xsltParseStylesheetDoc:\r
- * @doc:  and xmlDoc parsed XML\r
- *\r
- * parse an XSLT stylesheet building the associated structures\r
- *\r
- * Returns a new XSLT stylesheet structure.\r
- */\r
-\r
-xsltStylesheetPtr\r
-xsltParseStylesheetDoc(xmlDocPtr doc) {\r
-    xsltStylesheetPtr ret;\r
-\r
-    ret = xsltParseStylesheetImportedDoc(doc, NULL);\r
-    if (ret == NULL)\r
-       return(NULL);\r
-\r
-    xsltResolveStylesheetAttributeSet(ret);\r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * Free the compilation context.\r
-    * TODO: Check if it's better to move this cleanup to\r
-    *   xsltParseStylesheetImportedDoc().\r
-    */\r
-    if (ret->compCtxt != NULL) {\r
-       xsltCompilationCtxtFree(XSLT_CCTXT(ret));\r
-       ret->compCtxt = NULL;\r
-    }\r
-#endif\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltParseStylesheetFile:\r
- * @filename:  the filename/URL to the stylesheet\r
- *\r
- * Load and parse an XSLT stylesheet\r
- *\r
- * Returns a new XSLT stylesheet structure.\r
- */\r
-\r
-xsltStylesheetPtr\r
-xsltParseStylesheetFile(const xmlChar* filename) {\r
-    xsltSecurityPrefsPtr sec;\r
-    xsltStylesheetPtr ret;\r
-    xmlDocPtr doc;\r
-    \r
-\r
-    if (filename == NULL)\r
-       return(NULL);\r
-\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-    xsltGenericDebug(xsltGenericDebugContext,\r
-           "xsltParseStylesheetFile : parse %s\n", filename);\r
-#endif\r
-\r
-    /*\r
-     * Security framework check\r
-     */\r
-    sec = xsltGetDefaultSecurityPrefs();\r
-    if (sec != NULL) {\r
-       int res;\r
-\r
-       res = xsltCheckRead(sec, NULL, filename);\r
-       if (res == 0) {\r
-           xsltTransformError(NULL, NULL, NULL,\r
-                "xsltParseStylesheetFile: read rights for %s denied\n",\r
-                            filename);\r
-           return(NULL);\r
-       }\r
-    }\r
-\r
-    doc = xsltDocDefaultLoader(filename, NULL, XSLT_PARSE_OPTIONS,\r
-                               NULL, XSLT_LOAD_START);\r
-    if (doc == NULL) {\r
-       xsltTransformError(NULL, NULL, NULL,\r
-               "xsltParseStylesheetFile : cannot parse %s\n", filename);\r
-       return(NULL);\r
-    }\r
-    ret = xsltParseStylesheetDoc(doc);\r
-    if (ret == NULL) {\r
-       xmlFreeDoc(doc);\r
-       return(NULL);\r
-    }\r
-\r
-    return(ret);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Handling of Stylesheet PI                       *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-#define CUR (*cur)\r
-#define SKIP(val) cur += (val)\r
-#define NXT(val) cur[(val)]\r
-#define SKIP_BLANKS                                            \\r
-    while (IS_BLANK(CUR)) NEXT\r
-#define NEXT ((*cur) ?  cur++ : cur)\r
-\r
-/**\r
- * xsltParseStylesheetPI:\r
- * @value: the value of the PI\r
- *\r
- * This function checks that the type is text/xml and extracts\r
- * the URI-Reference for the stylesheet\r
- *\r
- * Returns the URI-Reference for the stylesheet or NULL (it need to\r
- *         be freed by the caller)\r
- */\r
-static xmlChar *\r
-xsltParseStylesheetPI(const xmlChar *value) {\r
-    const xmlChar *cur;\r
-    const xmlChar *start;\r
-    xmlChar *val;\r
-    xmlChar tmp;\r
-    xmlChar *href = NULL;\r
-    int isXml = 0;\r
-\r
-    if (value == NULL)\r
-       return(NULL);\r
-\r
-    cur = value;\r
-    while (CUR != 0) {\r
-       SKIP_BLANKS;\r
-       if ((CUR == 't') && (NXT(1) == 'y') && (NXT(2) == 'p') &&\r
-           (NXT(3) == 'e')) {\r
-           SKIP(4);\r
-           SKIP_BLANKS;\r
-           if (CUR != '=')\r
-               continue;\r
-           NEXT;\r
-           if ((CUR != '\'') && (CUR != '"'))\r
-               continue;\r
-           tmp = CUR;\r
-           NEXT;\r
-           start = cur;\r
-           while ((CUR != 0) && (CUR != tmp))\r
-               NEXT;\r
-           if (CUR != tmp)\r
-               continue;\r
-           val = xmlStrndup(start, cur - start);\r
-           NEXT;\r
-           if (val == NULL) \r
-               return(NULL);\r
-           if ((xmlStrcasecmp(val, BAD_CAST "text/xml")) &&\r
-               (xmlStrcasecmp(val, BAD_CAST "text/xsl"))) {\r
-                xmlFree(val);\r
-               break;\r
-           }\r
-           isXml = 1;\r
-           xmlFree(val);\r
-       } else if ((CUR == 'h') && (NXT(1) == 'r') && (NXT(2) == 'e') &&\r
-           (NXT(3) == 'f')) {\r
-           SKIP(4);\r
-           SKIP_BLANKS;\r
-           if (CUR != '=')\r
-               continue;\r
-           NEXT;\r
-           if ((CUR != '\'') && (CUR != '"'))\r
-               continue;\r
-           tmp = CUR;\r
-           NEXT;\r
-           start = cur;\r
-           while ((CUR != 0) && (CUR != tmp))\r
-               NEXT;\r
-           if (CUR != tmp)\r
-               continue;\r
-           if (href == NULL)\r
-               href = xmlStrndup(start, cur - start);\r
-           NEXT;\r
-       } else {\r
-           while ((CUR != 0) && (!IS_BLANK(CUR)))\r
-               NEXT;\r
-       }\r
-            \r
-    }\r
-\r
-    if (!isXml) {\r
-       if (href != NULL)\r
-           xmlFree(href);\r
-       href = NULL;\r
-    }\r
-    return(href);\r
-}\r
-\r
-/**\r
- * xsltLoadStylesheetPI:\r
- * @doc:  a document to process\r
- *\r
- * This function tries to locate the stylesheet PI in the given document\r
- * If found, and if contained within the document, it will extract \r
- * that subtree to build the stylesheet to process @doc (doc itself will\r
- * be modified). If found but referencing an external document it will\r
- * attempt to load it and generate a stylesheet from it. In both cases,\r
- * the resulting stylesheet and the document need to be freed once the\r
- * transformation is done.\r
- *\r
- * Returns a new XSLT stylesheet structure or NULL if not found.\r
- */\r
-xsltStylesheetPtr\r
-xsltLoadStylesheetPI(xmlDocPtr doc) {\r
-    xmlNodePtr child;\r
-    xsltStylesheetPtr ret = NULL;\r
-    xmlChar *href = NULL;\r
-    xmlURIPtr URI;\r
-\r
-    if (doc == NULL)\r
-       return(NULL);\r
-\r
-    /*\r
-     * Find the text/xml stylesheet PI id any before the root\r
-     */\r
-    child = doc->children;\r
-    while ((child != NULL) && (child->type != XML_ELEMENT_NODE)) {\r
-       if ((child->type == XML_PI_NODE) &&\r
-           (xmlStrEqual(child->name, BAD_CAST "xml-stylesheet"))) {\r
-           href = xsltParseStylesheetPI(child->content);\r
-           if (href != NULL)\r
-               break;\r
-       }\r
-       child = child->next;\r
-    }\r
-\r
-    /*\r
-     * If found check the href to select processing\r
-     */\r
-    if (href != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-       xsltGenericDebug(xsltGenericDebugContext,\r
-               "xsltLoadStylesheetPI : found PI href=%s\n", href);\r
-#endif\r
-       URI = xmlParseURI((const char *) href);\r
-       if (URI == NULL) {\r
-           xsltTransformError(NULL, NULL, child,\r
-                   "xml-stylesheet : href %s is not valid\n", href);\r
-           xmlFree(href);\r
-           return(NULL);\r
-       }\r
-       if ((URI->fragment != NULL) && (URI->scheme == NULL) &&\r
-            (URI->opaque == NULL) && (URI->authority == NULL) &&\r
-            (URI->server == NULL) && (URI->user == NULL) &&\r
-            (URI->path == NULL) && (URI->query == NULL)) {\r
-           xmlAttrPtr ID;\r
-\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-           xsltGenericDebug(xsltGenericDebugContext,\r
-                   "xsltLoadStylesheetPI : Reference to ID %s\n", href);\r
-#endif\r
-           if (URI->fragment[0] == '#')\r
-               ID = xmlGetID(doc, (const xmlChar *) &(URI->fragment[1]));\r
-           else\r
-               ID = xmlGetID(doc, (const xmlChar *) URI->fragment);\r
-           if (ID == NULL) {\r
-               xsltTransformError(NULL, NULL, child,\r
-                   "xml-stylesheet : no ID %s found\n", URI->fragment);\r
-           } else {\r
-               xmlDocPtr fake;\r
-               xmlNodePtr subtree;\r
-\r
-               /*\r
-                * move the subtree in a new document passed to\r
-                * the stylesheet analyzer\r
-                */\r
-               subtree = ID->parent;\r
-               fake = xmlNewDoc(NULL);\r
-               if (fake != NULL) {\r
-                    /*\r
-                    * the dictionnary should be shared since nodes are\r
-                    * moved over.\r
-                    */\r
-                   fake->dict = doc->dict;\r
-                   xmlDictReference(doc->dict);\r
-#ifdef WITH_XSLT_DEBUG\r
-                   xsltGenericDebug(xsltGenericDebugContext,\r
-                         "reusing dictionary from %s for stylesheet\n",\r
-                        doc->URL);\r
-#endif\r
-\r
-                   xmlUnlinkNode(subtree);\r
-                   xmlAddChild((xmlNodePtr) fake, subtree);\r
-                   ret = xsltParseStylesheetDoc(fake);\r
-                   if (ret == NULL)\r
-                       xmlFreeDoc(fake);\r
-               }\r
-           }\r
-       } else {\r
-           xmlChar *URL, *base;\r
-\r
-           /*\r
-            * Reference to an external stylesheet\r
-            */\r
-\r
-           base = xmlNodeGetBase(doc, (xmlNodePtr) doc);\r
-           URL = xmlBuildURI(href, base);\r
-           if (URL != NULL) {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-               xsltGenericDebug(xsltGenericDebugContext,\r
-                       "xsltLoadStylesheetPI : fetching %s\n", URL);\r
-#endif\r
-               ret = xsltParseStylesheetFile(URL);\r
-               xmlFree(URL);\r
-           } else {\r
-#ifdef WITH_XSLT_DEBUG_PARSING\r
-               xsltGenericDebug(xsltGenericDebugContext,\r
-                       "xsltLoadStylesheetPI : fetching %s\n", href);\r
-#endif\r
-               ret = xsltParseStylesheetFile(href);\r
-           }\r
-           if (base != NULL)\r
-               xmlFree(base);\r
-       }\r
-       xmlFreeURI(URI);\r
-       xmlFree(href);\r
-    }\r
-    return(ret);\r
-}\r
+/*
+ * xslt.c: Implemetation of an XSL Transformation 1.0 engine
+ *
+ * Reference:
+ *   XSLT specification
+ *   http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ *   Associating Style Sheets with XML documents
+ *   http://www.w3.org/1999/06/REC-xml-stylesheet-19990629
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <string.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/valid.h>
+#include <libxml/hash.h>
+#include <libxml/uri.h>
+#include <libxml/xmlerror.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/xpath.h>
+#include "xslt.h"
+#include "xsltInternals.h"
+#include "pattern.h"
+#include "variables.h"
+#include "namespaces.h"
+#include "attributes.h"
+#include "xsltutils.h"
+#include "imports.h"
+#include "keys.h"
+#include "documents.h"
+#include "extensions.h"
+#include "preproc.h"
+#include "extra.h"
+#include "security.h"
+
+#ifdef WITH_XSLT_DEBUG
+#define WITH_XSLT_DEBUG_PARSING
+/* #define WITH_XSLT_DEBUG_BLANKS */
+#endif
+
+const char *xsltEngineVersion = LIBXSLT_VERSION_STRING LIBXSLT_VERSION_EXTRA;
+const int xsltLibxsltVersion = LIBXSLT_VERSION;
+const int xsltLibxmlVersion = LIBXML_VERSION;
+
+#ifdef XSLT_REFACTORED
+
+const xmlChar *xsltConstNamespaceNameXSLT = (const xmlChar *) XSLT_NAMESPACE;
+
+/*
+* xsltLiteralResultMarker:
+* Marker for Literal result elements, in order to avoid multiple attempts
+* to recognize such elements in the stylesheet's tree.
+* This marker is set on node->psvi during the initial traversal
+* of a stylesheet's node tree.
+*
+const xmlChar *xsltLiteralResultMarker =
+    (const xmlChar *) "Literal Result Element";
+*/
+
+/*
+* xsltXSLTTextMarker:
+* Marker for xsl:text elements. Used to recognize xsl:text elements
+* for post-processing of the stylesheet's tree, where those
+* elements are removed from the tree.
+*/
+const xmlChar *xsltXSLTTextMarker = (const xmlChar *) "XSLT Text Element";
+
+/*
+* xsltXSLTAttrMarker:
+* Marker for XSLT attribute on Literal Result Elements.
+*/
+const xmlChar *xsltXSLTAttrMarker = (const xmlChar *) "LRE XSLT Attr";
+
+#endif
+
+/*
+ * Harmless but avoiding a problem when compiling against a
+ * libxml <= 2.3.11 without LIBXML_DEBUG_ENABLED
+ */
+#ifndef LIBXML_DEBUG_ENABLED
+double xmlXPathStringEvalNumber(const xmlChar *str);
+#endif
+/*
+ * Useful macros
+ */
+
+#ifdef  IS_BLANK
+#undef IS_BLANK
+#endif
+#define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \
+                     ((c) == 0x0D))
+
+#ifdef IS_BLANK_NODE
+#undef IS_BLANK_NODE
+#endif
+#define IS_BLANK_NODE(n)                                               \
+    (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
+
+/**
+ * xsltParseContentError:
+ *
+ * @style: the stylesheet
+ * @node: the node where the error occured
+ *
+ * Compile-time error function.
+ */
+static void
+xsltParseContentError(xsltStylesheetPtr style,
+                      xmlNodePtr node)
+{
+    if ((style == NULL) || (node == NULL))
+       return;
+
+    if (IS_XSLT_ELEM(node))
+       xsltTransformError(NULL, style, node,
+           "The XSLT-element '%s' is not allowed at this position.\n",
+           node->name);
+    else
+       xsltTransformError(NULL, style, node,
+           "The element '%s' is not allowed at this position.\n",
+           node->name);
+    style->errors++;
+}
+
+#ifdef XSLT_REFACTORED
+#else
+/**
+ * exclPrefixPush:
+ * @style: the transformation stylesheet
+ * @value:  the excluded namespace name to push on the stack
+ *
+ * Push an excluded namespace name on the stack
+ *
+ * Returns the new index in the stack or 0 in case of error
+ */
+static int
+exclPrefixPush(xsltStylesheetPtr style, xmlChar * value)
+{
+    if (style->exclPrefixMax == 0) {
+        style->exclPrefixMax = 4;
+        style->exclPrefixTab =
+            (xmlChar * *)xmlMalloc(style->exclPrefixMax *
+                                   sizeof(style->exclPrefixTab[0]));
+        if (style->exclPrefixTab == NULL) {
+            xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
+            return (0);
+        }
+    }
+    if (style->exclPrefixNr >= style->exclPrefixMax) {
+        style->exclPrefixMax *= 2;
+        style->exclPrefixTab =
+            (xmlChar * *)xmlRealloc(style->exclPrefixTab,
+                                    style->exclPrefixMax *
+                                    sizeof(style->exclPrefixTab[0]));
+        if (style->exclPrefixTab == NULL) {
+            xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
+            return (0);
+        }
+    }
+    style->exclPrefixTab[style->exclPrefixNr] = value;
+    style->exclPrefix = value;
+    return (style->exclPrefixNr++);
+}
+/**
+ * exclPrefixPop:
+ * @style: the transformation stylesheet
+ *
+ * Pop an excluded prefix value from the stack
+ *
+ * Returns the stored excluded prefix value
+ */
+static xmlChar *
+exclPrefixPop(xsltStylesheetPtr style)
+{
+    xmlChar *ret;
+
+    if (style->exclPrefixNr <= 0)
+        return (0);
+    style->exclPrefixNr--;
+    if (style->exclPrefixNr > 0)
+        style->exclPrefix = style->exclPrefixTab[style->exclPrefixNr - 1];
+    else
+        style->exclPrefix = NULL;
+    ret = style->exclPrefixTab[style->exclPrefixNr];
+    style->exclPrefixTab[style->exclPrefixNr] = 0;
+    return (ret);
+}
+#endif
+
+/************************************************************************
+ *                                                                     *
+ *                     Helper functions                                *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltInit:
+ *
+ * Initializes the processor (e.g. registers built-in extensions,
+ * etc.)
+ */
+
+static int initialized = 0;
+
+void
+xsltInit (void) {
+    if (initialized == 0) {
+       initialized = 1;
+        xsltRegisterAllExtras();
+    }
+}
+
+/**
+ * xsltUninit
+ *
+ * Uninitializes the processor.
+ */
+
+void
+xsltUninit (void) {
+    initialized = 0;
+}
+
+/**
+ * xsltIsBlank:
+ * @str:  a string
+ *
+ * Check if a string is ignorable
+ *
+ * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
+ */
+int
+xsltIsBlank(xmlChar *str) {
+    if (str == NULL)
+       return(1);
+    while (*str != 0) {
+       if (!(IS_BLANK(*str))) return(0);
+       str++;
+    }
+    return(1);
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Routines to handle XSLT data structures                 *
+ *                                                                     *
+ ************************************************************************/
+static xsltDecimalFormatPtr
+xsltNewDecimalFormat(xmlChar *name)
+{
+    xsltDecimalFormatPtr self;
+    /* UTF-8 for 0x2030 */
+    static const xmlChar permille[4] = {0xe2, 0x80, 0xb0, 0};
+
+    self = xmlMalloc(sizeof(xsltDecimalFormat));
+    if (self != NULL) {
+       self->next = NULL;
+       self->name = name;
+       
+       /* Default values */
+       self->digit = xmlStrdup(BAD_CAST("#"));
+       self->patternSeparator = xmlStrdup(BAD_CAST(";"));
+       self->decimalPoint = xmlStrdup(BAD_CAST("."));
+       self->grouping = xmlStrdup(BAD_CAST(","));
+       self->percent = xmlStrdup(BAD_CAST("%"));
+       self->permille = xmlStrdup(BAD_CAST(permille));
+       self->zeroDigit = xmlStrdup(BAD_CAST("0"));
+       self->minusSign = xmlStrdup(BAD_CAST("-"));
+       self->infinity = xmlStrdup(BAD_CAST("Infinity"));
+       self->noNumber = xmlStrdup(BAD_CAST("NaN"));
+    }
+    return self;
+}
+
+static void
+xsltFreeDecimalFormat(xsltDecimalFormatPtr self)
+{
+    if (self != NULL) {
+       if (self->digit)
+           xmlFree(self->digit);
+       if (self->patternSeparator)
+           xmlFree(self->patternSeparator);
+       if (self->decimalPoint)
+           xmlFree(self->decimalPoint);
+       if (self->grouping)
+           xmlFree(self->grouping);
+       if (self->percent)
+           xmlFree(self->percent);
+       if (self->permille)
+           xmlFree(self->permille);
+       if (self->zeroDigit)
+           xmlFree(self->zeroDigit);
+       if (self->minusSign)
+           xmlFree(self->minusSign);
+       if (self->infinity)
+           xmlFree(self->infinity);
+       if (self->noNumber)
+           xmlFree(self->noNumber);
+       if (self->name)
+           xmlFree(self->name);
+       xmlFree(self);
+    }
+}
+
+static void
+xsltFreeDecimalFormatList(xsltStylesheetPtr self)
+{
+    xsltDecimalFormatPtr iter;
+    xsltDecimalFormatPtr tmp;
+
+    if (self == NULL)
+       return;
+    
+    iter = self->decimalFormat;
+    while (iter != NULL) {
+       tmp = iter->next;
+       xsltFreeDecimalFormat(iter);
+       iter = tmp;
+    }
+}
+
+/**
+ * xsltDecimalFormatGetByName:
+ * @style: the XSLT stylesheet
+ * @name: the decimal-format name to find
+ *
+ * Find decimal-format by name
+ *
+ * Returns the xsltDecimalFormatPtr
+ */
+xsltDecimalFormatPtr
+xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name)
+{
+    xsltDecimalFormatPtr result = NULL;
+
+    if (name == NULL)
+       return style->decimalFormat;
+
+    while (style != NULL) {
+       for (result = style->decimalFormat->next;
+            result != NULL;
+            result = result->next) {
+           if (xmlStrEqual(name, result->name))
+               return result;
+       }
+       style = xsltNextImport(style);
+    }
+    return result;
+}
+
+
+/**
+ * xsltNewTemplate:
+ *
+ * Create a new XSLT Template
+ *
+ * Returns the newly allocated xsltTemplatePtr or NULL in case of error
+ */
+static xsltTemplatePtr
+xsltNewTemplate(void) {
+    xsltTemplatePtr cur;
+
+    cur = (xsltTemplatePtr) xmlMalloc(sizeof(xsltTemplate));
+    if (cur == NULL) {
+       xsltTransformError(NULL, NULL, NULL,
+               "xsltNewTemplate : malloc failed\n");
+       return(NULL);
+    }
+    memset(cur, 0, sizeof(xsltTemplate));
+    cur->priority = XSLT_PAT_NO_PRIORITY;
+    return(cur);
+}
+
+/**
+ * xsltFreeTemplate:
+ * @template:  an XSLT template
+ *
+ * Free up the memory allocated by @template
+ */
+static void
+xsltFreeTemplate(xsltTemplatePtr template) {
+    if (template == NULL)
+       return;
+    if (template->match) xmlFree(template->match);
+/*
+*   NOTE: @name and @nameURI are put into the string dict now.
+*   if (template->name) xmlFree(template->name);
+*   if (template->nameURI) xmlFree(template->nameURI);
+*/
+/*
+    if (template->mode) xmlFree(template->mode);
+    if (template->modeURI) xmlFree(template->modeURI);
+ */
+    if (template->inheritedNs) xmlFree(template->inheritedNs);
+    memset(template, -1, sizeof(xsltTemplate));
+    xmlFree(template);
+}
+
+/**
+ * xsltFreeTemplateList:
+ * @template:  an XSLT template list
+ *
+ * Free up the memory allocated by all the elements of @template
+ */
+static void
+xsltFreeTemplateList(xsltTemplatePtr template) {
+    xsltTemplatePtr cur;
+
+    while (template != NULL) {
+       cur = template;
+       template = template->next;
+       xsltFreeTemplate(cur);
+    }
+}
+
+#ifdef XSLT_REFACTORED
+
+static void
+xsltFreeNsAliasList(xsltNsAliasPtr item)
+{
+    xsltNsAliasPtr tmp;
+    
+    while (item) {
+       tmp = item;
+       item = item->next;
+       xmlFree(tmp);
+    } 
+    return;
+}
+
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+static void
+xsltFreeNamespaceMap(xsltNsMapPtr item)
+{
+    xsltNsMapPtr tmp;
+    
+    while (item) {
+       tmp = item;
+       item = item->next;
+       xmlFree(tmp);
+    } 
+    return;
+}
+
+static xsltNsMapPtr
+xsltNewNamespaceMapItem(xsltCompilerCtxtPtr cctxt,
+                       xmlDocPtr doc,
+                       xmlNsPtr ns,
+                       xmlNodePtr elem)
+{
+    xsltNsMapPtr ret;
+
+    if ((cctxt == NULL) || (doc == NULL) || (ns == NULL))
+       return(NULL);
+
+    ret = (xsltNsMapPtr) xmlMalloc(sizeof(xsltNsMap));
+    if (ret == NULL) {
+       xsltTransformError(NULL, cctxt->style, elem,
+           "Internal error: (xsltNewNamespaceMapItem) "
+           "memory allocation failed.\n");
+       return(NULL);
+    }
+    memset(ret, 0, sizeof(xsltNsMap));
+    ret->doc = doc;
+    ret->ns = ns;
+    ret->origNsName = ns->href;
+    /*
+    * Store the item at current stylesheet-level.
+    */
+    if (cctxt->psData->nsMap != NULL)
+       ret->next = cctxt->psData->nsMap;
+    cctxt->psData->nsMap = ret;
+
+    return(ret);
+}
+#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
+
+/**
+ * xsltCompilerVarInfoFree: 
+ * @cctxt: the compilation context
+ * 
+ * Frees the list of information for vars/params.
+ */
+static void
+xsltCompilerVarInfoFree(xsltCompilerCtxtPtr cctxt)
+{
+    xsltVarInfoPtr ivar = cctxt->ivars, ivartmp;    
+
+    while (ivar) {
+       ivartmp = ivar;
+       ivar = ivar->next;
+       xmlFree(ivartmp);
+    }
+}
+
+/**
+ * xsltCompilerCtxtFree:
+ *
+ * Free an XSLT compiler context. 
+ */
+static void
+xsltCompilationCtxtFree(xsltCompilerCtxtPtr cctxt)
+{    
+    if (cctxt == NULL)
+       return;
+#ifdef WITH_XSLT_DEBUG_PARSING
+    xsltGenericDebug(xsltGenericDebugContext,
+       "Freeing compilation context\n");
+    xsltGenericDebug(xsltGenericDebugContext,
+       "### Max inodes: %d\n", cctxt->maxNodeInfos);
+    xsltGenericDebug(xsltGenericDebugContext,
+       "### Max LREs  : %d\n", cctxt->maxLREs);
+#endif
+    /*
+    * Free node-infos.
+    */
+    if (cctxt->inodeList != NULL) {
+       xsltCompilerNodeInfoPtr tmp, cur = cctxt->inodeList;
+       while (cur != NULL) {
+           tmp = cur;
+           cur = cur->next;
+           xmlFree(tmp);
+       }
+    }
+    if (cctxt->tmpList != NULL)
+       xsltPointerListFree(cctxt->tmpList);
+#ifdef XSLT_REFACTORED_XPATHCOMP
+    if (cctxt->xpathCtxt != NULL)
+       xmlXPathFreeContext(cctxt->xpathCtxt);
+#endif
+    if (cctxt->nsAliases != NULL)
+       xsltFreeNsAliasList(cctxt->nsAliases);
+
+    if (cctxt->ivars)
+       xsltCompilerVarInfoFree(cctxt);
+
+    xmlFree(cctxt);
+}
+
+/**
+ * xsltCompilerCreate:
+ *
+ * Creates an XSLT compiler context.
+ *
+ * Returns the pointer to the created xsltCompilerCtxt or
+ *         NULL in case of an internal error.
+ */
+static xsltCompilerCtxtPtr
+xsltCompilationCtxtCreate(xsltStylesheetPtr style) {
+    xsltCompilerCtxtPtr ret;
+
+    ret = (xsltCompilerCtxtPtr) xmlMalloc(sizeof(xsltCompilerCtxt));
+    if (ret == NULL) {
+       xsltTransformError(NULL, style, NULL,
+           "xsltCompilerCreate: allocation of compiler "
+           "context failed.\n");
+       return(NULL);
+    }
+    memset(ret, 0, sizeof(xsltCompilerCtxt));
+
+    ret->errSeverity = XSLT_ERROR_SEVERITY_ERROR;
+    ret->tmpList = xsltPointerListCreate(20);
+    if (ret->tmpList == NULL) {
+       goto internal_err;
+    }
+#ifdef XSLT_REFACTORED_XPATHCOMP
+    /*
+    * Create the XPath compilation context in order
+    * to speed up precompilation of XPath expressions.
+    */
+    ret->xpathCtxt = xmlXPathNewContext(NULL);
+    if (ret->xpathCtxt == NULL)
+       goto internal_err;
+#endif
+    
+    return(ret);
+
+internal_err:
+    xsltCompilationCtxtFree(ret);
+    return(NULL);
+}
+
+static void
+xsltLREEffectiveNsNodesFree(xsltEffectiveNsPtr first)
+{
+    xsltEffectiveNsPtr tmp;
+
+    while (first != NULL) {
+       tmp = first;
+       first = first->nextInStore;
+       xmlFree(tmp);
+    }
+}
+
+static void
+xsltFreePrincipalStylesheetData(xsltPrincipalStylesheetDataPtr data)
+{
+    if (data == NULL)
+       return;
+
+    if (data->inScopeNamespaces != NULL) {
+       int i;
+       xsltNsListContainerPtr nsi;
+       xsltPointerListPtr list =
+           (xsltPointerListPtr) data->inScopeNamespaces;
+
+       for (i = 0; i < list->number; i++) {
+           /*
+           * REVISIT TODO: Free info of in-scope namespaces.
+           */
+           nsi = (xsltNsListContainerPtr) list->items[i];
+           if (nsi->list != NULL)
+               xmlFree(nsi->list);
+           xmlFree(nsi);
+       }
+       xsltPointerListFree(list);
+       data->inScopeNamespaces = NULL;
+    }
+
+    if (data->exclResultNamespaces != NULL) {
+       int i;
+       xsltPointerListPtr list = (xsltPointerListPtr)
+           data->exclResultNamespaces; 
+       
+       for (i = 0; i < list->number; i++)
+           xsltPointerListFree((xsltPointerListPtr) list->items[i]);
+       
+       xsltPointerListFree(list);
+       data->exclResultNamespaces = NULL;
+    }
+
+    if (data->extElemNamespaces != NULL) {
+       xsltPointerListPtr list = (xsltPointerListPtr)
+           data->extElemNamespaces;
+       int i;
+
+       for (i = 0; i < list->number; i++)
+           xsltPointerListFree((xsltPointerListPtr) list->items[i]);
+
+       xsltPointerListFree(list);
+       data->extElemNamespaces = NULL;
+    }
+    if (data->effectiveNs) {
+       xsltLREEffectiveNsNodesFree(data->effectiveNs);
+       data->effectiveNs = NULL;
+    }
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+    xsltFreeNamespaceMap(data->nsMap);
+#endif
+    xmlFree(data);
+}
+
+static xsltPrincipalStylesheetDataPtr
+xsltNewPrincipalStylesheetData(void)
+{
+    xsltPrincipalStylesheetDataPtr ret;
+
+    ret = (xsltPrincipalStylesheetDataPtr)
+       xmlMalloc(sizeof(xsltPrincipalStylesheetData));
+    if (ret == NULL) {
+       xsltTransformError(NULL, NULL, NULL,
+           "xsltNewPrincipalStylesheetData: memory allocation failed.\n");
+       return(NULL);
+    }
+    memset(ret, 0, sizeof(xsltPrincipalStylesheetData));
+    
+    /*
+    * Global list of in-scope namespaces.
+    */    
+    ret->inScopeNamespaces = xsltPointerListCreate(-1);
+    if (ret->inScopeNamespaces == NULL)
+       goto internal_err;
+    /*
+    * Global list of excluded result ns-decls.
+    */
+    ret->exclResultNamespaces = xsltPointerListCreate(-1);
+    if (ret->exclResultNamespaces == NULL)
+       goto internal_err;
+    /*
+    * Global list of extension instruction namespace names.
+    */    
+    ret->extElemNamespaces = xsltPointerListCreate(-1);
+    if (ret->extElemNamespaces == NULL)
+       goto internal_err;
+
+    return(ret);
+
+internal_err:
+
+    return(NULL);
+}
+
+#endif
+
+/**
+ * xsltNewStylesheet:
+ *
+ * Create a new XSLT Stylesheet
+ *
+ * Returns the newly allocated xsltStylesheetPtr or NULL in case of error
+ */
+xsltStylesheetPtr
+xsltNewStylesheet(void) {
+    xsltStylesheetPtr ret = NULL;    
+
+    ret = (xsltStylesheetPtr) xmlMalloc(sizeof(xsltStylesheet));
+    if (ret == NULL) {
+       xsltTransformError(NULL, NULL, NULL,
+               "xsltNewStylesheet : malloc failed\n");
+       goto internal_err;
+    }
+    memset(ret, 0, sizeof(xsltStylesheet));
+
+    ret->omitXmlDeclaration = -1;
+    ret->standalone = -1;
+    ret->decimalFormat = xsltNewDecimalFormat(NULL);
+    ret->indent = -1;
+    ret->errors = 0;
+    ret->warnings = 0;
+    ret->exclPrefixNr = 0;
+    ret->exclPrefixMax = 0;
+    ret->exclPrefixTab = NULL;
+    ret->extInfos = NULL;
+    ret->extrasNr = 0;
+    ret->internalized = 1;
+    ret->literal_result = 0;
+    ret->dict = xmlDictCreate();
+#ifdef WITH_XSLT_DEBUG
+    xsltGenericDebug(xsltGenericDebugContext,
+       "creating dictionary for stylesheet\n");
+#endif
+
+    xsltInit();
+
+    return(ret);
+
+internal_err:
+    if (ret != NULL)
+       xsltFreeStylesheet(ret);
+    return(NULL);
+}
+
+/**
+ * xsltAllocateExtra:
+ * @style:  an XSLT stylesheet
+ *
+ * Allocate an extra runtime information slot statically while compiling
+ * the stylesheet and return its number
+ *
+ * Returns the number of the slot
+ */
+int
+xsltAllocateExtra(xsltStylesheetPtr style)
+{
+    return(style->extrasNr++);
+}
+
+/**
+ * xsltAllocateExtraCtxt:
+ * @ctxt:  an XSLT transformation context
+ *
+ * Allocate an extra runtime information slot at run-time
+ * and return its number
+ * This make sure there is a slot ready in the transformation context
+ *
+ * Returns the number of the slot
+ */
+int
+xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
+{
+    if (ctxt->extrasNr >= ctxt->extrasMax) {
+       int i;
+       if (ctxt->extrasNr == 0) {
+           ctxt->extrasMax = 20;
+           ctxt->extras = (xsltRuntimeExtraPtr)
+               xmlMalloc(ctxt->extrasMax * sizeof(xsltRuntimeExtra));
+           if (ctxt->extras == NULL) {
+               xmlGenericError(xmlGenericErrorContext,
+                       "xsltAllocateExtraCtxt: out of memory\n");
+               ctxt->state = XSLT_STATE_ERROR;
+               return(0);
+           }
+           for (i = 0;i < ctxt->extrasMax;i++) {
+               ctxt->extras[i].info = NULL;
+               ctxt->extras[i].deallocate = NULL;
+               ctxt->extras[i].val.ptr = NULL;
+           }
+
+       } else {
+           xsltRuntimeExtraPtr tmp;
+
+           ctxt->extrasMax += 100;
+           tmp = (xsltRuntimeExtraPtr) xmlRealloc(ctxt->extras,
+                           ctxt->extrasMax * sizeof(xsltRuntimeExtra));
+           if (tmp == NULL) {
+               xmlGenericError(xmlGenericErrorContext,
+                       "xsltAllocateExtraCtxt: out of memory\n");
+               ctxt->state = XSLT_STATE_ERROR;
+               return(0);
+           }
+           ctxt->extras = tmp;
+           for (i = ctxt->extrasNr;i < ctxt->extrasMax;i++) {
+               ctxt->extras[i].info = NULL;
+               ctxt->extras[i].deallocate = NULL;
+               ctxt->extras[i].val.ptr = NULL;
+           }
+       }
+    }
+    return(ctxt->extrasNr++);
+}
+
+/**
+ * xsltFreeStylesheetList:
+ * @style:  an XSLT stylesheet list
+ *
+ * Free up the memory allocated by the list @style
+ */
+static void
+xsltFreeStylesheetList(xsltStylesheetPtr style) {
+    xsltStylesheetPtr next;
+
+    while (style != NULL) {
+       next = style->next;
+       xsltFreeStylesheet(style);
+       style = next;
+    }
+}
+
+/**
+ * xsltCleanupStylesheetTree:
+ *
+ * @doc: the document-node
+ * @node: the element where the stylesheet is rooted at
+ *
+ * Actually @node need not be the document-element, but
+ * currently Libxslt does not support embedeed stylesheets.
+ *
+ * Returns 0 if OK, -1 on API or internal errors.
+ */
+static int
+xsltCleanupStylesheetTree(xmlDocPtr doc, xmlNodePtr rootElem)
+{    
+#if 0 /* TODO: Currently disabled, since probably not needed. */
+    xmlNodePtr cur;
+
+    if ((doc == NULL) || (rootElem == NULL) ||
+       (rootElem->type != XML_ELEMENT_NODE) ||
+       (doc != rootElem->doc))
+       return(-1);
+
+    /*
+    * Cleanup was suggested by Aleksey Sanin:
+    * Clear the PSVI field to avoid problems if the
+    * node-tree of the stylesheet is intended to be used for
+    * further processing by the user (e.g. for compiling it
+    * once again - although not recommended).
+    */
+
+    cur = rootElem;
+    while (cur != NULL) {
+       if (cur->type == XML_ELEMENT_NODE) {
+           /*
+           * Clear the PSVI field.
+           */
+           cur->psvi = NULL;
+           if (cur->children) {
+               cur = cur->children;
+               continue;
+           }
+       }
+
+leave_node:
+       if (cur == rootElem)
+           break;
+       if (cur->next != NULL)
+           cur = cur->next;
+       else {
+           cur = cur->parent;
+           if (cur == NULL)
+               break;
+           goto leave_node;
+       }
+    }
+#endif /* #if 0 */
+    return(0);
+}
+
+/**
+ * xsltFreeStylesheet:
+ * @style:  an XSLT stylesheet
+ *
+ * Free up the memory allocated by @style
+ */
+void
+xsltFreeStylesheet(xsltStylesheetPtr style)
+{
+    if (style == NULL)
+        return;
+    
+#ifdef XSLT_REFACTORED
+    /*
+    * Start with a cleanup of the main stylesheet's doc.
+    */
+    if ((style->principal == style) && (style->doc))
+       xsltCleanupStylesheetTree(style->doc,
+           xmlDocGetRootElement(style->doc));
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+    /*
+    * Restore changed ns-decls before freeing the document.
+    */
+    if ((style->doc != NULL) &&
+       XSLT_HAS_INTERNAL_NSMAP(style))
+    {
+       xsltRestoreDocumentNamespaces(XSLT_GET_INTERNAL_NSMAP(style),
+           style->doc);        
+    }
+#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
+#else
+    /*
+    * Start with a cleanup of the main stylesheet's doc.
+    */
+    if ((style->parent == NULL) && (style->doc))
+       xsltCleanupStylesheetTree(style->doc,
+           xmlDocGetRootElement(style->doc));
+#endif /* XSLT_REFACTORED */
+
+    xsltFreeKeys(style);
+    xsltFreeExts(style);
+    xsltFreeTemplateHashes(style);
+    xsltFreeDecimalFormatList(style);
+    xsltFreeTemplateList(style->templates);
+    xsltFreeAttributeSetsHashes(style);
+    xsltFreeNamespaceAliasHashes(style);
+    xsltFreeStylePreComps(style);
+    /*
+    * Free documents of all included stylsheet modules of this
+    * stylesheet level.
+    */
+    xsltFreeStyleDocuments(style);
+    /*
+    * TODO: Best time to shutdown extension stuff?
+    */
+    xsltShutdownExts(style);
+       
+    if (style->variables != NULL)
+        xsltFreeStackElemList(style->variables);
+    if (style->cdataSection != NULL)
+        xmlHashFree(style->cdataSection, NULL);
+    if (style->stripSpaces != NULL)
+        xmlHashFree(style->stripSpaces, NULL);
+    if (style->nsHash != NULL)
+        xmlHashFree(style->nsHash, NULL);
+    if (style->exclPrefixTab != NULL)
+        xmlFree(style->exclPrefixTab);
+    if (style->method != NULL)
+        xmlFree(style->method);
+    if (style->methodURI != NULL)
+        xmlFree(style->methodURI);
+    if (style->version != NULL)
+        xmlFree(style->version);
+    if (style->encoding != NULL)
+        xmlFree(style->encoding);
+    if (style->doctypePublic != NULL)
+        xmlFree(style->doctypePublic);
+    if (style->doctypeSystem != NULL)
+        xmlFree(style->doctypeSystem);
+    if (style->mediaType != NULL)
+        xmlFree(style->mediaType);
+    if (style->attVTs)
+        xsltFreeAVTList(style->attVTs);
+    if (style->imports != NULL)
+        xsltFreeStylesheetList(style->imports);
+
+#ifdef XSLT_REFACTORED
+    /*
+    * If this is the principal stylesheet, then
+    * free its internal data.
+    */
+    if (style->principal == style) {
+       if (style->principalData) {
+           xsltFreePrincipalStylesheetData(style->principalData);
+           style->principalData = NULL;
+       }
+    }    
+#endif
+    /*
+    * Better to free the main document of this stylesheet level
+    * at the end - so here.
+    */
+    if (style->doc != NULL) {  
+        xmlFreeDoc(style->doc);
+    }
+
+#ifdef WITH_XSLT_DEBUG
+    xsltGenericDebug(xsltGenericDebugContext,
+                     "freeing dictionary from stylesheet\n");
+#endif
+    xmlDictFree(style->dict);
+
+    memset(style, -1, sizeof(xsltStylesheet));
+    xmlFree(style);
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Parsing of an XSLT Stylesheet                           *
+ *                                                                     *
+ ************************************************************************/
+
+#ifdef XSLT_REFACTORED
+    /*
+    * This is now performed in an optimized way in xsltParseXSLTTemplate.
+    */
+#else
+/**
+ * xsltGetInheritedNsList:
+ * @style:  the stylesheet
+ * @template: the template
+ * @node:  the current node
+ *
+ * Search all the namespace applying to a given element except the ones 
+ * from excluded output prefixes currently in scope. Initialize the
+ * template inheritedNs list with it.
+ *
+ * Returns the number of entries found
+ */
+static int
+xsltGetInheritedNsList(xsltStylesheetPtr style,
+                      xsltTemplatePtr template,
+                      xmlNodePtr node)
+{
+    xmlNsPtr cur;
+    xmlNsPtr *ret = NULL;
+    int nbns = 0;
+    int maxns = 10;
+    int i;    
+
+    if ((style == NULL) || (template == NULL) || (node == NULL) ||
+       (template->inheritedNsNr != 0) || (template->inheritedNs != NULL))
+       return(0);
+    while (node != NULL) {
+        if (node->type == XML_ELEMENT_NODE) {
+            cur = node->nsDef;
+            while (cur != NULL) {
+               if (xmlStrEqual(cur->href, XSLT_NAMESPACE))
+                   goto skip_ns;
+
+               if ((cur->prefix != NULL) &&
+                   (xsltCheckExtPrefix(style, cur->prefix)))
+                   goto skip_ns;
+               /*
+               * Check if this namespace was excluded.
+               * Note that at this point only the exclusions defined
+               * on the topmost stylesheet element are in the exclusion-list.
+               */
+               for (i = 0;i < style->exclPrefixNr;i++) {
+                   if (xmlStrEqual(cur->href, style->exclPrefixTab[i]))
+                       goto skip_ns;
+               }
+                if (ret == NULL) {
+                    ret =
+                        (xmlNsPtr *) xmlMalloc((maxns + 1) *
+                                               sizeof(xmlNsPtr));
+                    if (ret == NULL) {
+                        xmlGenericError(xmlGenericErrorContext,
+                                        "xsltGetInheritedNsList : out of memory!\n");
+                        return(0);
+                    }
+                    ret[nbns] = NULL;
+                }
+               /*
+               * Skip shadowed namespace bindings.
+               */
+                for (i = 0; i < nbns; i++) {
+                    if ((cur->prefix == ret[i]->prefix) ||
+                        (xmlStrEqual(cur->prefix, ret[i]->prefix)))
+                        break;
+                }
+                if (i >= nbns) {
+                    if (nbns >= maxns) {
+                        maxns *= 2;
+                        ret = (xmlNsPtr *) xmlRealloc(ret,
+                                                      (maxns +
+                                                       1) *
+                                                      sizeof(xmlNsPtr));
+                        if (ret == NULL) {
+                            xmlGenericError(xmlGenericErrorContext,
+                                            "xsltGetInheritedNsList : realloc failed!\n");
+                            return(0);
+                        }
+                    }
+                    ret[nbns++] = cur;
+                    ret[nbns] = NULL;
+                }
+skip_ns:
+                cur = cur->next;
+            }
+        }
+        node = node->parent;
+    }
+    if (nbns != 0) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+        xsltGenericDebug(xsltGenericDebugContext,
+                         "template has %d inherited namespaces\n", nbns);
+#endif
+       template->inheritedNsNr = nbns;
+       template->inheritedNs = ret;
+    }
+    return (nbns);
+}
+#endif /* else of XSLT_REFACTORED */
+
+/**
+ * xsltParseStylesheetOutput:
+ * @style:  the XSLT stylesheet
+ * @cur:  the "output" element
+ *
+ * parse an XSLT stylesheet output element and record
+ * information related to the stylesheet output
+ */
+
+void
+xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)
+{
+    xmlChar *elements,
+     *prop;
+    xmlChar *element,
+     *end;
+
+    if ((cur == NULL) || (style == NULL))
+        return;
+   
+    prop = xmlGetNsProp(cur, (const xmlChar *) "version", NULL);
+    if (prop != NULL) {
+        if (style->version != NULL)
+            xmlFree(style->version);
+        style->version = prop;
+    }
+
+    prop = xmlGetNsProp(cur, (const xmlChar *) "encoding", NULL);
+    if (prop != NULL) {
+        if (style->encoding != NULL)
+            xmlFree(style->encoding);
+        style->encoding = prop;
+    }
+
+    /* relaxed to support xt:document
+    * TODO KB: What does "relaxed to support xt:document" mean?
+    */
+    prop = xmlGetNsProp(cur, (const xmlChar *) "method", NULL);
+    if (prop != NULL) {
+        const xmlChar *URI;
+
+        if (style->method != NULL)
+            xmlFree(style->method);
+        style->method = NULL;
+        if (style->methodURI != NULL)
+            xmlFree(style->methodURI);
+        style->methodURI = NULL;
+
+       /*
+       * TODO: Don't use xsltGetQNameURI().
+       */
+       URI = xsltGetQNameURI(cur, &prop);
+       if (prop == NULL) {
+           if (style != NULL) style->errors++;
+       } else if (URI == NULL) {
+            if ((xmlStrEqual(prop, (const xmlChar *) "xml")) ||
+                (xmlStrEqual(prop, (const xmlChar *) "html")) ||
+                (xmlStrEqual(prop, (const xmlChar *) "text"))) {
+                style->method = prop;
+            } else {
+               xsltTransformError(NULL, style, cur,
+                                 "invalid value for method: %s\n", prop);
+                if (style != NULL) style->warnings++;
+            }
+       } else {
+           style->method = prop;
+           style->methodURI = xmlStrdup(URI);
+       }
+    }
+
+    prop = xmlGetNsProp(cur, (const xmlChar *) "doctype-system", NULL);
+    if (prop != NULL) {
+        if (style->doctypeSystem != NULL)
+            xmlFree(style->doctypeSystem);
+        style->doctypeSystem = prop;
+    }
+
+    prop = xmlGetNsProp(cur, (const xmlChar *) "doctype-public", NULL);
+    if (prop != NULL) {
+        if (style->doctypePublic != NULL)
+            xmlFree(style->doctypePublic);
+        style->doctypePublic = prop;
+    }
+
+    prop = xmlGetNsProp(cur, (const xmlChar *) "standalone", NULL);
+    if (prop != NULL) {
+        if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
+            style->standalone = 1;
+        } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
+            style->standalone = 0;
+        } else {
+           xsltTransformError(NULL, style, cur,
+                             "invalid value for standalone: %s\n", prop);
+            style->errors++;
+        }
+        xmlFree(prop);
+    }
+
+    prop = xmlGetNsProp(cur, (const xmlChar *) "indent", NULL);
+    if (prop != NULL) {
+        if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
+            style->indent = 1;
+        } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
+            style->indent = 0;
+        } else {
+           xsltTransformError(NULL, style, cur,
+                             "invalid value for indent: %s\n", prop);
+            style->errors++;
+        }
+        xmlFree(prop);
+    }
+
+    prop = xmlGetNsProp(cur, (const xmlChar *) "omit-xml-declaration", NULL);
+    if (prop != NULL) {
+        if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
+            style->omitXmlDeclaration = 1;
+        } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
+            style->omitXmlDeclaration = 0;
+        } else {
+           xsltTransformError(NULL, style, cur,
+                             "invalid value for omit-xml-declaration: %s\n",
+                             prop);
+            style->errors++;
+        }
+        xmlFree(prop);
+    }
+
+    elements = xmlGetNsProp(cur, (const xmlChar *) "cdata-section-elements",
+       NULL);
+    if (elements != NULL) {
+        if (style->cdataSection == NULL)
+            style->cdataSection = xmlHashCreate(10);
+        if (style->cdataSection == NULL)
+            return;
+
+        element = elements;
+        while (*element != 0) {
+            while (IS_BLANK(*element))
+                element++;
+            if (*element == 0)
+                break;
+            end = element;
+            while ((*end != 0) && (!IS_BLANK(*end)))
+                end++;
+            element = xmlStrndup(element, end - element);
+            if (element) {             
+#ifdef WITH_XSLT_DEBUG_PARSING
+                xsltGenericDebug(xsltGenericDebugContext,
+                                 "add cdata section output element %s\n",
+                                 element);
+#endif
+               if (xmlValidateQName(BAD_CAST element, 0) != 0) {
+                   xsltTransformError(NULL, style, cur,
+                       "Attribute 'cdata-section-elements': The value "
+                       "'%s' is not a valid QName.\n", element);
+                   xmlFree(element);
+                   style->errors++;
+               } else {
+                   const xmlChar *URI;
+
+                   /*
+                   * TODO: Don't use xsltGetQNameURI().
+                   */
+                   URI = xsltGetQNameURI(cur, &element);
+                   if (element == NULL) {
+                       /*
+                       * TODO: We'll report additionally an error
+                       *  via the stylesheet's error handling.                 
+                       */
+                       xsltTransformError(NULL, style, cur,
+                           "Attribute 'cdata-section-elements': The value "
+                           "'%s' is not a valid QName.\n", element);
+                       style->errors++;
+                   } else {
+                       xmlNsPtr ns;
+                       
+                       /*
+                       * XSLT-1.0 "Each QName is expanded into an
+                       *  expanded-name using the namespace declarations in
+                       *  effect on the xsl:output element in which the QName
+                       *  occurs; if there is a default namespace, it is used
+                       *  for QNames that do not have a prefix"
+                       * NOTE: Fix of bug #339570.
+                       */
+                       if (URI == NULL) {
+                           ns = xmlSearchNs(style->doc, cur, NULL);
+                           if (ns != NULL)
+                               URI = ns->href;
+                       }                  
+                       xmlHashAddEntry2(style->cdataSection, element, URI,
+                           (void *) "cdata");
+                       xmlFree(element);
+                   }
+               }
+            }
+            element = end;
+        }
+        xmlFree(elements);
+    }
+
+    prop = xmlGetNsProp(cur, (const xmlChar *) "media-type", NULL);
+    if (prop != NULL) {
+       if (style->mediaType)
+           xmlFree(style->mediaType);
+       style->mediaType = prop;
+    }
+    if (cur->children != NULL) {
+       xsltParseContentError(style, cur->children);
+    }
+}
+
+/**
+ * xsltParseStylesheetDecimalFormat:
+ * @style:  the XSLT stylesheet
+ * @cur:  the "decimal-format" element
+ *
+ * <!-- Category: top-level-element -->
+ * <xsl:decimal-format
+ *   name = qname, decimal-separator = char, grouping-separator = char,
+ *   infinity = string, minus-sign = char, NaN = string, percent = char
+ *   per-mille = char, zero-digit = char, digit = char,
+ * pattern-separator = char />
+ *
+ * parse an XSLT stylesheet decimal-format element and
+ * and record the formatting characteristics
+ */
+static void
+xsltParseStylesheetDecimalFormat(xsltStylesheetPtr style, xmlNodePtr cur)
+{
+    xmlChar *prop;
+    xsltDecimalFormatPtr format;
+    xsltDecimalFormatPtr iter;
+    
+    if ((cur == NULL) || (style == NULL))
+       return;
+
+    format = style->decimalFormat;
+    
+    prop = xmlGetNsProp(cur, BAD_CAST("name"), NULL);
+    if (prop != NULL) {
+       format = xsltDecimalFormatGetByName(style, prop);
+       if (format != NULL) {
+           xsltTransformError(NULL, style, cur,
+        "xsltParseStylestyleDecimalFormat: %s already exists\n", prop);
+           if (style != NULL) style->warnings++;
+           return;
+       }
+       format = xsltNewDecimalFormat(prop);
+       if (format == NULL) {
+           xsltTransformError(NULL, style, cur,
+     "xsltParseStylestyleDecimalFormat: failed creating new decimal-format\n");
+           if (style != NULL) style->errors++;
+           return;
+       }
+       /* Append new decimal-format structure */
+       for (iter = style->decimalFormat; iter->next; iter = iter->next)
+           ;
+       if (iter)
+           iter->next = format;
+    }
+
+    prop = xmlGetNsProp(cur, (const xmlChar *)"decimal-separator", NULL);
+    if (prop != NULL) {
+       if (format->decimalPoint != NULL) xmlFree(format->decimalPoint);
+       format->decimalPoint  = prop;
+    }
+    
+    prop = xmlGetNsProp(cur, (const xmlChar *)"grouping-separator", NULL);
+    if (prop != NULL) {
+       if (format->grouping != NULL) xmlFree(format->grouping);
+       format->grouping  = prop;
+    }
+
+    prop = xmlGetNsProp(cur, (const xmlChar *)"infinity", NULL);
+    if (prop != NULL) {
+       if (format->infinity != NULL) xmlFree(format->infinity);
+       format->infinity  = prop;
+    }
+    
+    prop = xmlGetNsProp(cur, (const xmlChar *)"minus-sign", NULL);
+    if (prop != NULL) {
+       if (format->minusSign != NULL) xmlFree(format->minusSign);
+       format->minusSign  = prop;
+    }
+    
+    prop = xmlGetNsProp(cur, (const xmlChar *)"NaN", NULL);
+    if (prop != NULL) {
+       if (format->noNumber != NULL) xmlFree(format->noNumber);
+       format->noNumber  = prop;
+    }
+    
+    prop = xmlGetNsProp(cur, (const xmlChar *)"percent", NULL);
+    if (prop != NULL) {
+       if (format->percent != NULL) xmlFree(format->percent);
+       format->percent  = prop;
+    }
+    
+    prop = xmlGetNsProp(cur, (const xmlChar *)"per-mille", NULL);
+    if (prop != NULL) {
+       if (format->permille != NULL) xmlFree(format->permille);
+       format->permille  = prop;
+    }
+    
+    prop = xmlGetNsProp(cur, (const xmlChar *)"zero-digit", NULL);
+    if (prop != NULL) {
+       if (format->zeroDigit != NULL) xmlFree(format->zeroDigit);
+       format->zeroDigit  = prop;
+    }
+    
+    prop = xmlGetNsProp(cur, (const xmlChar *)"digit", NULL);
+    if (prop != NULL) {
+       if (format->digit != NULL) xmlFree(format->digit);
+       format->digit  = prop;
+    }
+    
+    prop = xmlGetNsProp(cur, (const xmlChar *)"pattern-separator", NULL);
+    if (prop != NULL) {
+       if (format->patternSeparator != NULL) xmlFree(format->patternSeparator);
+       format->patternSeparator  = prop;
+    }
+    if (cur->children != NULL) {
+       xsltParseContentError(style, cur->children);
+    }
+}
+
+/**
+ * xsltParseStylesheetPreserveSpace:
+ * @style:  the XSLT stylesheet
+ * @cur:  the "preserve-space" element
+ *
+ * parse an XSLT stylesheet preserve-space element and record
+ * elements needing preserving
+ */
+
+static void
+xsltParseStylesheetPreserveSpace(xsltStylesheetPtr style, xmlNodePtr cur) {
+    xmlChar *elements;
+    xmlChar *element, *end;
+
+    if ((cur == NULL) || (style == NULL))
+       return;
+
+    elements = xmlGetNsProp(cur, (const xmlChar *)"elements", NULL);
+    if (elements == NULL) {
+       xsltTransformError(NULL, style, cur,
+           "xsltParseStylesheetPreserveSpace: missing elements attribute\n");
+       if (style != NULL) style->warnings++;
+       return;
+    }
+
+    if (style->stripSpaces == NULL)
+       style->stripSpaces = xmlHashCreate(10);
+    if (style->stripSpaces == NULL)
+       return;
+
+    element = elements;
+    while (*element != 0) {
+       while (IS_BLANK(*element)) element++;
+       if (*element == 0)
+           break;
+        end = element;
+       while ((*end != 0) && (!IS_BLANK(*end))) end++;
+       element = xmlStrndup(element, end - element);
+       if (element) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+           xsltGenericDebug(xsltGenericDebugContext,
+               "add preserved space element %s\n", element);
+#endif
+           if (xmlStrEqual(element, (const xmlChar *)"*")) {
+               style->stripAll = -1;
+           } else {
+               const xmlChar *URI;
+
+               /*
+               * TODO: Don't use xsltGetQNameURI().
+               */
+                URI = xsltGetQNameURI(cur, &element);
+
+               xmlHashAddEntry2(style->stripSpaces, element, URI,
+                               (xmlChar *) "preserve");
+           }
+           xmlFree(element);
+       }
+       element = end;
+    }
+    xmlFree(elements);
+    if (cur->children != NULL) {
+       xsltParseContentError(style, cur->children);
+    }
+}
+
+#ifdef XSLT_REFACTORED
+#else
+/**
+ * xsltParseStylesheetExtPrefix:
+ * @style:  the XSLT stylesheet
+ * @template:  the "extension-element-prefixes" prefix
+ *
+ * parse an XSLT stylesheet's "extension-element-prefix" attribute value
+ * and register the namespaces of extension instruction.
+ * SPEC "A namespace is designated as an extension namespace by using
+ *   an extension-element-prefixes attribute on:
+ *   1) an xsl:stylesheet element
+ *   2) an xsl:extension-element-prefixes attribute on a
+ *      literal result element 
+ *   3) an extension instruction."
+ */
+static void
+xsltParseStylesheetExtPrefix(xsltStylesheetPtr style, xmlNodePtr cur,
+                            int isXsltElem) {
+    xmlChar *prefixes;
+    xmlChar *prefix, *end;
+
+    if ((cur == NULL) || (style == NULL))
+       return;
+
+    if (isXsltElem) {
+       /* For xsl:stylesheet/xsl:transform. */
+       prefixes = xmlGetNsProp(cur,
+           (const xmlChar *)"extension-element-prefixes", NULL);
+    } else {
+       /* For literal result elements and extension instructions. */
+       prefixes = xmlGetNsProp(cur,
+           (const xmlChar *)"extension-element-prefixes", XSLT_NAMESPACE);
+    }
+    if (prefixes == NULL) {
+       return;
+    }
+
+    prefix = prefixes;
+    while (*prefix != 0) {
+       while (IS_BLANK(*prefix)) prefix++;
+       if (*prefix == 0)
+           break;
+        end = prefix;
+       while ((*end != 0) && (!IS_BLANK(*end))) end++;
+       prefix = xmlStrndup(prefix, end - prefix);
+       if (prefix) {
+           xmlNsPtr ns;
+
+           if (xmlStrEqual(prefix, (const xmlChar *)"#default"))
+               ns = xmlSearchNs(style->doc, cur, NULL);
+           else
+               ns = xmlSearchNs(style->doc, cur, prefix);
+           if (ns == NULL) {
+               xsltTransformError(NULL, style, cur,
+           "xsl:extension-element-prefix : undefined namespace %s\n",
+                                prefix);
+               if (style != NULL) style->warnings++;
+           } else {
+#ifdef WITH_XSLT_DEBUG_PARSING
+               xsltGenericDebug(xsltGenericDebugContext,
+                   "add extension prefix %s\n", prefix);
+#endif
+               xsltRegisterExtPrefix(style, prefix, ns->href);
+           }
+           xmlFree(prefix);
+       }
+       prefix = end;
+    }
+    xmlFree(prefixes);
+}
+#endif /* else of XSLT_REFACTORED */
+
+/**
+ * xsltParseStylesheetStripSpace:
+ * @style:  the XSLT stylesheet
+ * @cur:  the "strip-space" element
+ *
+ * parse an XSLT stylesheet's strip-space element and record
+ * the elements needing stripping
+ */
+
+static void
+xsltParseStylesheetStripSpace(xsltStylesheetPtr style, xmlNodePtr cur) {
+    xmlChar *elements;
+    xmlChar *element, *end;
+
+    if ((cur == NULL) || (style == NULL))
+       return;
+
+    elements = xmlGetNsProp(cur, (const xmlChar *)"elements", NULL);
+    if (elements == NULL) {
+       xsltTransformError(NULL, style, cur,
+           "xsltParseStylesheetStripSpace: missing elements attribute\n");
+       if (style != NULL) style->warnings++;
+       return;
+    }
+
+    if (style->stripSpaces == NULL)
+       style->stripSpaces = xmlHashCreate(10);
+    if (style->stripSpaces == NULL)
+       return;
+
+    element = elements;
+    while (*element != 0) {
+       while (IS_BLANK(*element)) element++;
+       if (*element == 0)
+           break;
+        end = element;
+       while ((*end != 0) && (!IS_BLANK(*end))) end++;
+       element = xmlStrndup(element, end - element);
+       if (element) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+           xsltGenericDebug(xsltGenericDebugContext,
+               "add stripped space element %s\n", element);
+#endif
+           if (xmlStrEqual(element, (const xmlChar *)"*")) {
+               style->stripAll = 1;
+           } else {
+               const xmlChar *URI;
+
+               /*
+               * TODO: Don't use xsltGetQNameURI().
+               */
+                URI = xsltGetQNameURI(cur, &element);
+
+               xmlHashAddEntry2(style->stripSpaces, element, URI,
+                               (xmlChar *) "strip");
+           }
+           xmlFree(element);
+       }
+       element = end;
+    }
+    xmlFree(elements);
+    if (cur->children != NULL) {
+       xsltParseContentError(style, cur->children);
+    }
+}
+
+#ifdef XSLT_REFACTORED
+#else
+/**
+ * xsltParseStylesheetExcludePrefix:
+ * @style:  the XSLT stylesheet
+ * @cur:  the current point in the stylesheet
+ *
+ * parse an XSLT stylesheet exclude prefix and record
+ * namespaces needing stripping
+ *
+ * Returns the number of Excluded prefixes added at that level
+ */
+
+static int
+xsltParseStylesheetExcludePrefix(xsltStylesheetPtr style, xmlNodePtr cur,
+                                int isXsltElem)
+{
+    int nb = 0;
+    xmlChar *prefixes;
+    xmlChar *prefix, *end;
+
+    if ((cur == NULL) || (style == NULL))
+       return(0);
+
+    if (isXsltElem)
+       prefixes = xmlGetNsProp(cur,
+           (const xmlChar *)"exclude-result-prefixes", NULL);
+    else
+       prefixes = xmlGetNsProp(cur,
+           (const xmlChar *)"exclude-result-prefixes", XSLT_NAMESPACE);
+
+    if (prefixes == NULL) {
+       return(0);
+    }
+
+    prefix = prefixes;
+    while (*prefix != 0) {
+       while (IS_BLANK(*prefix)) prefix++;
+       if (*prefix == 0)
+           break;
+        end = prefix;
+       while ((*end != 0) && (!IS_BLANK(*end))) end++;
+       prefix = xmlStrndup(prefix, end - prefix);
+       if (prefix) {
+           xmlNsPtr ns;
+
+           if (xmlStrEqual(prefix, (const xmlChar *)"#default"))
+               ns = xmlSearchNs(style->doc, cur, NULL);
+           else
+               ns = xmlSearchNs(style->doc, cur, prefix);
+           if (ns == NULL) {
+               xsltTransformError(NULL, style, cur,
+           "xsl:exclude-result-prefixes : undefined namespace %s\n",
+                                prefix);
+               if (style != NULL) style->warnings++;
+           } else {
+#ifdef WITH_XSLT_DEBUG_PARSING
+               xsltGenericDebug(xsltGenericDebugContext,
+                   "exclude result prefix %s\n", prefix);
+#endif
+               exclPrefixPush(style, (xmlChar *) ns->href);
+               nb++;
+           }
+           xmlFree(prefix);
+       }
+       prefix = end;
+    }
+    xmlFree(prefixes);
+    return(nb);
+}
+#endif /* else of XSLT_REFACTORED */
+
+#ifdef XSLT_REFACTORED
+
+/*
+* xsltTreeEnsureXMLDecl:
+* @doc: the doc
+* 
+* BIG NOTE:
+*  This was copy&pasted from Libxml2's xmlTreeEnsureXMLDecl() in "tree.c".
+* Ensures that there is an XML namespace declaration on the doc.
+* 
+* Returns the XML ns-struct or NULL on API and internal errors.
+*/
+static xmlNsPtr
+xsltTreeEnsureXMLDecl(xmlDocPtr doc)
+{
+    if (doc == NULL)
+       return (NULL);
+    if (doc->oldNs != NULL)
+       return (doc->oldNs);
+    {
+       xmlNsPtr ns;
+       ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
+       if (ns == NULL) {
+           xmlGenericError(xmlGenericErrorContext,
+               "xsltTreeEnsureXMLDecl: Failed to allocate "
+               "the XML namespace.\n");        
+           return (NULL);
+       }
+       memset(ns, 0, sizeof(xmlNs));
+       ns->type = XML_LOCAL_NAMESPACE;
+       /*
+       * URGENT TODO: revisit this.
+       */
+#ifdef LIBXML_NAMESPACE_DICT
+       if (doc->dict)
+           ns->href = xmlDictLookup(doc->dict, XML_XML_NAMESPACE, -1);
+       else
+           ns->href = xmlStrdup(XML_XML_NAMESPACE);
+#else
+       ns->href = xmlStrdup(XML_XML_NAMESPACE); 
+#endif
+       ns->prefix = xmlStrdup((const xmlChar *)"xml");
+       doc->oldNs = ns;
+       return (ns);
+    }
+}
+
+/*
+* xsltTreeAcquireStoredNs:
+* @doc: the doc
+* @nsName: the namespace name
+* @prefix: the prefix
+* 
+* BIG NOTE:
+*  This was copy&pasted from Libxml2's xmlDOMWrapStoreNs() in "tree.c".
+* Creates or reuses an xmlNs struct on doc->oldNs with
+* the given prefix and namespace name.
+* 
+* Returns the aquired ns struct or NULL in case of an API
+*         or internal error.
+*/
+static xmlNsPtr
+xsltTreeAcquireStoredNs(xmlDocPtr doc,
+                       const xmlChar *nsName,
+                       const xmlChar *prefix)
+{
+    xmlNsPtr ns;
+
+    if (doc == NULL)
+       return (NULL);
+    if (doc->oldNs != NULL)
+       ns = doc->oldNs;
+    else
+       ns = xsltTreeEnsureXMLDecl(doc);
+    if (ns == NULL)
+       return (NULL);
+    if (ns->next != NULL) {
+       /* Reuse. */
+       ns = ns->next;
+       while (ns != NULL) {
+           if ((ns->prefix == NULL) != (prefix == NULL)) {
+               /* NOP */
+           } else if (prefix == NULL) {
+               if (xmlStrEqual(ns->href, nsName))
+                   return (ns);
+           } else {
+               if ((ns->prefix[0] == prefix[0]) &&
+                    xmlStrEqual(ns->prefix, prefix) &&
+                    xmlStrEqual(ns->href, nsName))
+                   return (ns);
+               
+           }
+           if (ns->next == NULL)
+               break;
+           ns = ns->next;
+       }
+    }
+    /* Create. */
+    ns->next = xmlNewNs(NULL, nsName, prefix);
+    return (ns->next);
+}
+
+/**
+ * xsltLREBuildEffectiveNs:
+ *
+ * Apply ns-aliasing on the namespace of the given @elem and
+ * its attributes.
+ */
+static int
+xsltLREBuildEffectiveNs(xsltCompilerCtxtPtr cctxt,
+                       xmlNodePtr elem)
+{
+    xmlNsPtr ns;
+    xsltNsAliasPtr alias;
+
+    if ((cctxt == NULL) || (elem == NULL))
+       return(-1);
+    if ((cctxt->nsAliases == NULL) || (! cctxt->hasNsAliases))
+       return(0);
+
+    alias = cctxt->nsAliases;                  
+    while (alias != NULL) {
+       if ( /* If both namespaces are NULL... */
+           ( (elem->ns == NULL) &&
+           ((alias->literalNs == NULL) ||
+           (alias->literalNs->href == NULL)) ) ||
+           /* ... or both namespace are equal */
+           ( (elem->ns != NULL) &&
+           (alias->literalNs != NULL) &&
+           xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )
+       {
+           if ((alias->targetNs != NULL) &&
+               (alias->targetNs->href != NULL))
+           {
+               /*
+               * Convert namespace.
+               */
+               if (elem->doc == alias->docOfTargetNs) {
+                   /*
+                   * This is the nice case: same docs.
+                   * This will eventually assign a ns-decl which
+                   * is shadowed, but this has no negative effect on
+                   * the generation of the result tree.
+                   */
+                   elem->ns = alias->targetNs;
+               } else {
+                   /*
+                   * This target xmlNs originates from a different
+                   * stylesheet tree. Try to locate it in the
+                   * in-scope namespaces.
+                   * OPTIMIZE TODO: Use the compiler-node-info inScopeNs.
+                   */
+                   ns = xmlSearchNs(elem->doc, elem,
+                       alias->targetNs->prefix);                   
+                   /*
+                   * If no matching ns-decl found, then assign a
+                   * ns-decl stored in xmlDoc.
+                   */
+                   if ((ns == NULL) ||
+                       (! xmlStrEqual(ns->href, alias->targetNs->href)))
+                   {
+                       /*
+                       * BIG NOTE: The use of xsltTreeAcquireStoredNs()
+                       *  is not very efficient, but currently I don't
+                       *  see an other way of *safely* changing a node's
+                       *  namespace, since the xmlNs struct in
+                       *  alias->targetNs might come from an other
+                       *  stylesheet tree. So we need to anchor it in the
+                       *  current document, without adding it to the tree,
+                       *  which would otherwise change the in-scope-ns
+                       *  semantic of the tree.
+                       */
+                       ns = xsltTreeAcquireStoredNs(elem->doc,
+                           alias->targetNs->href,
+                           alias->targetNs->prefix);
+                       
+                       if (ns == NULL) {
+                           xsltTransformError(NULL, cctxt->style, elem,
+                               "Internal error in "
+                               "xsltLREBuildEffectiveNs(): "
+                               "failed to acquire a stored "
+                               "ns-declaration.\n");
+                           cctxt->style->errors++;
+                           return(-1);
+                           
+                       }
+                   }
+                   elem->ns = ns;
+               }                  
+           } else {
+               /*
+               * Move into or leave in the NULL namespace.
+               */
+               elem->ns = NULL;
+           }
+           break;
+       }
+       alias = alias->next;
+    }
+    /*
+    * Same with attributes of literal result elements.
+    */
+    if (elem->properties != NULL) {
+       xmlAttrPtr attr = elem->properties;
+       
+       while (attr != NULL) {
+           if (attr->ns == NULL) {
+               attr = attr->next;
+               continue;
+           }
+           alias = cctxt->nsAliases;
+           while (alias != NULL) {
+               if ( /* If both namespaces are NULL... */
+                   ( (elem->ns == NULL) &&
+                   ((alias->literalNs == NULL) ||
+                   (alias->literalNs->href == NULL)) ) ||
+                   /* ... or both namespace are equal */
+                   ( (elem->ns != NULL) &&
+                   (alias->literalNs != NULL) &&
+                   xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )
+               {
+                   if ((alias->targetNs != NULL) &&
+                       (alias->targetNs->href != NULL))
+                   {               
+                       if (elem->doc == alias->docOfTargetNs) {
+                           elem->ns = alias->targetNs;
+                       } else {
+                           ns = xmlSearchNs(elem->doc, elem,
+                               alias->targetNs->prefix);
+                           if ((ns == NULL) ||
+                               (! xmlStrEqual(ns->href, alias->targetNs->href)))
+                           {
+                               ns = xsltTreeAcquireStoredNs(elem->doc,
+                                   alias->targetNs->href,
+                                   alias->targetNs->prefix);
+                               
+                               if (ns == NULL) {
+                                   xsltTransformError(NULL, cctxt->style, elem,
+                                       "Internal error in "
+                                       "xsltLREBuildEffectiveNs(): "
+                                       "failed to acquire a stored "
+                                       "ns-declaration.\n");
+                                   cctxt->style->errors++;
+                                   return(-1);
+                                   
+                               }
+                           }
+                           elem->ns = ns;
+                       }
+                   } else {
+                   /*
+                   * Move into or leave in the NULL namespace.
+                       */
+                       elem->ns = NULL;
+                   }
+                   break;
+               }
+               alias = alias->next;
+           }
+           
+           attr = attr->next;
+       }
+    }
+    return(0);
+}
+
+/**
+ * xsltLREBuildEffectiveNsNodes:
+ *
+ * Computes the effective namespaces nodes for a literal result
+ * element.
+ * @effectiveNs is the set of effective ns-nodes
+ *  on the literal result element, which will be added to the result
+ *  element if not already existing in the result tree.
+ *  This means that excluded namespaces (via exclude-result-prefixes,
+ *  extension-element-prefixes and the XSLT namespace) not added
+ *  to the set.
+ *  Namespace-aliasing was applied on the @effectiveNs.
+ */
+static int
+xsltLREBuildEffectiveNsNodes(xsltCompilerCtxtPtr cctxt,
+                            xsltStyleItemLRElementInfoPtr item,
+                            xmlNodePtr elem,
+                            int isLRE)
+{
+    xmlNsPtr ns, tmpns;
+    xsltEffectiveNsPtr effNs, lastEffNs = NULL;
+    int i, j, holdByElem;
+    xsltPointerListPtr extElemNs = cctxt->inode->extElemNs;
+    xsltPointerListPtr exclResultNs = cctxt->inode->exclResultNs;
+
+    if ((cctxt == NULL) || (cctxt->inode == NULL) || (elem == NULL) ||
+       (item == NULL) || (item->effectiveNs != NULL))
+       return(-1);
+
+    if (item->inScopeNs == NULL)    
+       return(0);
+
+    extElemNs = cctxt->inode->extElemNs;
+    exclResultNs = cctxt->inode->exclResultNs;
+
+    for (i = 0; i < item->inScopeNs->totalNumber; i++) {
+       ns = item->inScopeNs->list[i];
+       /*
+       * Skip namespaces designated as excluded namespaces
+       * -------------------------------------------------
+       *
+       * XSLT-20 TODO: In XSLT 2.0 we need to keep namespaces
+       *  which are target namespaces of namespace-aliases
+       *  regardless if designated as excluded.
+       *
+       * Exclude the XSLT namespace.
+       */
+       if (xmlStrEqual(ns->href, XSLT_NAMESPACE))
+           goto skip_ns;
+
+       /*
+       * Apply namespace aliasing
+       * ------------------------
+       *
+       * SPEC XSLT 2.0
+       *  "- A namespace node whose string value is a literal namespace
+       *     URI is not copied to the result tree.
+       *   - A namespace node whose string value is a target namespace URI
+       *     is copied to the result tree, whether or not the URI
+       *     identifies an excluded namespace."
+       * 
+       * NOTE: The ns-aliasing machanism is non-cascading.
+       *  (checked with Saxon, Xalan and MSXML .NET).
+       * URGENT TODO: is style->nsAliases the effective list of
+       *  ns-aliases, or do we need to lookup the whole
+       *  import-tree?
+       * TODO: Get rid of import-tree lookup.
+       */
+       if (cctxt->hasNsAliases) {
+           xsltNsAliasPtr alias;
+           /*
+           * First check for being a target namespace.
+           */
+           alias = cctxt->nsAliases;
+           do {
+               /*
+               * TODO: Is xmlns="" handled already?
+               */
+               if ((alias->targetNs != NULL) &&
+                   (xmlStrEqual(alias->targetNs->href, ns->href)))
+               {
+                   /*
+                   * Recognized as a target namespace; use it regardless
+                   * if excluded otherwise.
+                   */
+                   goto add_effective_ns;
+               }
+               alias = alias->next;
+           } while (alias != NULL);
+
+           alias = cctxt->nsAliases;
+           do {
+               /*
+               * TODO: Is xmlns="" handled already?
+               */
+               if ((alias->literalNs != NULL) &&
+                   (xmlStrEqual(alias->literalNs->href, ns->href)))
+               {
+                   /*
+                   * Recognized as an namespace alias; do not use it.
+                   */
+                   goto skip_ns;
+               }
+               alias = alias->next;
+           } while (alias != NULL);
+       }
+       
+       /*
+       * Exclude excluded result namespaces.
+       */
+       if (exclResultNs) {
+           for (j = 0; j < exclResultNs->number; j++)
+               if (xmlStrEqual(ns->href, BAD_CAST exclResultNs->items[j]))
+                   goto skip_ns;
+       }
+       /*
+       * Exclude extension-element namespaces.
+       */
+       if (extElemNs) {
+           for (j = 0; j < extElemNs->number; j++)
+               if (xmlStrEqual(ns->href, BAD_CAST extElemNs->items[j]))
+                   goto skip_ns;
+       }
+
+add_effective_ns:
+       /*
+       * OPTIMIZE TODO: This information may not be needed.
+       */
+       if (isLRE && (elem->nsDef != NULL)) {
+           holdByElem = 0;
+           tmpns = elem->nsDef;
+           do {
+               if (tmpns == ns) {
+                   holdByElem = 1;
+                   break;
+               }
+               tmpns = tmpns->next;
+           } while (tmpns != NULL);        
+       } else
+           holdByElem = 0;
+       
+       
+       /*
+       * Add the effective namespace declaration.
+       */
+       effNs = (xsltEffectiveNsPtr) xmlMalloc(sizeof(xsltEffectiveNs));
+       if (effNs == NULL) {
+           xsltTransformError(NULL, cctxt->style, elem,
+               "Internal error in xsltLREBuildEffectiveNs(): "
+               "failed to allocate memory.\n");
+           cctxt->style->errors++;
+           return(-1);
+       }
+       if (cctxt->psData->effectiveNs == NULL) {
+           cctxt->psData->effectiveNs = effNs;
+           effNs->nextInStore = NULL;   
+       } else {
+           effNs->nextInStore = cctxt->psData->effectiveNs;
+           cctxt->psData->effectiveNs = effNs;
+       }
+
+       effNs->next = NULL;
+       effNs->prefix = ns->prefix;
+       effNs->nsName = ns->href;
+       effNs->holdByElem = holdByElem;
+       
+       if (lastEffNs == NULL)
+           item->effectiveNs = effNs;
+       else
+           lastEffNs->next = effNs;
+       lastEffNs = effNs;
+       
+skip_ns:
+       {}
+    }
+    return(0);
+}
+
+
+/**
+ * xsltLREInfoCreate:
+ *
+ * @isLRE: indicates if the given @elem is a literal result element
+ *
+ * Creates a new info for a literal result element.
+ */
+static int
+xsltLREInfoCreate(xsltCompilerCtxtPtr cctxt,
+                 xmlNodePtr elem,
+                 int isLRE)
+{
+    xsltStyleItemLRElementInfoPtr item;
+
+    if ((cctxt == NULL) || (cctxt->inode == NULL))
+       return(-1);
+
+    item = (xsltStyleItemLRElementInfoPtr)
+       xmlMalloc(sizeof(xsltStyleItemLRElementInfo));
+    if (item == NULL) {
+       xsltTransformError(NULL, cctxt->style, NULL,
+           "Internal error in xsltLREInfoCreate(): "
+           "memory allocation failed.\n");
+       cctxt->style->errors++;
+       return(-1);
+    }
+    memset(item, 0, sizeof(xsltStyleItemLRElementInfo));
+    item->type = XSLT_FUNC_LITERAL_RESULT_ELEMENT;
+    /*
+    * Store it in the stylesheet.
+    */
+    item->next = cctxt->style->preComps;
+    cctxt->style->preComps = (xsltElemPreCompPtr) item;
+    /*
+    * @inScopeNs are used for execution of XPath expressions
+    *  in AVTs.
+    */
+    item->inScopeNs = cctxt->inode->inScopeNs;
+    
+    if (elem)
+       xsltLREBuildEffectiveNsNodes(cctxt, item, elem, isLRE);
+
+    cctxt->inode->litResElemInfo = item;
+    cctxt->inode->nsChanged = 0;
+    cctxt->maxLREs++;
+    return(0);
+}
+
+/**
+ * xsltCompilerVarInfoPush: 
+ * @cctxt: the compilation context
+ * 
+ * Pushes a new var/param info onto the stack.
+ *
+ * Returns the acquired variable info.
+ */ 
+static xsltVarInfoPtr
+xsltCompilerVarInfoPush(xsltCompilerCtxtPtr cctxt,
+                                 xmlNodePtr inst,
+                                 const xmlChar *name,
+                                 const xmlChar *nsName)
+{
+    xsltVarInfoPtr ivar;
+
+    if ((cctxt->ivar != NULL) && (cctxt->ivar->next != NULL)) {
+       ivar = cctxt->ivar->next;
+    } else if ((cctxt->ivar == NULL) && (cctxt->ivars != NULL)) {
+       ivar = cctxt->ivars;
+    } else {
+       ivar = (xsltVarInfoPtr) xmlMalloc(sizeof(xsltVarInfo));
+       if (ivar == NULL) {
+           xsltTransformError(NULL, cctxt->style, inst,
+               "xsltParseInScopeVarPush: xmlMalloc() failed!\n");
+           cctxt->style->errors++;
+           return(NULL);
+       }
+       /* memset(retVar, 0, sizeof(xsltInScopeVar)); */
+       if (cctxt->ivars == NULL) {
+           cctxt->ivars = ivar;
+           ivar->prev = NULL;
+       } else {
+           cctxt->ivar->next = ivar;
+           ivar->prev = cctxt->ivar;
+       }
+       cctxt->ivar = ivar;
+       ivar->next = NULL;
+    }
+    ivar->depth = cctxt->depth;
+    ivar->name = name;
+    ivar->nsName = nsName;
+    return(ivar);
+}
+
+/**
+ * xsltCompilerVarInfoPop: 
+ * @cctxt: the compilation context
+ * 
+ * Pops all var/param infos from the stack, which
+ * have the current depth.
+ */ 
+static void
+xsltCompilerVarInfoPop(xsltCompilerCtxtPtr cctxt)
+{
+
+    while ((cctxt->ivar != NULL) &&
+       (cctxt->ivar->depth > cctxt->depth))
+    {
+       cctxt->ivar = cctxt->ivar->prev;
+    }
+}
+
+/*
+* xsltCompilerNodePush:
+*
+* @cctxt: the compilation context
+* @node: the node to be pushed (this can also be the doc-node)
+*
+* Returns the current node info structure or
+*         NULL in case of an internal error.
+*/
+xsltCompilerNodeInfoPtr
+xsltCompilerNodePush(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
+{    
+    xsltCompilerNodeInfoPtr inode, iprev;
+
+    if ((cctxt->inode != NULL) && (cctxt->inode->next != NULL)) {      
+       inode = cctxt->inode->next;
+    } else if ((cctxt->inode == NULL) && (cctxt->inodeList != NULL)) {
+       inode = cctxt->inodeList;       
+    } else {
+       /*
+       * Create a new node-info.
+       */
+       inode = (xsltCompilerNodeInfoPtr)
+           xmlMalloc(sizeof(xsltCompilerNodeInfo));
+       if (inode == NULL) {
+           xsltTransformError(NULL, cctxt->style, NULL,
+               "xsltCompilerNodePush: malloc failed.\n");
+           return(NULL);
+       }
+       memset(inode, 0, sizeof(xsltCompilerNodeInfo));
+       if (cctxt->inodeList == NULL)
+           cctxt->inodeList = inode;
+       else {
+           cctxt->inodeLast->next = inode;
+           inode->prev = cctxt->inodeLast;
+       }
+       cctxt->inodeLast = inode;
+       cctxt->maxNodeInfos++;  
+       if (cctxt->inode == NULL) {
+           cctxt->inode = inode;
+           /*
+           * Create an initial literal result element info for
+           * the root of the stylesheet.
+           */
+           xsltLREInfoCreate(cctxt, NULL, 0);
+       } 
+    }       
+    cctxt->depth++;
+    cctxt->inode = inode;
+    /*
+    * REVISIT TODO: Keep the reset always complete.    
+    * NOTE: Be carefull with the @node, since it might be
+    *  a doc-node.
+    */
+    inode->node = node;
+    inode->depth = cctxt->depth;
+    inode->templ = NULL;
+    inode->category = XSLT_ELEMENT_CATEGORY_XSLT;
+    inode->type = 0;
+    inode->item = NULL;
+    inode->curChildType = 0;
+    inode->extContentHandled = 0;
+    inode->isRoot = 0;
+    
+    if (inode->prev != NULL) {
+       iprev = inode->prev;
+       /*
+       * Inherit the following information:
+       * ---------------------------------
+       *
+       * In-scope namespaces
+       */
+       inode->inScopeNs = iprev->inScopeNs;
+       /*
+       * Info for literal result elements
+       */
+       inode->litResElemInfo = iprev->litResElemInfo;
+       inode->nsChanged = iprev->nsChanged;
+       /*
+       * Excluded result namespaces
+       */
+       inode->exclResultNs = iprev->exclResultNs;
+       /*
+       * Extension instruction namespaces
+       */
+       inode->extElemNs = iprev->extElemNs;
+       /*
+       * Whitespace preservation
+       */
+       inode->preserveWhitespace = iprev->preserveWhitespace;
+       /*
+       * Forwards-compatible mode
+       */
+       inode->forwardsCompat = iprev->forwardsCompat;  
+    } else {
+       inode->inScopeNs = NULL;
+       inode->exclResultNs = NULL;
+       inode->extElemNs = NULL;
+       inode->preserveWhitespace = 0;
+       inode->forwardsCompat = 0;
+    }
+    
+    return(inode);
+}
+
+/*
+* xsltCompilerNodePop:
+*
+* @cctxt: the compilation context
+* @node: the node to be pushed (this can also be the doc-node)
+*
+* Pops the current node info.
+*/
+static void
+xsltCompilerNodePop(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
+{    
+    if (cctxt->inode == NULL) {
+       xmlGenericError(xmlGenericErrorContext,
+           "xsltCompilerNodePop: Top-node mismatch.\n");
+       return;
+    }
+    /*
+    * NOTE: Be carefull with the @node, since it might be
+    *  a doc-node.
+    */
+    if (cctxt->inode->node != node) {
+       xmlGenericError(xmlGenericErrorContext,
+       "xsltCompilerNodePop: Node mismatch.\n");
+       goto mismatch;
+    }
+    if (cctxt->inode->depth != cctxt->depth) {
+       xmlGenericError(xmlGenericErrorContext,
+       "xsltCompilerNodePop: Depth mismatch.\n");
+       goto mismatch;
+    }
+    /*
+    * Pop information of variables.
+    */
+    if ((cctxt->ivar) && (cctxt->ivar->depth > cctxt->depth))
+       xsltCompilerVarInfoPop(cctxt);
+
+    cctxt->depth--;
+    cctxt->inode = cctxt->inode->prev;
+    if (cctxt->inode != NULL)
+       cctxt->inode->curChildType = 0;
+    return;
+
+mismatch:
+    {
+       const xmlChar *nsName = NULL, *name = NULL;
+       const xmlChar *infnsName = NULL, *infname = NULL;
+       
+       if (node) {
+           if (node->type == XML_ELEMENT_NODE) {
+               name = node->name;
+               if (node->ns != NULL)
+                   nsName = node->ns->href;
+               else
+                   nsName = BAD_CAST "";
+           } else {
+               name = BAD_CAST "#document";
+               nsName = BAD_CAST "";
+           }
+       } else
+           name = BAD_CAST "Not given";
+
+       if (cctxt->inode->node) {
+           if (node->type == XML_ELEMENT_NODE) {
+               infname = cctxt->inode->node->name;
+               if (cctxt->inode->node->ns != NULL)
+                   infnsName = cctxt->inode->node->ns->href;
+               else
+                   infnsName = BAD_CAST "";
+           } else {
+               infname = BAD_CAST "#document";
+               infnsName = BAD_CAST "";
+           }
+       } else
+           infname = BAD_CAST "Not given";
+
+       
+       xmlGenericError(xmlGenericErrorContext,
+           "xsltCompilerNodePop: Given   : '%s' URI '%s'\n",
+           name, nsName);
+       xmlGenericError(xmlGenericErrorContext,
+           "xsltCompilerNodePop: Expected: '%s' URI '%s'\n",
+           infname, infnsName);
+    }
+}
+
+/*
+* xsltCompilerBuildInScopeNsList:
+*
+* Create and store the list of in-scope namespaces for the given
+* node in the stylesheet. If there are no changes in the in-scope
+* namespaces then the last ns-info of the ancestor axis will be returned.
+* Compilation-time only.
+*
+* Returns the ns-info or NULL if there are no namespaces in scope.
+*/
+static xsltNsListContainerPtr
+xsltCompilerBuildInScopeNsList(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
+{
+    xsltNsListContainerPtr nsi = NULL;
+    xmlNsPtr *list = NULL, ns;
+    int i, maxns = 5;
+    /*
+    * Create a new ns-list for this position in the node-tree.
+    * xmlGetNsList() will return NULL, if there are no ns-decls in the
+    * tree. Note that the ns-decl for the XML namespace is not added
+    * to the resulting list; the XPath module handles the XML namespace
+    * internally.
+    */
+    while (node != NULL) {
+        if (node->type == XML_ELEMENT_NODE) {
+            ns = node->nsDef;
+            while (ns != NULL) {
+                if (nsi == NULL) {
+                   nsi = (xsltNsListContainerPtr)
+                       xmlMalloc(sizeof(xsltNsListContainer));
+                   if (nsi == NULL) {
+                       xsltTransformError(NULL, cctxt->style, NULL,
+                           "xsltCompilerBuildInScopeNsList: "
+                           "malloc failed!\n");
+                       goto internal_err;
+                   }
+                   memset(nsi, 0, sizeof(xsltNsListContainer));
+                    nsi->list =
+                        (xmlNsPtr *) xmlMalloc(maxns * sizeof(xmlNsPtr));
+                    if (nsi->list == NULL) {
+                       xsltTransformError(NULL, cctxt->style, NULL,
+                           "xsltCompilerBuildInScopeNsList: "
+                           "malloc failed!\n");
+                       goto internal_err;
+                    }
+                    nsi->list[0] = NULL;
+                }
+               /*
+               * Skip shadowed namespace bindings.
+               */
+                for (i = 0; i < nsi->totalNumber; i++) {
+                    if ((ns->prefix == nsi->list[i]->prefix) ||
+                        (xmlStrEqual(ns->prefix, nsi->list[i]->prefix)))
+                   break;
+                }
+                if (i >= nsi->totalNumber) {
+                    if (nsi->totalNumber +1 >= maxns) {
+                        maxns *= 2;
+                       nsi->list =
+                           (xmlNsPtr *) xmlRealloc(nsi->list,
+                               maxns * sizeof(xmlNsPtr));
+                        if (nsi->list == NULL) {
+                            xsltTransformError(NULL, cctxt->style, NULL,
+                               "xsltCompilerBuildInScopeNsList: "
+                               "realloc failed!\n");
+                               goto internal_err;
+                        }
+                    }
+                    nsi->list[nsi->totalNumber++] = ns;
+                    nsi->list[nsi->totalNumber] = NULL;
+                }
+
+                ns = ns->next;
+            }
+        }
+        node = node->parent;
+    }
+    if (nsi == NULL)
+       return(NULL);
+    /*
+    * Move the default namespace to last position.
+    */
+    nsi->xpathNumber = nsi->totalNumber;
+    for (i = 0; i < nsi->totalNumber; i++) {
+       if (nsi->list[i]->prefix == NULL) {
+           ns = nsi->list[i];
+           nsi->list[i] = nsi->list[nsi->totalNumber-1];
+           nsi->list[nsi->totalNumber-1] = ns;
+           nsi->xpathNumber--;
+           break;
+       }
+    }
+    /*
+    * Store the ns-list in the stylesheet.
+    */
+    if (xsltPointerListAddSize(
+       (xsltPointerListPtr)cctxt->psData->inScopeNamespaces,
+       (void *) nsi, 5) == -1)
+    {  
+       xmlFree(nsi);
+       nsi = NULL;
+       xsltTransformError(NULL, cctxt->style, NULL,
+           "xsltCompilerBuildInScopeNsList: failed to add ns-info.\n");
+       goto internal_err;
+    }
+    /*
+    * Notify of change in status wrt namespaces.
+    */
+    if (cctxt->inode != NULL)
+       cctxt->inode->nsChanged = 1;
+
+    return(nsi);
+
+internal_err:
+    if (list != NULL)
+       xmlFree(list);    
+    cctxt->style->errors++;
+    return(NULL);
+}
+
+static int
+xsltParseNsPrefixList(xsltCompilerCtxtPtr cctxt,
+                     xsltPointerListPtr list,
+                     xmlNodePtr node,
+                     const xmlChar *value)
+{
+    xmlChar *cur, *end;
+    xmlNsPtr ns;
+    
+    if ((cctxt == NULL) || (value == NULL) || (list == NULL))
+       return(-1);
+
+    list->number = 0;
+
+    cur = (xmlChar *) value;
+    while (*cur != 0) {
+       while (IS_BLANK(*cur)) cur++;
+       if (*cur == 0)
+           break;
+       end = cur;
+       while ((*end != 0) && (!IS_BLANK(*end))) end++;
+       cur = xmlStrndup(cur, end - cur);
+       if (cur == NULL) {
+           cur = end;
+           continue;
+       }               
+       /*
+       * TODO: Export and use xmlSearchNsByPrefixStrict()
+       *   in Libxml2, tree.c, since xmlSearchNs() is in most
+       *   cases not efficient and in some cases not correct.
+       *
+       * XSLT-2 TODO: XSLT 2.0 allows an additional "#all" value.
+       */
+       if ((cur[0] == '#') &&
+           xmlStrEqual(cur, (const xmlChar *)"#default"))
+           ns = xmlSearchNs(cctxt->style->doc, node, NULL);
+       else
+           ns = xmlSearchNs(cctxt->style->doc, node, cur);         
+
+       if (ns == NULL) {
+           /*
+           * TODO: Better to report the attr-node, otherwise
+           *  the user won't know which attribute was invalid.
+           */
+           xsltTransformError(NULL, cctxt->style, node,
+               "No namespace binding in scope for prefix '%s'.\n", cur);
+           /*
+           * XSLT-1.0: "It is an error if there is no namespace
+           *  bound to the prefix on the element bearing the
+           *  exclude-result-prefixes or xsl:exclude-result-prefixes
+           *  attribute."
+           */
+           cctxt->style->errors++;
+       } else {
+#ifdef WITH_XSLT_DEBUG_PARSING
+           xsltGenericDebug(xsltGenericDebugContext,
+               "resolved prefix '%s'\n", cur);
+#endif
+           /*
+           * Note that we put the namespace name into the dict.
+           */
+           if (xsltPointerListAddSize(list,
+               (void *) xmlDictLookup(cctxt->style->dict,
+               ns->href, -1), 5) == -1)
+           {
+               xmlFree(cur);
+               goto internal_err;
+           }
+       }
+       xmlFree(cur);
+               
+       cur = end;
+    }
+    return(0);
+
+internal_err:
+    cctxt->style->errors++;
+    return(-1);
+}
+
+/**
+ * xsltCompilerUtilsCreateMergedList:
+ * @dest: the destination list (optional)
+ * @first: the first list
+ * @second: the second list (optional)
+ *
+ * Appends the content of @second to @first into @destination.
+ * If @destination is NULL a new list will be created.
+ *
+ * Returns the merged list of items or NULL if there's nothing to merge.
+ */
+static xsltPointerListPtr
+xsltCompilerUtilsCreateMergedList(xsltPointerListPtr first,
+                           xsltPointerListPtr second)
+{
+    xsltPointerListPtr ret;
+    size_t num;
+
+    if (first)
+       num = first->number;
+    else
+       num = 0;
+    if (second)
+       num += second->number;    
+    if (num == 0)
+       return(NULL);
+    ret = xsltPointerListCreate(num);
+    if (ret == NULL)
+       return(NULL);
+    /*
+    * Copy contents.
+    */
+    if ((first != NULL) &&  (first->number != 0)) {
+       memcpy(ret->items, first->items,
+           first->number * sizeof(void *));
+       if ((second != NULL) && (second->number != 0))
+           memcpy(ret->items + first->number, second->items,
+               second->number * sizeof(void *));
+    } else if ((second != NULL) && (second->number != 0))
+       memcpy(ret->items, (void *) second->items,
+           second->number * sizeof(void *));
+    ret->number = num;
+    return(ret);
+}
+
+/*
+* xsltParseExclResultPrefixes:
+*
+* Create and store the list of in-scope namespaces for the given
+* node in the stylesheet. If there are no changes in the in-scope
+* namespaces then the last ns-info of the ancestor axis will be returned.
+* Compilation-time only.
+*
+* Returns the ns-info or NULL if there are no namespaces in scope.
+*/
+static xsltPointerListPtr
+xsltParseExclResultPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
+                           xsltPointerListPtr def,
+                           int instrCategory)
+{    
+    xsltPointerListPtr list = NULL;
+    xmlChar *value;
+    xmlAttrPtr attr;
+
+    if ((cctxt == NULL) || (node == NULL))
+       return(NULL);
+
+    if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)
+       attr = xmlHasNsProp(node, BAD_CAST "exclude-result-prefixes", NULL);
+    else
+       attr = xmlHasNsProp(node, BAD_CAST "exclude-result-prefixes",
+           XSLT_NAMESPACE);
+    if (attr == NULL)  
+       return(def);
+
+    if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {
+       /*
+       * Mark the XSLT attr.
+       */
+       attr->psvi = (void *) xsltXSLTAttrMarker;
+    }
+
+    if ((attr->children != NULL) &&    
+       (attr->children->content != NULL))
+       value = attr->children->content;
+    else {
+       xsltTransformError(NULL, cctxt->style, node,
+           "Attribute 'exclude-result-prefixes': Invalid value.\n");
+       cctxt->style->errors++;
+       return(def);
+    }        
+
+    if (xsltParseNsPrefixList(cctxt, cctxt->tmpList, node,
+       BAD_CAST value) != 0)
+       goto exit;
+    if (cctxt->tmpList->number == 0)   
+       goto exit;    
+    /*
+    * Merge the list with the inherited list.
+    */
+    list = xsltCompilerUtilsCreateMergedList(def, cctxt->tmpList);
+    if (list == NULL)
+       goto exit;    
+    /*
+    * Store the list in the stylesheet/compiler context.
+    */
+    if (xsltPointerListAddSize(
+       cctxt->psData->exclResultNamespaces, list, 5) == -1)
+    {
+       xsltPointerListFree(list);
+       list = NULL;
+       goto exit;
+    }
+    /*
+    * Notify of change in status wrt namespaces.
+    */
+    if (cctxt->inode != NULL)
+       cctxt->inode->nsChanged = 1;
+
+exit:    
+    if (list != NULL)
+       return(list);
+    else
+       return(def);
+}
+
+/*
+* xsltParseExtElemPrefixes:
+*
+* Create and store the list of in-scope namespaces for the given
+* node in the stylesheet. If there are no changes in the in-scope
+* namespaces then the last ns-info of the ancestor axis will be returned.
+* Compilation-time only.
+*
+* Returns the ns-info or NULL if there are no namespaces in scope.
+*/
+static xsltPointerListPtr
+xsltParseExtElemPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
+                        xsltPointerListPtr def,
+                        int instrCategory)
+{    
+    xsltPointerListPtr list = NULL;
+    xmlAttrPtr attr;
+    xmlChar *value;
+    int i;
+
+    if ((cctxt == NULL) || (node == NULL))
+       return(NULL);
+
+    if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)
+       attr = xmlHasNsProp(node, BAD_CAST "extension-element-prefixes", NULL);
+    else
+       attr = xmlHasNsProp(node, BAD_CAST "extension-element-prefixes",
+           XSLT_NAMESPACE);
+    if (attr == NULL)  
+       return(def);
+
+    if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {
+       /*
+       * Mark the XSLT attr.
+       */
+       attr->psvi = (void *) xsltXSLTAttrMarker;
+    }
+
+    if ((attr->children != NULL) &&    
+       (attr->children->content != NULL))
+       value = attr->children->content;
+    else {
+       xsltTransformError(NULL, cctxt->style, node,
+           "Attribute 'extension-element-prefixes': Invalid value.\n");
+       cctxt->style->errors++;
+       return(def);
+    }
+
+
+    if (xsltParseNsPrefixList(cctxt, cctxt->tmpList, node,
+       BAD_CAST value) != 0)
+       goto exit;
+
+    if (cctxt->tmpList->number == 0)
+       goto exit;    
+    /*
+    * REVISIT: Register the extension namespaces.
+    */
+    for (i = 0; i < cctxt->tmpList->number; i++)
+       xsltRegisterExtPrefix(cctxt->style, NULL,
+       BAD_CAST cctxt->tmpList->items[i]);
+    /*
+    * Merge the list with the inherited list.
+    */
+    list = xsltCompilerUtilsCreateMergedList(def, cctxt->tmpList);
+    if (list == NULL)
+       goto exit;
+    /*
+    * Store the list in the stylesheet.
+    */
+    if (xsltPointerListAddSize(
+       cctxt->psData->extElemNamespaces, list, 5) == -1)
+    {
+       xsltPointerListFree(list);
+       list = NULL;
+       goto exit;
+    }
+    /*
+    * Notify of change in status wrt namespaces.
+    */
+    if (cctxt->inode != NULL)
+       cctxt->inode->nsChanged = 1;
+
+exit:    
+    if (list != NULL)
+       return(list);
+    else
+       return(def);
+}
+
+/*
+* xsltParseAttrXSLTVersion:
+*
+* @cctxt: the compilation context
+* @node: the element-node
+* @isXsltElem: whether this is an XSLT element
+*
+* Parses the attribute xsl:version.
+*
+* Returns 1 if there was such an attribute, 0 if not and
+*         -1 if an internal or API error occured.
+*/
+static int
+xsltParseAttrXSLTVersion(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,                    
+                        int instrCategory)
+{
+    xmlChar *value;
+    xmlAttrPtr attr;
+
+    if ((cctxt == NULL) || (node == NULL))
+       return(-1);
+
+    if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)
+       attr = xmlHasNsProp(node, BAD_CAST "version", NULL);
+    else
+       attr = xmlHasNsProp(node, BAD_CAST "version", XSLT_NAMESPACE);
+
+    if (attr == NULL)  
+       return(0);
+
+    attr->psvi = (void *) xsltXSLTAttrMarker;
+
+    if ((attr->children != NULL) &&    
+       (attr->children->content != NULL))
+       value = attr->children->content;
+    else {
+       xsltTransformError(NULL, cctxt->style, node,
+           "Attribute 'version': Invalid value.\n");
+       cctxt->style->errors++;
+       return(1);
+    }
+    
+    if (! xmlStrEqual(value, (const xmlChar *)"1.0")) {
+       cctxt->inode->forwardsCompat = 1;
+       /*
+       * TODO: To what extent do we support the
+       *  forwards-compatible mode?
+       */
+       /*
+       * Report this only once per compilation episode.
+       */
+       if (! cctxt->hasForwardsCompat) {
+           cctxt->hasForwardsCompat = 1;
+           cctxt->errSeverity = XSLT_ERROR_SEVERITY_WARNING;
+           xsltTransformError(NULL, cctxt->style, node,
+               "Warning: the attribute xsl:version specifies a value "
+               "different from '1.0'. Switching to forwards-compatible "
+               "mode. Only features of XSLT 1.0 are supported by this "
+               "processor.\n");
+           cctxt->style->warnings++;
+           cctxt->errSeverity = XSLT_ERROR_SEVERITY_ERROR;
+       }       
+    } else {
+       cctxt->inode->forwardsCompat = 0;
+    }
+
+    if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {
+       /*
+       * Set a marker on XSLT attributes.
+       */
+       attr->psvi = (void *) xsltXSLTAttrMarker;
+    }
+    return(1);
+}
+
+static int
+xsltParsePreprocessStylesheetTree(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
+{
+    xmlNodePtr deleteNode, cur, txt, textNode = NULL;
+    xmlDocPtr doc;
+    xsltStylesheetPtr style;
+    int internalize = 0, findSpaceAttr;
+    int xsltStylesheetElemDepth;
+    xmlAttrPtr attr;
+    xmlChar *value;
+    const xmlChar *name, *nsNameXSLT = NULL;
+    int strictWhitespace, inXSLText = 0;
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+    xsltNsMapPtr nsMapItem;
+#endif
+
+    if ((cctxt == NULL) || (cctxt->style == NULL) ||
+       (node == NULL) || (node->type != XML_ELEMENT_NODE))
+        return(-1);
+
+    doc = node->doc;
+    if (doc == NULL)
+       goto internal_err;
+
+    style = cctxt->style;
+    if ((style->dict != NULL) && (doc->dict == style->dict))
+       internalize = 1;
+    else
+        style->internalized = 0;
+
+    /*
+    * Init value of xml:space. Since this might be an embedded
+    * stylesheet, this is needed to be performed on the element
+    * where the stylesheet is rooted at, taking xml:space of
+    * ancestors into account.
+    */
+    if (! cctxt->simplified)
+       xsltStylesheetElemDepth = cctxt->depth +1;
+    else
+       xsltStylesheetElemDepth = 0;
+
+    if (xmlNodeGetSpacePreserve(node) != 1)
+       cctxt->inode->preserveWhitespace = 0;
+    else
+       cctxt->inode->preserveWhitespace = 1; 
+    
+    /*
+    * Eval if we should keep the old incorrect behaviour.
+    */
+    strictWhitespace = (cctxt->strict != 0) ? 1 : 0;
+
+    nsNameXSLT = xsltConstNamespaceNameXSLT;
+
+    deleteNode = NULL;
+    cur = node;
+    while (cur != NULL) {
+       if (deleteNode != NULL) {
+
+#ifdef WITH_XSLT_DEBUG_BLANKS
+           xsltGenericDebug(xsltGenericDebugContext,
+            "xsltParsePreprocessStylesheetTree: removing node\n");
+#endif
+           xmlUnlinkNode(deleteNode);
+           xmlFreeNode(deleteNode);
+           deleteNode = NULL;
+       }
+       if (cur->type == XML_ELEMENT_NODE) {
+           
+           /*
+           * Clear the PSVI field.
+           */
+           cur->psvi = NULL;
+
+           xsltCompilerNodePush(cctxt, cur);
+
+           inXSLText = 0;
+           textNode = NULL;        
+           findSpaceAttr = 1;      
+           cctxt->inode->stripWhitespace = 0;
+           /*
+           * TODO: I'd love to use a string pointer comparison here :-/
+           */
+           if (IS_XSLT_ELEM(cur)) {
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+               if (cur->ns->href != nsNameXSLT) {
+                   nsMapItem = xsltNewNamespaceMapItem(cctxt,
+                       doc, cur->ns, cur);
+                   if (nsMapItem == NULL)
+                       goto internal_err;
+                   cur->ns->href = nsNameXSLT;
+               }
+#endif
+
+               if (cur->name == NULL)
+                   goto process_attributes;
+               /*
+               * Mark the XSLT element for later recognition.
+               * TODO: Using the marker is still too dangerous, since if
+               *   the parsing mechanism leaves out an XSLT element, then
+               *   this might hit the transformation-mechanism, which
+               *   will break if it doesn't expect such a marker.
+               */
+               /* cur->psvi = (void *) xsltXSLTElemMarker; */
+
+               /*
+               * XSLT 2.0: "Any whitespace text node whose parent is
+               * one of the following elements is removed from the "
+               * tree, regardless of any xml:space attributes:..."
+               * xsl:apply-imports, 
+               * xsl:apply-templates,
+               * xsl:attribute-set,
+               * xsl:call-template, 
+               * xsl:choose,
+               * xsl:stylesheet, xsl:transform.
+               * XSLT 2.0: xsl:analyze-string,
+               *           xsl:character-map,
+               *           xsl:next-match              
+               *
+               * TODO: I'd love to use a string pointer comparison here :-/
+               */              
+               name = cur->name;
+               switch (*name) {
+                   case 't':
+                       if ((name[0] == 't') && (name[1] == 'e') &&
+                           (name[2] == 'x') && (name[3] == 't') &&
+                           (name[4] == 0))
+                       {
+                           /*
+                           * Process the xsl:text element.
+                           * ----------------------------
+                           * Mark it for later recognition.
+                           */
+                           cur->psvi = (void *) xsltXSLTTextMarker;
+                           /*
+                           * For stylesheets, the set of
+                           * whitespace-preserving element names
+                           * consists of just xsl:text.
+                           */
+                           findSpaceAttr = 0;
+                           cctxt->inode->preserveWhitespace = 1;
+                           inXSLText = 1;
+                       }                           
+                       break;
+                   case 'c':
+                       if (xmlStrEqual(name, BAD_CAST "choose") ||
+                           xmlStrEqual(name, BAD_CAST "call-template"))
+                           cctxt->inode->stripWhitespace = 1;
+                       break;
+                   case 'a':
+                       if (xmlStrEqual(name, BAD_CAST "apply-templates") ||
+                           xmlStrEqual(name, BAD_CAST "apply-imports") ||
+                           xmlStrEqual(name, BAD_CAST "attribute-set"))
+
+                           cctxt->inode->stripWhitespace = 1;
+                       break;
+                   default:
+                       if (xsltStylesheetElemDepth == cctxt->depth) {
+                           /*
+                           * This is a xsl:stylesheet/xsl:transform.
+                           */
+                           cctxt->inode->stripWhitespace = 1;
+                           break;
+                       }
+
+                       if ((cur->prev != NULL) &&
+                           (cur->prev->type == XML_TEXT_NODE))
+                       {
+                           /*
+                           * XSLT 2.0 : "Any whitespace text node whose
+                           *  following-sibling node is an xsl:param or
+                           *  xsl:sort element is removed from the tree,
+                           *  regardless of any xml:space attributes."
+                           */
+                           if (((*name == 'p') || (*name == 's')) &&
+                               (xmlStrEqual(name, BAD_CAST "param") ||
+                                xmlStrEqual(name, BAD_CAST "sort")))
+                           {
+                               do {
+                                   if (IS_BLANK_NODE(cur->prev)) {
+                                       txt = cur->prev;
+                                       xmlUnlinkNode(txt);
+                                       xmlFreeNode(txt);
+                                   } else {
+                                       /*
+                                       * This will result in a content
+                                       * error, when hitting the parsing
+                                       * functions.
+                                       */
+                                       break;
+                                   }
+                               } while (cur->prev);                                
+                           }
+                       }
+                       break;
+               }
+           }
+
+process_attributes:
+           /*
+           * Process attributes.
+           * ------------------
+           */
+           if (cur->properties != NULL) {
+               if (cur->children == NULL)
+                   findSpaceAttr = 0;
+               attr = cur->properties;
+               do {
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+                   if ((attr->ns) && (attr->ns->href != nsNameXSLT) &&
+                       xmlStrEqual(attr->ns->href, nsNameXSLT))
+                   {                   
+                       nsMapItem = xsltNewNamespaceMapItem(cctxt,
+                           doc, attr->ns, cur);
+                       if (nsMapItem == NULL)
+                           goto internal_err;
+                       attr->ns->href = nsNameXSLT;
+                   }               
+#endif
+                   if (internalize) {
+                       /*
+                       * Internalize the attribute's value; the goal is to
+                       * speed up operations and minimize used space by
+                       * compiled stylesheets.
+                       */
+                       txt = attr->children;
+                       /*
+                       * NOTE that this assumes only one
+                       *  text-node in the attribute's content.
+                       */
+                       if ((txt != NULL) && (txt->content != NULL) &&
+                           (!xmlDictOwns(style->dict, txt->content)))
+                       {
+                           value = (xmlChar *) xmlDictLookup(style->dict,
+                               txt->content, -1);
+                           xmlNodeSetContent(txt, NULL);
+                           txt->content = value;
+                       }
+                   }
+                   /*
+                   * Process xml:space attributes.
+                   * ----------------------------
+                   */
+                   if ((findSpaceAttr != 0) &&
+                       (attr->ns != NULL) &&
+                       (attr->name != NULL) &&
+                       (attr->name[0] == 's') &&                       
+                       (attr->ns->prefix != NULL) &&
+                       (attr->ns->prefix[0] == 'x') &&
+                       (attr->ns->prefix[1] == 'm') &&
+                       (attr->ns->prefix[2] == 'l') &&
+                       (attr->ns->prefix[3] == 0))
+                   {
+                       value = xmlGetNsProp(cur, BAD_CAST "space",
+                           XML_XML_NAMESPACE);
+                       if (value != NULL) {
+                           if (xmlStrEqual(value, BAD_CAST "preserve")) {
+                               cctxt->inode->preserveWhitespace = 1;                           
+                           } else if (xmlStrEqual(value, BAD_CAST "default")) {
+                               cctxt->inode->preserveWhitespace = 0;
+                           } else {
+                               /* Invalid value for xml:space. */
+                               xsltTransformError(NULL, style, cur,
+                                   "Attribute xml:space: Invalid value.\n");
+                               cctxt->style->warnings++;
+                           }
+                           findSpaceAttr = 0;
+                           xmlFree(value);
+                       }
+                       
+                   }
+                   attr = attr->next;
+               } while (attr != NULL);
+           }
+           /*
+           * We'll descend into the children of element nodes only.
+           */
+           if (cur->children != NULL) {
+               cur = cur->children;
+               continue;
+           }
+       } else if ((cur->type == XML_TEXT_NODE) ||
+               (cur->type == XML_CDATA_SECTION_NODE))
+       {
+           /*
+           * Merge adjacent text/CDATA-section-nodes
+           * ---------------------------------------       
+           * In order to avoid breaking of existing stylesheets,
+           * if the old behaviour is wanted (strictWhitespace == 0),
+           * then we *won't* merge adjacent text-nodes
+           * (except in xsl:text); this will ensure that whitespace-only
+           * text nodes are (incorrectly) not stripped in some cases.
+           * 
+           * Example:               : <foo>  <!-- bar -->zoo</foo>
+           * Corrent (strict) result: <foo>  zoo</foo>
+           * Incorrect (old) result : <foo>zoo</foo>
+           *    
+           * NOTE that we *will* merge adjacent text-nodes if
+           * they are in xsl:text.
+           * Example, the following:
+           * <xsl:text>  <!-- bar -->zoo<xsl:text>
+           * will result in both cases in:
+           * <xsl:text>  zoo<xsl:text>
+           */
+           cur->type = XML_TEXT_NODE;
+           if ((strictWhitespace != 0) || (inXSLText != 0)) {
+               /*
+               * New behaviour; merge nodes.
+               */
+               if (textNode == NULL)
+                   textNode = cur;
+               else {
+                   if (cur->content != NULL)
+                       xmlNodeAddContent(textNode, cur->content);
+                   deleteNode = cur;
+               }
+               if ((cur->next == NULL) ||
+                   (cur->next->type == XML_ELEMENT_NODE))
+                   goto end_of_text;
+               else
+                   goto next_sibling;
+           } else {
+               /*
+               * Old behaviour.
+               */
+               if (textNode == NULL)
+                   textNode = cur;
+               goto end_of_text;
+           }              
+       } else if ((cur->type == XML_COMMENT_NODE) ||
+           (cur->type == XML_PI_NODE))
+       {           
+           /*
+           * Remove processing instructions and comments.
+           */
+           deleteNode = cur;
+           if ((cur->next == NULL) ||
+               (cur->next->type == XML_ELEMENT_NODE))
+               goto end_of_text;
+           else
+               goto next_sibling;
+       } else {
+           textNode = NULL;
+           /*
+           * Invalid node-type for this data-model.
+           */
+           xsltTransformError(NULL, style, cur,
+               "Invalid type of node for the XSLT data model.\n");
+           cctxt->style->errors++;
+           goto next_sibling;
+       }
+
+end_of_text:
+       if (textNode) {
+           value = textNode->content;
+           /*
+           * At this point all adjacent text/CDATA-section nodes
+           * have been merged.
+           *
+           * Strip whitespace-only text-nodes.
+           * (cctxt->inode->stripWhitespace)
+           */
+           if ((value == NULL) || (*value == 0) ||
+               (((cctxt->inode->stripWhitespace) ||
+                 (! cctxt->inode->preserveWhitespace)) &&
+                IS_BLANK(*value) &&
+                xsltIsBlank(value)))
+           {           
+               if (textNode != cur) {
+                   xmlUnlinkNode(textNode);
+                   xmlFreeNode(textNode);
+               } else
+                   deleteNode = textNode;
+               textNode = NULL;
+               goto next_sibling;
+           }
+           /*
+           * Convert CDATA-section nodes to text-nodes.
+           * TODO: Can this produce problems?
+           */
+           if (textNode->type != XML_TEXT_NODE) {
+               textNode->type = XML_TEXT_NODE;
+               textNode->name = xmlStringText;
+           }
+           if (internalize &&
+               (textNode->content != NULL) &&
+               (!xmlDictOwns(style->dict, textNode->content)))
+           {
+               /*
+               * Internalize the string.
+               */
+               value = (xmlChar *) xmlDictLookup(style->dict,
+                   textNode->content, -1);
+               xmlNodeSetContent(textNode, NULL);
+               textNode->content = value;
+           }
+           textNode = NULL;
+           /*
+           * Note that "disable-output-escaping" of the xsl:text
+           * element will be applied at a later level, when
+           * XSLT elements are processed.
+           */
+       }
+
+next_sibling:
+       if (cur->type == XML_ELEMENT_NODE) {
+           xsltCompilerNodePop(cctxt, cur);
+       }
+       if (cur == node)
+           break;
+       if (cur->next != NULL) {
+           cur = cur->next;
+       } else {
+           cur = cur->parent;
+           inXSLText = 0;
+           goto next_sibling;
+       };
+    }
+    if (deleteNode != NULL) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+       xsltGenericDebug(xsltGenericDebugContext,
+        "xsltParsePreprocessStylesheetTree: removing node\n");
+#endif
+       xmlUnlinkNode(deleteNode);
+       xmlFreeNode(deleteNode);
+    }
+    return(0);
+
+internal_err:
+    return(-1);
+}
+
+#endif /* XSLT_REFACTORED */
+
+#ifdef XSLT_REFACTORED
+#else
+static void
+xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
+{
+    xmlNodePtr deleteNode;
+    int internalize = 0;
+
+    if ((style == NULL) || (cur == NULL))
+        return;
+
+    if ((cur->doc != NULL) && (style->dict != NULL) &&
+        (cur->doc->dict == style->dict))
+       internalize = 1;
+    else
+        style->internalized = 0;
+    /*
+     * This content comes from the stylesheet
+     * For stylesheets, the set of whitespace-preserving
+     * element names consists of just xsl:text.
+     */
+    deleteNode = NULL;
+    while (cur != NULL) {
+       if (deleteNode != NULL) {
+#ifdef WITH_XSLT_DEBUG_BLANKS
+           xsltGenericDebug(xsltGenericDebugContext,
+            "xsltPrecomputeStylesheet: removing ignorable blank node\n");
+#endif
+           xmlUnlinkNode(deleteNode);
+           xmlFreeNode(deleteNode);
+           deleteNode = NULL;
+       }
+       if (cur->type == XML_ELEMENT_NODE) {
+           int exclPrefixes;
+           /*
+            * Internalize attributes values.
+            */
+           if ((internalize) && (cur->properties != NULL)) {
+               xmlAttrPtr attr = cur->properties;
+               xmlNodePtr txt;
+
+               while (attr != NULL) {
+                   txt = attr->children;
+                   if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
+                       (txt->content != NULL) &&
+                       (!xmlDictOwns(style->dict, txt->content)))
+                   {
+                       xmlChar *tmp;
+
+                       /*
+                        * internalize the text string, goal is to speed
+                        * up operations and minimize used space by compiled
+                        * stylesheets.
+                        */
+                       tmp = (xmlChar *) xmlDictLookup(style->dict,
+                                                       txt->content, -1);
+                       if (tmp != txt->content) {
+                           xmlNodeSetContent(txt, NULL);
+                           txt->content = tmp;
+                       }
+                   }
+                   attr = attr->next;
+               }
+           }
+           if (IS_XSLT_ELEM(cur)) {
+               exclPrefixes = 0;
+               xsltStylePreCompute(style, cur);
+               if (IS_XSLT_NAME(cur, "text")) {
+                   for (;exclPrefixes > 0;exclPrefixes--)
+                       exclPrefixPop(style);
+                   goto skip_children;
+               }
+           } else {
+               exclPrefixes = xsltParseStylesheetExcludePrefix(style, cur, 0);
+           }
+                    
+           if ((cur->nsDef != NULL) && (style->exclPrefixNr > 0)) {
+               xmlNsPtr ns = cur->nsDef, prev = NULL, next;
+               xmlNodePtr root = NULL;
+               int i, moved;
+
+               root = xmlDocGetRootElement(cur->doc);
+               if ((root != NULL) && (root != cur)) {
+                   while (ns != NULL) {
+                       moved = 0;
+                       next = ns->next;
+                       for (i = 0;i < style->exclPrefixNr;i++) {
+                           if ((ns->prefix != NULL) && 
+                               (xmlStrEqual(ns->href,
+                                            style->exclPrefixTab[i]))) {
+                               /*
+                                * Move the namespace definition on the root
+                                * element to avoid duplicating it without
+                                * loosing it.
+                                */
+                               if (prev == NULL) {
+                                   cur->nsDef = ns->next;
+                               } else {
+                                   prev->next = ns->next;
+                               }
+                               ns->next = root->nsDef;
+                               root->nsDef = ns;
+                               moved = 1;
+                               break;
+                           }
+                       }
+                       if (moved == 0)
+                           prev = ns;
+                       ns = next;
+                   }
+               }
+           }
+           /*
+            * If we have prefixes locally, recurse and pop them up when
+            * going back
+            */
+           if (exclPrefixes > 0) {
+               xsltPrecomputeStylesheet(style, cur->children);
+               for (;exclPrefixes > 0;exclPrefixes--)
+                   exclPrefixPop(style);
+               goto skip_children;
+           }
+       } else if (cur->type == XML_TEXT_NODE) {
+           if (IS_BLANK_NODE(cur)) {
+               if (xmlNodeGetSpacePreserve(cur) != 1) {
+                   deleteNode = cur;
+               }
+           } else if ((cur->content != NULL) && (internalize) &&
+                      (!xmlDictOwns(style->dict, cur->content))) {
+               xmlChar *tmp;
+
+               /*
+                * internalize the text string, goal is to speed
+                * up operations and minimize used space by compiled
+                * stylesheets.
+                */
+               tmp = (xmlChar *) xmlDictLookup(style->dict, cur->content, -1);
+               xmlNodeSetContent(cur, NULL);
+               cur->content = tmp;
+           }
+       } else if ((cur->type != XML_ELEMENT_NODE) &&
+                  (cur->type != XML_CDATA_SECTION_NODE)) {
+           deleteNode = cur;
+           goto skip_children;
+       }
+
+       /*
+        * Skip to next node
+        */
+       if (cur->children != NULL) {
+           if ((cur->children->type != XML_ENTITY_DECL) &&
+               (cur->children->type != XML_ENTITY_REF_NODE) &&
+               (cur->children->type != XML_ENTITY_NODE)) {
+               cur = cur->children;
+               continue;
+           }
+       }
+
+skip_children:
+       if (cur->next != NULL) {
+           cur = cur->next;
+           continue;
+       }       
+       do {
+
+           cur = cur->parent;
+           if (cur == NULL)
+               break;
+           if (cur == (xmlNodePtr) style->doc) {
+               cur = NULL;
+               break;
+           }
+           if (cur->next != NULL) {
+               cur = cur->next;
+               break;
+           }
+       } while (cur != NULL);
+    }
+    if (deleteNode != NULL) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+       xsltGenericDebug(xsltGenericDebugContext,
+        "xsltPrecomputeStylesheet: removing ignorable blank node\n");
+#endif
+       xmlUnlinkNode(deleteNode);
+       xmlFreeNode(deleteNode);
+    }
+}
+#endif /* end of else XSLT_REFACTORED */
+
+/**
+ * xsltGatherNamespaces:
+ * @style:  the XSLT stylesheet
+ *
+ * Browse the stylesheet and build the namspace hash table which
+ * will be used for XPath interpretation. If needed do a bit of normalization
+ */
+
+static void
+xsltGatherNamespaces(xsltStylesheetPtr style) {
+    xmlNodePtr cur;
+    const xmlChar *URI;
+
+    if (style == NULL)
+        return;
+    /* 
+     * TODO: basically if the stylesheet uses the same prefix for different
+     *       patterns, well they may be in problem, hopefully they will get
+     *       a warning first.
+     */
+    /*
+    * TODO: Eliminate the use of the hash for XPath expressions.
+    *   An expression should be evaluated in the context of the in-scope
+    *   namespaces; eliminate the restriction of an XML document to contain
+    *   no duplicate prefixes for different namespace names.
+    * 
+    */
+    cur = xmlDocGetRootElement(style->doc);
+    while (cur != NULL) {
+       if (cur->type == XML_ELEMENT_NODE) {
+           xmlNsPtr ns = cur->nsDef;
+           while (ns != NULL) {
+               if (ns->prefix != NULL) {
+                   if (style->nsHash == NULL) {
+                       style->nsHash = xmlHashCreate(10);
+                       if (style->nsHash == NULL) {
+                           xsltTransformError(NULL, style, cur,
+                "xsltGatherNamespaces: failed to create hash table\n");
+                           style->errors++;
+                           return;
+                       }
+                   }
+                   URI = xmlHashLookup(style->nsHash, ns->prefix);
+                   if ((URI != NULL) && (!xmlStrEqual(URI, ns->href))) {
+                       xsltTransformError(NULL, style, cur,
+            "Namespaces prefix %s used for multiple namespaces\n",ns->prefix);
+                       style->warnings++;
+                   } else if (URI == NULL) {
+                       xmlHashUpdateEntry(style->nsHash, ns->prefix,
+                           (void *) ns->href, (xmlHashDeallocator)xmlFree);
+
+#ifdef WITH_XSLT_DEBUG_PARSING
+                       xsltGenericDebug(xsltGenericDebugContext,
+                "Added namespace: %s mapped to %s\n", ns->prefix, ns->href);
+#endif
+                   }
+               }
+               ns = ns->next;
+           }
+       }
+
+       /*
+        * Skip to next node
+        */
+       if (cur->children != NULL) {
+           if (cur->children->type != XML_ENTITY_DECL) {
+               cur = cur->children;
+               continue;
+           }
+       }
+       if (cur->next != NULL) {
+           cur = cur->next;
+           continue;
+       }
+       
+       do {
+           cur = cur->parent;
+           if (cur == NULL)
+               break;
+           if (cur == (xmlNodePtr) style->doc) {
+               cur = NULL;
+               break;
+           }
+           if (cur->next != NULL) {
+               cur = cur->next;
+               break;
+           }
+       } while (cur != NULL);
+    }
+}
+
+#ifdef XSLT_REFACTORED
+
+static xsltStyleType
+xsltGetXSLTElementTypeByNode(xsltCompilerCtxtPtr cctxt,
+                            xmlNodePtr node)
+{
+    if ((node == NULL) || (node->type != XML_ELEMENT_NODE) ||
+       (node->name == NULL))
+       return(0);
+
+    if (node->name[0] == 'a') {
+       if (IS_XSLT_NAME(node, "apply-templates"))
+           return(XSLT_FUNC_APPLYTEMPLATES);
+       else if (IS_XSLT_NAME(node, "attribute"))
+           return(XSLT_FUNC_ATTRIBUTE);
+       else if (IS_XSLT_NAME(node, "apply-imports"))
+           return(XSLT_FUNC_APPLYIMPORTS);
+       else if (IS_XSLT_NAME(node, "attribute-set"))
+           return(0);
+
+    } else if (node->name[0] == 'c') {
+       if (IS_XSLT_NAME(node, "choose"))
+           return(XSLT_FUNC_CHOOSE);
+       else if (IS_XSLT_NAME(node, "copy"))
+           return(XSLT_FUNC_COPY);
+       else if (IS_XSLT_NAME(node, "copy-of"))
+           return(XSLT_FUNC_COPYOF);
+       else if (IS_XSLT_NAME(node, "call-template"))
+           return(XSLT_FUNC_CALLTEMPLATE);
+       else if (IS_XSLT_NAME(node, "comment"))
+           return(XSLT_FUNC_COMMENT);
+
+    } else if (node->name[0] == 'd') {
+       if (IS_XSLT_NAME(node, "document"))
+           return(XSLT_FUNC_DOCUMENT);
+       else if (IS_XSLT_NAME(node, "decimal-format"))
+           return(0);
+
+    } else if (node->name[0] == 'e') {
+       if (IS_XSLT_NAME(node, "element"))
+           return(XSLT_FUNC_ELEMENT);
+
+    } else if (node->name[0] == 'f') {
+       if (IS_XSLT_NAME(node, "for-each"))
+           return(XSLT_FUNC_FOREACH);
+       else if (IS_XSLT_NAME(node, "fallback"))
+           return(XSLT_FUNC_FALLBACK);
+
+    } else if (*(node->name) == 'i') {
+       if (IS_XSLT_NAME(node, "if"))
+           return(XSLT_FUNC_IF);
+       else if (IS_XSLT_NAME(node, "include"))
+           return(0);
+       else if (IS_XSLT_NAME(node, "import"))
+           return(0);
+
+    } else if (*(node->name) == 'k') {
+       if (IS_XSLT_NAME(node, "key"))
+           return(0);
+
+    } else if (*(node->name) == 'm') {
+       if (IS_XSLT_NAME(node, "message"))
+           return(XSLT_FUNC_MESSAGE);
+
+    } else if (*(node->name) == 'n') {
+       if (IS_XSLT_NAME(node, "number"))
+           return(XSLT_FUNC_NUMBER);
+       else if (IS_XSLT_NAME(node, "namespace-alias"))
+           return(0);
+
+    } else if (*(node->name) == 'o') {
+       if (IS_XSLT_NAME(node, "otherwise"))
+           return(XSLT_FUNC_OTHERWISE);
+       else if (IS_XSLT_NAME(node, "output"))
+           return(0);
+
+    } else if (*(node->name) == 'p') {
+       if (IS_XSLT_NAME(node, "param"))
+           return(XSLT_FUNC_PARAM);
+       else if (IS_XSLT_NAME(node, "processing-instruction"))
+           return(XSLT_FUNC_PI);
+       else if (IS_XSLT_NAME(node, "preserve-space"))
+           return(0);
+
+    } else if (*(node->name) == 's') {
+       if (IS_XSLT_NAME(node, "sort"))
+           return(XSLT_FUNC_SORT);
+       else if (IS_XSLT_NAME(node, "strip-space"))
+           return(0);
+       else if (IS_XSLT_NAME(node, "stylesheet"))
+           return(0);
+
+    } else if (node->name[0] == 't') {
+       if (IS_XSLT_NAME(node, "text"))
+           return(XSLT_FUNC_TEXT);
+       else if (IS_XSLT_NAME(node, "template"))
+           return(0);
+       else if (IS_XSLT_NAME(node, "transform"))
+           return(0);
+
+    } else if (*(node->name) == 'v') {
+       if (IS_XSLT_NAME(node, "value-of"))
+           return(XSLT_FUNC_VALUEOF);
+       else if (IS_XSLT_NAME(node, "variable"))
+           return(XSLT_FUNC_VARIABLE);
+
+    } else if (*(node->name) == 'w') {
+       if (IS_XSLT_NAME(node, "when"))
+           return(XSLT_FUNC_WHEN);
+       if (IS_XSLT_NAME(node, "with-param"))
+           return(XSLT_FUNC_WITHPARAM);
+    }
+    return(0);
+}
+
+/**
+ * xsltParseAnyXSLTElem:
+ *
+ * @cctxt: the compilation context
+ * @elem: the element node of the XSLT instruction
+ *
+ * Parses, validates the content models and compiles XSLT instructions.
+ *
+ * Returns 0 if everything's fine;
+ *         -1 on API or internal errors.
+ */ 
+int
+xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)
+{
+    if ((cctxt == NULL) || (elem == NULL) ||
+       (elem->type != XML_ELEMENT_NODE))
+       return(-1);
+
+    elem->psvi = NULL;
+
+    if (! (IS_XSLT_ELEM_FAST(elem)))
+       return(-1);
+    /*
+    * Detection of handled content of extension instructions.
+    */
+    if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
+       cctxt->inode->extContentHandled = 1;
+    }
+    
+    xsltCompilerNodePush(cctxt, elem);
+    /*
+    * URGENT TODO: Find a way to speed up this annoying redundant
+    *  textual node-name and namespace comparison.
+    */
+    if (cctxt->inode->prev->curChildType != 0)
+       cctxt->inode->type = cctxt->inode->prev->curChildType;
+    else
+       cctxt->inode->type = xsltGetXSLTElementTypeByNode(cctxt, elem);    
+    /*
+    * Update the in-scope namespaces if needed.
+    */
+    if (elem->nsDef != NULL)
+       cctxt->inode->inScopeNs =
+           xsltCompilerBuildInScopeNsList(cctxt, elem);
+    /*
+    * xsltStylePreCompute():
+    *  This will compile the information found on the current
+    *  element's attributes. NOTE that this won't process the
+    *  children of the instruction.
+    */
+    xsltStylePreCompute(cctxt->style, elem);
+    /*
+    * TODO: How to react on errors in xsltStylePreCompute() ?
+    */
+
+    /*
+    * Validate the content model of the XSLT-element.
+    */
+    switch (cctxt->inode->type) {      
+       case XSLT_FUNC_APPLYIMPORTS:
+           /* EMPTY */
+           goto empty_content;
+       case XSLT_FUNC_APPLYTEMPLATES:
+           /* <!-- Content: (xsl:sort | xsl:with-param)* --> */
+           goto apply_templates;           
+       case XSLT_FUNC_ATTRIBUTE:           
+           /* <!-- Content: template --> */
+           goto sequence_constructor;
+       case XSLT_FUNC_CALLTEMPLATE:
+           /* <!-- Content: xsl:with-param* --> */
+           goto call_template;
+       case XSLT_FUNC_CHOOSE:      
+           /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */
+           goto choose;
+       case XSLT_FUNC_COMMENT:
+           /* <!-- Content: template --> */
+           goto sequence_constructor;      
+       case XSLT_FUNC_COPY:
+           /* <!-- Content: template --> */
+           goto sequence_constructor;      
+       case XSLT_FUNC_COPYOF:
+           /* EMPTY */
+           goto empty_content;    
+       case XSLT_FUNC_DOCUMENT: /* Extra one */
+           /* ?? template ?? */
+           goto sequence_constructor;
+       case XSLT_FUNC_ELEMENT:
+           /* <!-- Content: template --> */
+           goto sequence_constructor;
+       case XSLT_FUNC_FALLBACK:
+           /* <!-- Content: template --> */
+           goto sequence_constructor;
+       case XSLT_FUNC_FOREACH:
+           /* <!-- Content: (xsl:sort*, template) --> */
+           goto for_each;
+       case XSLT_FUNC_IF:
+           /* <!-- Content: template --> */
+           goto sequence_constructor;
+       case XSLT_FUNC_OTHERWISE:
+           /* <!-- Content: template --> */
+           goto sequence_constructor;
+       case XSLT_FUNC_MESSAGE:
+           /* <!-- Content: template --> */
+           goto sequence_constructor;
+       case XSLT_FUNC_NUMBER:
+           /* EMPTY */
+           goto empty_content;
+       case XSLT_FUNC_PARAM:
+           /*
+           * Check for redefinition.
+           */
+           if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {
+               xsltVarInfoPtr ivar = cctxt->ivar;
+
+               do {
+                   if ((ivar->name ==
+                        ((xsltStyleItemParamPtr) elem->psvi)->name) &&
+                       (ivar->nsName ==
+                        ((xsltStyleItemParamPtr) elem->psvi)->ns))
+                   {
+                       elem->psvi = NULL;
+                       xsltTransformError(NULL, cctxt->style, elem,
+                           "Redefinition of variable or parameter '%s'.\n",
+                           ivar->name);
+                       cctxt->style->errors++;
+                       goto error;
+                   }
+                   ivar = ivar->prev;
+               } while (ivar != NULL);
+           }
+           /*  <!-- Content: template --> */
+           goto sequence_constructor;
+       case XSLT_FUNC_PI:
+           /*  <!-- Content: template --> */
+           goto sequence_constructor;
+       case XSLT_FUNC_SORT:
+           /* EMPTY */
+           goto empty_content;
+       case XSLT_FUNC_TEXT:
+           /* <!-- Content: #PCDATA --> */
+           goto text;
+       case XSLT_FUNC_VALUEOF:
+           /* EMPTY */
+           goto empty_content;
+       case XSLT_FUNC_VARIABLE:
+           /*
+           * Check for redefinition.
+           */
+           if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {
+               xsltVarInfoPtr ivar = cctxt->ivar;              
+
+               do {
+                   if ((ivar->name ==
+                        ((xsltStyleItemVariablePtr) elem->psvi)->name) &&
+                       (ivar->nsName ==
+                        ((xsltStyleItemVariablePtr) elem->psvi)->ns))
+                   {
+                       elem->psvi = NULL;
+                       xsltTransformError(NULL, cctxt->style, elem,
+                           "Redefinition of variable or parameter '%s'.\n",
+                           ivar->name);
+                       cctxt->style->errors++;
+                       goto error;
+                   }
+                   ivar = ivar->prev;
+               } while (ivar != NULL);
+           }
+           /* <!-- Content: template --> */
+           goto sequence_constructor;
+       case XSLT_FUNC_WHEN:
+           /* <!-- Content: template --> */
+           goto sequence_constructor;
+       case XSLT_FUNC_WITHPARAM:
+           /* <!-- Content: template --> */
+           goto sequence_constructor;
+       default:
+#ifdef WITH_XSLT_DEBUG_PARSING
+           xsltGenericDebug(xsltGenericDebugContext,
+               "xsltParseXSLTNode: Unhandled XSLT element '%s'.\n",
+               elem->name);        
+#endif
+           xsltTransformError(NULL, cctxt->style, elem,
+               "xsltParseXSLTNode: Internal error; "
+               "unhandled XSLT element '%s'.\n", elem->name);
+           cctxt->style->errors++;
+           goto internal_err;
+    }
+
+apply_templates:
+    /* <!-- Content: (xsl:sort | xsl:with-param)* --> */
+    if (elem->children != NULL) {
+       xmlNodePtr child = elem->children;
+       do {
+           if (child->type == XML_ELEMENT_NODE) {
+               if (IS_XSLT_ELEM_FAST(child)) {
+                   if (xmlStrEqual(child->name, BAD_CAST "with-param")) {
+                       cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;
+                       xsltParseAnyXSLTElem(cctxt, child);
+                   } else if (xmlStrEqual(child->name, BAD_CAST "sort")) {
+                       cctxt->inode->curChildType = XSLT_FUNC_SORT;
+                       xsltParseAnyXSLTElem(cctxt, child);
+                   } else
+                       xsltParseContentError(cctxt->style, child);
+               } else
+                   xsltParseContentError(cctxt->style, child);
+           }
+           child = child->next;
+       } while (child != NULL);
+    }    
+    goto exit;
+
+call_template:
+    /* <!-- Content: xsl:with-param* --> */
+    if (elem->children != NULL) {
+       xmlNodePtr child = elem->children;
+       do {
+           if (child->type == XML_ELEMENT_NODE) {
+               if (IS_XSLT_ELEM_FAST(child)) {
+                   xsltStyleType type;
+
+                   type = xsltGetXSLTElementTypeByNode(cctxt, child);
+                   if (type == XSLT_FUNC_WITHPARAM) {
+                       cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;
+                       xsltParseAnyXSLTElem(cctxt, child);
+                   } else {
+                       xsltParseContentError(cctxt->style, child);
+                   }
+               } else
+                   xsltParseContentError(cctxt->style, child);
+           }
+           child = child->next;
+       } while (child != NULL);
+    }    
+    goto exit;
+
+text:
+    if (elem->children != NULL) {
+       xmlNodePtr child = elem->children;
+       do {
+           if ((child->type != XML_TEXT_NODE) &&
+               (child->type != XML_CDATA_SECTION_NODE))
+           {
+               xsltTransformError(NULL, cctxt->style, elem,
+                   "The XSLT 'text' element must have only character "
+                   "data as content.\n");
+           }
+           child = child->next;
+       } while (child != NULL);
+    }
+    goto exit;
+
+empty_content:
+    if (elem->children != NULL) {
+       xmlNodePtr child = elem->children;
+       /*
+       * Relaxed behaviour: we will allow whitespace-only text-nodes.
+       */
+       do {
+           if (((child->type != XML_TEXT_NODE) &&
+                (child->type != XML_CDATA_SECTION_NODE)) ||
+               (! IS_BLANK_NODE(child)))
+           {
+               xsltTransformError(NULL, cctxt->style, elem,
+                   "This XSLT element must have no content.\n");
+               cctxt->style->errors++;
+               break;
+           }
+           child = child->next;
+       } while (child != NULL);                
+    }
+    goto exit;
+
+choose:
+    /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */
+    /*
+    * TODO: text-nodes in between are *not* allowed in XSLT 1.0.
+    *   The old behaviour did not check this.
+    * NOTE: In XSLT 2.0 they are stripped beforehand
+    *  if whitespace-only (regardless of xml:space).
+    */
+    if (elem->children != NULL) {
+       xmlNodePtr child = elem->children;
+       int nbWhen = 0, nbOtherwise = 0, err = 0;
+       do {
+           if (child->type == XML_ELEMENT_NODE) {
+               if (IS_XSLT_ELEM_FAST(child)) {
+                   xsltStyleType type;
+               
+                   type = xsltGetXSLTElementTypeByNode(cctxt, child);
+                   if (type == XSLT_FUNC_WHEN) {
+                       nbWhen++;
+                       if (nbOtherwise) {
+                           xsltParseContentError(cctxt->style, child);
+                           err = 1;
+                           break;
+                       }
+                       cctxt->inode->curChildType = XSLT_FUNC_WHEN;
+                       xsltParseAnyXSLTElem(cctxt, child);
+                   } else if (type == XSLT_FUNC_OTHERWISE) {
+                       if (! nbWhen) {
+                           xsltParseContentError(cctxt->style, child);
+                           err = 1;
+                           break;
+                       }                       
+                       if (nbOtherwise) {
+                           xsltTransformError(NULL, cctxt->style, elem,
+                               "The XSLT 'choose' element must not contain "
+                               "more than one XSLT 'otherwise' element.\n");
+                           cctxt->style->errors++;
+                           err = 1;
+                           break;
+                       }
+                       nbOtherwise++;
+                       cctxt->inode->curChildType = XSLT_FUNC_OTHERWISE;
+                       xsltParseAnyXSLTElem(cctxt, child);
+                   } else
+                       xsltParseContentError(cctxt->style, child);
+               } else
+                   xsltParseContentError(cctxt->style, child);
+           } 
+           /*
+               else
+                   xsltParseContentError(cctxt, child);
+           */
+           child = child->next;
+       } while (child != NULL);
+       if ((! err) && (! nbWhen)) {
+           xsltTransformError(NULL, cctxt->style, elem,
+               "The XSLT element 'choose' must contain at least one "
+               "XSLT element 'when'.\n");
+               cctxt->style->errors++;
+       }       
+    }    
+    goto exit;
+
+for_each:
+    /* <!-- Content: (xsl:sort*, template) --> */
+    /*
+    * NOTE: Text-nodes before xsl:sort are *not* allowed in XSLT 1.0.
+    *   The old behaviour did not allow this, but it catched this
+    *   only at transformation-time.
+    *   In XSLT 2.0 they are stripped beforehand if whitespace-only
+    *   (regardless of xml:space).
+    */
+    if (elem->children != NULL) {
+       xmlNodePtr child = elem->children;
+       /*
+       * Parse xsl:sort first.
+       */
+       do {        
+           if ((child->type == XML_ELEMENT_NODE) &&
+               IS_XSLT_ELEM_FAST(child))
+           {           
+               if (xsltGetXSLTElementTypeByNode(cctxt, child) ==
+                   XSLT_FUNC_SORT)
+               {               
+                   cctxt->inode->curChildType = XSLT_FUNC_SORT;
+                   xsltParseAnyXSLTElem(cctxt, child);
+               } else
+                   break;
+           } else
+               break;
+           child = child->next;
+       } while (child != NULL);
+       /*
+       * Parse the sequece constructor.
+       */
+       if (child != NULL)
+           xsltParseSequenceConstructor(cctxt, child);
+    }    
+    goto exit;
+
+sequence_constructor:
+    /*
+    * Parse the sequence constructor.
+    */
+    if (elem->children != NULL)
+       xsltParseSequenceConstructor(cctxt, elem->children);
+
+    /*
+    * Register information for vars/params. Only needed if there
+    * are any following siblings.
+    */
+    if ((elem->next != NULL) &&
+       ((cctxt->inode->type == XSLT_FUNC_VARIABLE) ||
+        (cctxt->inode->type == XSLT_FUNC_PARAM)))
+    {  
+       if ((elem->psvi != NULL) &&
+           (((xsltStyleBasicItemVariablePtr) elem->psvi)->name))
+       {       
+           xsltCompilerVarInfoPush(cctxt, elem,
+               ((xsltStyleBasicItemVariablePtr) elem->psvi)->name,
+               ((xsltStyleBasicItemVariablePtr) elem->psvi)->ns);
+       }
+    }
+
+error:
+exit:
+    xsltCompilerNodePop(cctxt, elem);
+    return(0);
+
+internal_err:
+    xsltCompilerNodePop(cctxt, elem);
+    return(-1);
+}
+
+/**
+ * xsltForwardsCompatUnkownItemCreate:
+ *
+ * @cctxt: the compilation context 
+ *
+ * Creates a compiled representation of the unknown
+ * XSLT instruction.
+ *
+ * Returns the compiled representation.
+ */ 
+static xsltStyleItemUknownPtr
+xsltForwardsCompatUnkownItemCreate(xsltCompilerCtxtPtr cctxt)
+{
+    xsltStyleItemUknownPtr item;
+
+    item = (xsltStyleItemUknownPtr) xmlMalloc(sizeof(xsltStyleItemUknown));
+    if (item == NULL) {
+       xsltTransformError(NULL, cctxt->style, NULL,
+           "Internal error in xsltForwardsCompatUnkownItemCreate(): "
+           "Failed to allocate memory.\n");
+       cctxt->style->errors++;
+       return(NULL);
+    }
+    memset(item, 0, sizeof(xsltStyleItemUknown));
+    item->type = XSLT_FUNC_UNKOWN_FORWARDS_COMPAT;
+    /*
+    * Store it in the stylesheet.
+    */
+    item->next = cctxt->style->preComps;
+    cctxt->style->preComps = (xsltElemPreCompPtr) item;
+    return(item);
+}
+
+/**
+ * xsltParseUnknownXSLTElem:
+ *
+ * @cctxt: the compilation context
+ * @node: the element of the unknown XSLT instruction
+ *
+ * Parses an unknown XSLT element.
+ * If forwards compatible mode is enabled this will allow
+ * such an unknown XSLT and; otherwise it is rejected.
+ *
+ * Returns 1 in the unknown XSLT instruction is rejected,
+ *         0 if everything's fine and
+ *         -1 on API or internal errors.
+ */ 
+static int
+xsltParseUnknownXSLTElem(xsltCompilerCtxtPtr cctxt,
+                           xmlNodePtr node)
+{
+    if ((cctxt == NULL) || (node == NULL))
+       return(-1);
+
+    /*
+    * Detection of handled content of extension instructions.
+    */
+    if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
+       cctxt->inode->extContentHandled = 1;
+    }    
+    if (cctxt->inode->forwardsCompat == 0) {   
+       /*
+       * We are not in forwards-compatible mode, so raise an error.
+       */
+       xsltTransformError(NULL, cctxt->style, node,
+           "Unknown XSLT element '%s'.\n", node->name);
+       cctxt->style->errors++;
+       return(1);
+    }
+    /*
+    * Forwards-compatible mode.
+    * ------------------------
+    *    
+    * Parse/compile xsl:fallback elements.
+    *
+    * QUESTION: Do we have to raise an error if there's no xsl:fallback?
+    * ANSWER: No, since in the stylesheet the fallback behaviour might
+    *  also be provided by using the XSLT function "element-available".
+    */
+    if (cctxt->unknownItem == NULL) {
+       /*
+       * Create a singleton for all unknown XSLT instructions.
+       */
+       cctxt->unknownItem = xsltForwardsCompatUnkownItemCreate(cctxt);
+       if (cctxt->unknownItem == NULL) {
+           node->psvi = NULL;
+           return(-1);
+       }
+    }
+    node->psvi = cctxt->unknownItem;
+    if (node->children == NULL)
+       return(0);
+    else {
+       xmlNodePtr child = node->children;
+
+       xsltCompilerNodePush(cctxt, node);
+       /*
+       * Update the in-scope namespaces if needed.
+       */
+       if (node->nsDef != NULL)
+           cctxt->inode->inScopeNs =
+               xsltCompilerBuildInScopeNsList(cctxt, node);
+       /*
+       * Parse all xsl:fallback children.
+       */
+       do {
+           if ((child->type == XML_ELEMENT_NODE) &&
+               IS_XSLT_ELEM_FAST(child) &&
+               IS_XSLT_NAME(child, "fallback"))
+           {
+               cctxt->inode->curChildType = XSLT_FUNC_FALLBACK;
+               xsltParseAnyXSLTElem(cctxt, child);
+           }
+           child = child->next;
+       } while (child != NULL);
+       
+       xsltCompilerNodePop(cctxt, node);
+    }
+    return(0);
+}
+
+/**
+ * xsltParseSequenceConstructor:
+ *
+ * @cctxt: the compilation context
+ * @cur: the start-node of the content to be parsed
+ *
+ * Parses a "template" content (or "sequence constructor" in XSLT 2.0 terms).
+ * This will additionally remove xsl:text elements from the tree.
+ */ 
+void
+xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
+{
+    xsltStyleType type;
+    xmlNodePtr deleteNode = NULL;
+
+    if (cctxt == NULL) {
+       xmlGenericError(xmlGenericErrorContext,
+           "xsltParseSequenceConstructor: Bad arguments\n");
+       cctxt->style->errors++;
+       return;
+    }
+    /*
+    * Detection of handled content of extension instructions.
+    */
+    if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
+       cctxt->inode->extContentHandled = 1;
+    }
+    if (cur == NULL)
+       return;
+    /*
+    * This is the content reffered to as a "template".
+    * E.g. an xsl:element has such content model:
+    * <xsl:element
+    *   name = { qname }
+    *   namespace = { uri-reference }
+    *   use-attribute-sets = qnames>
+    * <!-- Content: template -->
+    *
+    * NOTE that in XSLT-2 the term "template" was abandoned due to
+    *  confusion with xsl:template and the term "sequence constructor"
+    *  was introduced instead.
+    *
+    * The following XSLT-instructions are allowed to appear:
+    *  xsl:apply-templates, xsl:call-template, xsl:apply-imports,
+    *  xsl:for-each, xsl:value-of, xsl:copy-of, xsl:number,
+    *  xsl:choose, xsl:if, xsl:text, xsl:copy, xsl:variable,
+    *  xsl:message, xsl:fallback,
+    *  xsl:processing-instruction, xsl:comment, xsl:element
+    *  xsl:attribute. 
+    * Additional allowed content:
+    * 1) extension instructions
+    * 2) literal result elements
+    * 3) PCDATA
+    *
+    * NOTE that this content model does *not* allow xsl:param.
+    */    
+    while (cur != NULL) {
+       if (deleteNode != NULL) {
+#ifdef WITH_XSLT_DEBUG_BLANKS
+           xsltGenericDebug(xsltGenericDebugContext,
+            "xsltParseSequenceConstructor: removing xsl:text element\n");
+#endif
+           xmlUnlinkNode(deleteNode);
+           xmlFreeNode(deleteNode);
+           deleteNode = NULL;
+       }
+       if (cur->type == XML_ELEMENT_NODE) {        
+           
+           if (cur->psvi == xsltXSLTTextMarker) {
+               /*
+               * xsl:text elements
+               * --------------------------------------------------------
+               */
+               xmlNodePtr tmp;
+
+               cur->psvi = NULL;
+               /*
+               * Mark the xsl:text element for later deletion.
+               */
+               deleteNode = cur;
+               /*
+               * Validate content.
+               */
+               tmp = cur->children;
+               if (tmp) {
+                   /*
+                   * We don't expect more than one text-node in the
+                   * content, since we already merged adjacent
+                   * text/CDATA-nodes and eliminated PI/comment-nodes.
+                   */
+                   if ((tmp->type == XML_TEXT_NODE) ||
+                       (tmp->next == NULL))
+                   {
+                       /*
+                       * Leave the contained text-node in the tree.
+                       */
+                       xmlUnlinkNode(tmp);
+                       xmlAddPrevSibling(cur, tmp);
+                   } else {
+                       tmp = NULL;
+                       xsltTransformError(NULL, cctxt->style, cur,
+                           "Element 'xsl:text': Invalid type "
+                           "of node found in content.\n");
+                       cctxt->style->errors++;
+                   } 
+               }
+               if (cur->properties) {
+                   xmlAttrPtr attr;
+                   /*
+                   * TODO: We need to report errors for
+                   *  invalid attrs.
+                   */
+                   attr = cur->properties;
+                   do {
+                       if ((attr->ns == NULL) &&
+                           (attr->name != NULL) &&
+                           (attr->name[0] == 'd') &&
+                           xmlStrEqual(attr->name,
+                           BAD_CAST "disable-output-escaping"))
+                       {
+                           /*
+                           * Attr "disable-output-escaping".
+                           * XSLT-2: This attribute is deprecated.
+                           */
+                           if ((attr->children != NULL) &&
+                               xmlStrEqual(attr->children->content,
+                               BAD_CAST "yes"))
+                           {
+                               /*
+                               * Disable output escaping for this
+                               * text node.
+                               */
+                               if (tmp)
+                                   tmp->name = xmlStringTextNoenc;
+                           } else if ((attr->children == NULL) ||
+                               (attr->children->content == NULL) ||
+                               (!xmlStrEqual(attr->children->content,
+                               BAD_CAST "no")))
+                           {
+                               xsltTransformError(NULL, cctxt->style,
+                                   cur,
+                                   "Attribute 'disable-output-escaping': "
+                                   "Invalid value. Expected is "
+                                   "'yes' or 'no'.\n");
+                               cctxt->style->errors++;
+                           }
+                           break;
+                       }
+                       attr = attr->next;
+                   } while (attr != NULL);
+               }
+           } else if (IS_XSLT_ELEM_FAST(cur)) {
+               /*
+               * TODO: Using the XSLT-marker is still not stable yet.
+               */
+               /* if (cur->psvi == xsltXSLTElemMarker) { */        
+               /*
+               * XSLT instructions
+               * --------------------------------------------------------
+               */
+               cur->psvi = NULL;
+               type = xsltGetXSLTElementTypeByNode(cctxt, cur);
+               switch (type) {
+                   case XSLT_FUNC_APPLYIMPORTS:
+                   case XSLT_FUNC_APPLYTEMPLATES:
+                   case XSLT_FUNC_ATTRIBUTE:
+                   case XSLT_FUNC_CALLTEMPLATE:
+                   case XSLT_FUNC_CHOOSE:
+                   case XSLT_FUNC_COMMENT:
+                   case XSLT_FUNC_COPY:
+                   case XSLT_FUNC_COPYOF:
+                   case XSLT_FUNC_DOCUMENT: /* Extra one */
+                   case XSLT_FUNC_ELEMENT:
+                   case XSLT_FUNC_FALLBACK:
+                   case XSLT_FUNC_FOREACH:
+                   case XSLT_FUNC_IF:
+                   case XSLT_FUNC_MESSAGE:
+                   case XSLT_FUNC_NUMBER:
+                   case XSLT_FUNC_PI:
+                   case XSLT_FUNC_TEXT:
+                   case XSLT_FUNC_VALUEOF:
+                   case XSLT_FUNC_VARIABLE:
+                       /*
+                       * Parse the XSLT element.
+                       */
+                       cctxt->inode->curChildType = type;
+                       xsltParseAnyXSLTElem(cctxt, cur);
+                       break;
+                   default:
+                       xsltParseUnknownXSLTElem(cctxt, cur);                   
+                       cur = cur->next;
+                       continue;
+               }
+           } else {
+               /*
+               * Non-XSLT elements
+               * -----------------
+               */
+               xsltCompilerNodePush(cctxt, cur);
+               /*
+               * Update the in-scope namespaces if needed.
+               */
+               if (cur->nsDef != NULL)
+                   cctxt->inode->inScopeNs =
+                       xsltCompilerBuildInScopeNsList(cctxt, cur);
+               /*
+               * The current element is either a literal result element
+               * or an extension instruction.
+               *
+               * Process attr "xsl:extension-element-prefixes".
+               * FUTURE TODO: IIRC in XSLT 2.0 this attribute must be
+               * processed by the implementor of the extension function;
+               * i.e., it won't be handled by the XSLT processor.
+               */
+               /* SPEC 1.0:
+               *   "exclude-result-prefixes" is only allowed on literal
+               *   result elements and "xsl:exclude-result-prefixes"
+               *   on xsl:stylesheet/xsl:transform.
+               * SPEC 2.0:
+               *   "There are a number of standard attributes
+               *   that may appear on any XSLT element: specifically
+               *   version, exclude-result-prefixes,
+               *   extension-element-prefixes, xpath-default-namespace,
+               *   default-collation, and use-when."
+               *
+               * SPEC 2.0:
+               *   For literal result elements:
+               *   "xsl:version, xsl:exclude-result-prefixes,
+               *    xsl:extension-element-prefixes,
+               *    xsl:xpath-default-namespace,
+               *    xsl:default-collation, or xsl:use-when."
+               */
+               if (cur->properties)
+                   cctxt->inode->extElemNs =
+                       xsltParseExtElemPrefixes(cctxt,
+                           cur, cctxt->inode->extElemNs,
+                           XSLT_ELEMENT_CATEGORY_LRE);
+               /*
+               * Eval if we have an extension instruction here.
+               */
+               if ((cur->ns != NULL) &&
+                   (cctxt->inode->extElemNs != NULL) &&
+                   (xsltCheckExtPrefix(cctxt->style, cur->ns->href) == 1))
+               {
+                   /*
+                   * Extension instructions
+                   * ----------------------------------------------------
+                   * Mark the node information.
+                   */
+                   cctxt->inode->category = XSLT_ELEMENT_CATEGORY_EXTENSION;
+                   cctxt->inode->extContentHandled = 0;
+                   if (cur->psvi != NULL) {
+                       cur->psvi = NULL;
+                       /*
+                       * TODO: Temporary sanity check.
+                       */
+                       xsltTransformError(NULL, cctxt->style, cur,
+                           "Internal error in xsltParseSequenceConstructor(): "
+                           "Occupied PSVI field.\n");
+                       cctxt->style->errors++;
+                       cur = cur->next;
+                       continue;
+                   }
+                   cur->psvi = (void *)
+                       xsltPreComputeExtModuleElement(cctxt->style, cur);
+                   
+                   if (cur->psvi == NULL) {
+                       /*
+                       * OLD COMMENT: "Unknown element, maybe registered
+                       *  at the context level. Mark it for later
+                       *  recognition."
+                       * QUESTION: What does the xsltExtMarker mean?
+                       *  ANSWER: It is used in
+                       *   xsltApplySequenceConstructor() at
+                       *   transformation-time to look out for extension
+                       *   registered in the transformation context.
+                       */
+                       cur->psvi = (void *) xsltExtMarker;
+                   }
+                   /*
+                   * BIG NOTE: Now the ugly part. In previous versions
+                   *  of Libxslt (until 1.1.16), all the content of an
+                   *  extension instruction was processed and compiled without
+                   *  the need of the extension-author to explicitely call
+                   *  such a processing;.We now need to mimic this old
+                   *  behaviour in order to avoid breaking old code
+                   *  on the extension-author's side.
+                   * The mechanism:
+                   *  1) If the author does *not* set the
+                   *    compile-time-flag @extContentHandled, then we'll
+                   *    parse the content assuming that it's a "template"
+                   *    (or "sequence constructor in XSLT 2.0 terms).
+                   *    NOTE: If the extension is registered at
+                   *    transformation-time only, then there's no way of
+                   *    knowing that content shall be valid, and we'll
+                   *    process the content the same way.
+                   *  2) If the author *does* set the flag, then we'll assume
+                   *   that the author has handled the parsing him/herself
+                   *   (e.g. called xsltParseSequenceConstructor(), etc.
+                   *   explicitely in his/her code).
+                   */
+                   if ((cur->children != NULL) &&
+                       (cctxt->inode->extContentHandled == 0))
+                   {
+                       /*
+                       * Default parsing of the content using the
+                       * sequence-constructor model.
+                       */
+                       xsltParseSequenceConstructor(cctxt, cur->children);
+                   }
+               } else {
+                   /*
+                   * Literal result element
+                   * ----------------------------------------------------
+                   * Allowed XSLT attributes:
+                   *  xsl:extension-element-prefixes CDATA #IMPLIED
+                   *  xsl:exclude-result-prefixes CDATA #IMPLIED
+                   *  TODO: xsl:use-attribute-sets %qnames; #IMPLIED
+                   *  xsl:version NMTOKEN #IMPLIED
+                   */
+                   cur->psvi = NULL;
+                   cctxt->inode->category = XSLT_ELEMENT_CATEGORY_LRE;
+                   if (cur->properties != NULL) {
+                       xmlAttrPtr attr = cur->properties;
+                       /*
+                       * Attribute "xsl:exclude-result-prefixes".
+                       */
+                       cctxt->inode->exclResultNs =
+                           xsltParseExclResultPrefixes(cctxt, cur,
+                               cctxt->inode->exclResultNs,
+                               XSLT_ELEMENT_CATEGORY_LRE);
+                       /*
+                       * Attribute "xsl:version".
+                       */
+                       xsltParseAttrXSLTVersion(cctxt, cur,
+                           XSLT_ELEMENT_CATEGORY_LRE);
+                       /*
+                       * Report invalid XSLT attributes.                       
+                       * For XSLT 1.0 only xsl:use-attribute-sets is allowed
+                       * next to xsl:version, xsl:exclude-result-prefixes and
+                       * xsl:extension-element-prefixes.
+                       *
+                       * Mark all XSLT attributes, in order to skip such
+                       * attributes when instantiating the LRE.
+                       */
+                       do {
+                           if ((attr->psvi != xsltXSLTAttrMarker) &&
+                               IS_XSLT_ATTR_FAST(attr))
+                           {                               
+                               if (! xmlStrEqual(attr->name,
+                                   BAD_CAST "use-attribute-sets"))
+                               {                               
+                                   xsltTransformError(NULL, cctxt->style,
+                                       cur,
+                                       "Unknown XSLT attribute '%s'.\n",
+                                       attr->name);
+                                   cctxt->style->errors++;
+                               } else {
+                                   /*
+                                   * XSLT attr marker.
+                                   */
+                                   attr->psvi = (void *) xsltXSLTAttrMarker;
+                               }
+                           }
+                           attr = attr->next;
+                       } while (attr != NULL);
+                   }
+                   /*
+                   * Create/reuse info for the literal result element.
+                   */
+                   if (cctxt->inode->nsChanged)
+                       xsltLREInfoCreate(cctxt, cur, 1);
+                   cur->psvi = cctxt->inode->litResElemInfo;
+                   /*
+                   * Apply ns-aliasing on the element and on its attributes.
+                   */
+                   if (cctxt->hasNsAliases)
+                       xsltLREBuildEffectiveNs(cctxt, cur);
+                   /*
+                   * Compile attribute value templates (AVT).
+                   */
+                   if (cur->properties) {
+                       xmlAttrPtr attr = cur->properties;
+                       
+                       while (attr != NULL) {
+                           xsltCompileAttr(cctxt->style, attr);
+                           attr = attr->next;
+                       }
+                   }
+                   /*
+                   * Parse the content, which is defined to be a "template"
+                   * (or "sequence constructor" in XSLT 2.0 terms).
+                   */
+                   if (cur->children != NULL) {
+                       xsltParseSequenceConstructor(cctxt, cur->children);
+                   }
+               }
+               /*
+               * Leave the non-XSLT element.
+               */
+               xsltCompilerNodePop(cctxt, cur);
+           }
+       }
+       cur = cur->next;
+    }
+    if (deleteNode != NULL) {
+#ifdef WITH_XSLT_DEBUG_BLANKS
+       xsltGenericDebug(xsltGenericDebugContext,
+           "xsltParseSequenceConstructor: removing xsl:text element\n");
+#endif
+       xmlUnlinkNode(deleteNode);
+       xmlFreeNode(deleteNode);
+       deleteNode = NULL;
+    }
+}
+
+/**
+ * xsltParseTemplateContent:
+ * @style:  the XSLT stylesheet
+ * @templ:  the node containing the content to be parsed
+ *
+ * Parses and compiles the content-model of an xsl:template element.
+ * Note that this is *not* the "template" content model (or "sequence
+ *  constructor" in XSLT 2.0); it it allows addional xsl:param
+ *  elements as immediate children of @templ.
+ *
+ * Called by: 
+ *   exsltFuncFunctionComp() (EXSLT, functions.c)
+ *   So this is intended to be called from extension functions.
+ */
+void
+xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
+    if ((style == NULL) || (templ == NULL))
+       return;
+
+    /*
+    * Detection of handled content of extension instructions.
+    */
+    if (XSLT_CCTXT(style)->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
+       XSLT_CCTXT(style)->inode->extContentHandled = 1;
+    }
+
+    if (templ->children != NULL) {     
+       xmlNodePtr child = templ->children;
+       /*
+       * Process xsl:param elements, which can only occur as the
+       * immediate children of xsl:template (well, and of any
+       * user-defined extension instruction if needed).
+       */      
+       do {
+           if ((child->type == XML_ELEMENT_NODE) &&
+               IS_XSLT_ELEM_FAST(child) &&
+               IS_XSLT_NAME(child, "param"))
+           {
+               XSLT_CCTXT(style)->inode->curChildType = XSLT_FUNC_PARAM;
+               xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);
+           } else
+               break;
+           child = child->next;
+       } while (child != NULL);
+       /*
+       * Parse the content and register the pattern.
+       */
+       xsltParseSequenceConstructor(XSLT_CCTXT(style), child);
+    }
+}
+
+#else /* XSLT_REFACTORED */
+
+/**
+ * xsltParseTemplateContent:
+ * @style:  the XSLT stylesheet
+ * @templ:  the container node (can be a document for literal results)
+ *
+ * parse a template content-model
+ * Clean-up the template content from unwanted ignorable blank nodes
+ * and process xslt:text
+ */
+void
+xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
+    xmlNodePtr cur, delete;
+    /*
+     * This content comes from the stylesheet
+     * For stylesheets, the set of whitespace-preserving
+     * element names consists of just xsl:text.
+     */
+    cur = templ->children;
+    delete = NULL;
+    while (cur != NULL) {
+       if (delete != NULL) {
+#ifdef WITH_XSLT_DEBUG_BLANKS
+           xsltGenericDebug(xsltGenericDebugContext,
+            "xsltParseTemplateContent: removing text\n");
+#endif
+           xmlUnlinkNode(delete);
+           xmlFreeNode(delete);
+           delete = NULL;
+       }
+       if (IS_XSLT_ELEM(cur)) {
+           if (IS_XSLT_NAME(cur, "text")) {
+               /*
+               * TODO: Processing of xsl:text should be moved to
+               *   xsltPrecomputeStylesheet(), since otherwise this
+               *   will be performed for every multiply included
+               *   stylesheet; i.e. this here is not skipped with
+               *   the use of the style->nopreproc flag.
+               */
+               if (cur->children != NULL) {
+                   xmlChar *prop;
+                   xmlNodePtr text = cur->children, next;
+                   int noesc = 0;
+                       
+                   prop = xmlGetNsProp(cur,
+                       (const xmlChar *)"disable-output-escaping",
+                       NULL);
+                   if (prop != NULL) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+                       xsltGenericDebug(xsltGenericDebugContext,
+                            "Disable escaping: %s\n", text->content);
+#endif
+                       if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
+                           noesc = 1;
+                       } else if (!xmlStrEqual(prop,
+                                               (const xmlChar *)"no")){
+                           xsltTransformError(NULL, style, cur,
+            "xsl:text: disable-output-escaping allows only yes or no\n");
+                           style->warnings++;
+
+                       }
+                       xmlFree(prop);
+                   }
+
+                   while (text != NULL) {
+                       if (text->type == XML_COMMENT_NODE) {
+                           text = text->next;
+                           continue;
+                       }
+                       if ((text->type != XML_TEXT_NODE) &&
+                            (text->type != XML_CDATA_SECTION_NODE)) {
+                           xsltTransformError(NULL, style, cur,
+                "xsltParseTemplateContent: xslt:text content problem\n");
+                           style->errors++;
+                           break;
+                       }
+                       if ((noesc) && (text->type != XML_CDATA_SECTION_NODE))
+                           text->name = xmlStringTextNoenc;
+                       text = text->next;
+                   }
+
+                   /*
+                    * replace xsl:text by the list of childs
+                    */
+                   if (text == NULL) {
+                       text = cur->children;
+                       while (text != NULL) {
+                           if ((style->internalized) &&
+                               (text->content != NULL) &&
+                               (!xmlDictOwns(style->dict, text->content))) {
+
+                               /*
+                                * internalize the text string
+                                */
+                               if (text->doc->dict != NULL) {
+                                   const xmlChar *tmp;
+                                   
+                                   tmp = xmlDictLookup(text->doc->dict,
+                                                       text->content, -1);
+                                   if (tmp != text->content) {
+                                       xmlNodeSetContent(text, NULL);
+                                       text->content = (xmlChar *) tmp;
+                                   }
+                               }
+                           }
+
+                           next = text->next;
+                           xmlUnlinkNode(text);
+                           xmlAddPrevSibling(cur, text);
+                           text = next;
+                       }
+                   }
+               }
+               delete = cur;
+               goto skip_children;
+           }
+       }
+       else if ((cur->ns != NULL) && (style->nsDefs != NULL) &&
+           (xsltCheckExtPrefix(style, cur->ns->prefix)))
+       {
+           /*
+            * okay this is an extension element compile it too
+            */
+           xsltStylePreCompute(style, cur);
+       } else {
+           /*
+            * This is an element which will be output as part of the
+            * template exectution, precompile AVT if found.
+            */
+           if ((cur->ns == NULL) && (style->defaultAlias != NULL) &&
+                       (cur->type == XML_ELEMENT_NODE)) {
+               cur->ns = xmlSearchNsByHref(cur->doc, cur,
+                       style->defaultAlias);
+           }
+           if (cur->properties != NULL) {
+               xmlAttrPtr attr = cur->properties;
+
+               while (attr != NULL) {
+                   xsltCompileAttr(style, attr);
+                   attr = attr->next;
+               }
+           }
+       }
+       /*
+        * Skip to next node
+        */
+       if (cur->children != NULL) {
+           if (cur->children->type != XML_ENTITY_DECL) {
+               cur = cur->children;
+               continue;
+           }
+       }
+skip_children:
+       if (cur->next != NULL) {
+           cur = cur->next;
+           continue;
+       }
+       
+       do {
+           cur = cur->parent;
+           if (cur == NULL)
+               break;
+           if (cur == templ) {
+               cur = NULL;
+               break;
+           }
+           if (cur->next != NULL) {
+               cur = cur->next;
+               break;
+           }
+       } while (cur != NULL);
+    }
+    if (delete != NULL) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+       xsltGenericDebug(xsltGenericDebugContext,
+        "xsltParseTemplateContent: removing text\n");
+#endif
+       xmlUnlinkNode(delete);
+       xmlFreeNode(delete);
+       delete = NULL;
+    }
+
+    /*
+     * Skip the first params
+     */
+    cur = templ->children;
+    while (cur != NULL) {
+       if ((IS_XSLT_ELEM(cur)) && (!(IS_XSLT_NAME(cur, "param"))))
+           break;
+       cur = cur->next;
+    }
+
+    /*
+     * Browse the remainder of the template
+     */
+    while (cur != NULL) {
+       if ((IS_XSLT_ELEM(cur)) && (IS_XSLT_NAME(cur, "param"))) {
+           xmlNodePtr param = cur;
+
+           xsltTransformError(NULL, style, cur,
+               "xsltParseTemplateContent: ignoring misplaced param element\n");
+           if (style != NULL) style->warnings++;
+            cur = cur->next;
+           xmlUnlinkNode(param);
+           xmlFreeNode(param);
+       } else
+           break;
+    }
+}
+
+#endif /* else XSLT_REFACTORED */
+
+/**
+ * xsltParseStylesheetKey:
+ * @style:  the XSLT stylesheet
+ * @key:  the "key" element
+ *
+ * <!-- Category: top-level-element -->
+ * <xsl:key name = qname, match = pattern, use = expression />
+ *
+ * parse an XSLT stylesheet key definition and register it
+ */
+
+static void
+xsltParseStylesheetKey(xsltStylesheetPtr style, xmlNodePtr key) {
+    xmlChar *prop = NULL;
+    xmlChar *use = NULL;
+    xmlChar *match = NULL;
+    xmlChar *name = NULL;
+    xmlChar *nameURI = NULL;
+
+    if ((style == NULL) || (key == NULL))
+       return;
+
+    /*
+     * Get arguments
+     */
+    prop = xmlGetNsProp(key, (const xmlChar *)"name", NULL);
+    if (prop != NULL) {
+        const xmlChar *URI;
+
+       /*
+       * TODO: Don't use xsltGetQNameURI().
+       */
+       URI = xsltGetQNameURI(key, &prop);
+       if (prop == NULL) {
+           if (style != NULL) style->errors++;
+           goto error;
+       } else {
+           name = prop;
+           if (URI != NULL)
+               nameURI = xmlStrdup(URI);
+       }
+#ifdef WITH_XSLT_DEBUG_PARSING
+       xsltGenericDebug(xsltGenericDebugContext,
+            "xsltParseStylesheetKey: name %s\n", name);
+#endif
+    } else {
+       xsltTransformError(NULL, style, key,
+           "xsl:key : error missing name\n");
+       if (style != NULL) style->errors++;
+       goto error;
+    }
+
+    match = xmlGetNsProp(key, (const xmlChar *)"match", NULL);
+    if (match == NULL) {
+       xsltTransformError(NULL, style, key,
+           "xsl:key : error missing match\n");
+       if (style != NULL) style->errors++;
+       goto error;
+    }
+
+    use = xmlGetNsProp(key, (const xmlChar *)"use", NULL);
+    if (use == NULL) {
+       xsltTransformError(NULL, style, key,
+           "xsl:key : error missing use\n");
+       if (style != NULL) style->errors++;
+       goto error;
+    }
+
+    /*
+     * register the keys
+     */
+    xsltAddKey(style, name, nameURI, match, use, key);
+
+
+error:
+    if (use != NULL)
+       xmlFree(use);
+    if (match != NULL)
+       xmlFree(match);
+    if (name != NULL)
+       xmlFree(name);
+    if (nameURI != NULL)
+       xmlFree(nameURI);
+
+    if (key->children != NULL) {
+       xsltParseContentError(style, key->children);
+    }
+}
+
+#ifdef XSLT_REFACTORED
+/**
+ * xsltParseXSLTTemplate:
+ * @style:  the XSLT stylesheet
+ * @template:  the "template" element
+ *
+ * parse an XSLT stylesheet template building the associated structures
+ * TODO: Is @style ever expected to be NULL?
+ *
+ * Called from:
+ *   xsltParseXSLTStylesheet()
+ *   xsltParseStylesheetTop()
+ */
+
+static void
+xsltParseXSLTTemplate(xsltCompilerCtxtPtr cctxt, xmlNodePtr templNode) {
+    xsltTemplatePtr templ;
+    xmlChar *prop;    
+    double  priority;    
+
+    if ((cctxt == NULL) || (templNode == NULL))
+       return;
+
+    /*
+     * Create and link the structure
+     */
+    templ = xsltNewTemplate();
+    if (templ == NULL)
+       return;
+
+    xsltCompilerNodePush(cctxt, templNode);
+    if (templNode->nsDef != NULL)
+       cctxt->inode->inScopeNs =
+           xsltCompilerBuildInScopeNsList(cctxt, templNode);
+
+    templ->next = cctxt->style->templates;
+    cctxt->style->templates = templ;
+    templ->style = cctxt->style;  
+
+    /*
+    * Attribute "mode".
+    */
+    prop = xmlGetNsProp(templNode, (const xmlChar *)"mode", NULL);
+    if (prop != NULL) {        
+        const xmlChar *modeURI;
+
+       /*
+       * TODO: We need a standardized function for extraction
+       *  of namespace names and local names from QNames.
+       *  Don't use xsltGetQNameURI() as it cannot channeö
+       *  reports through the context.
+       */
+       modeURI = xsltGetQNameURI(templNode, &prop);
+       if (prop == NULL) {
+           cctxt->style->errors++;
+           goto error;
+       }
+       templ->mode = xmlDictLookup(cctxt->style->dict, prop, -1);
+       xmlFree(prop);
+       prop = NULL;
+       if (xmlValidateNCName(templ->mode, 0)) {
+           xsltTransformError(NULL, cctxt->style, templNode,
+               "xsl:template: Attribute 'mode': The local part '%s' "
+               "of the value is not a valid NCName.\n", templ->name);
+           cctxt->style->errors++;
+           goto error;
+       }
+       if (modeURI != NULL)
+           templ->modeURI = xmlDictLookup(cctxt->style->dict, modeURI, -1);
+#ifdef WITH_XSLT_DEBUG_PARSING
+       xsltGenericDebug(xsltGenericDebugContext,
+            "xsltParseXSLTTemplate: mode %s\n", templ->mode);
+#endif
+    }
+    /*
+    * Attribute "match".
+    */
+    prop = xmlGetNsProp(templNode, (const xmlChar *)"match", NULL);
+    if (prop != NULL) {
+       templ->match  = prop;
+       prop = NULL;
+    }
+    /*
+    * Attribute "priority".
+    */
+    prop = xmlGetNsProp(templNode, (const xmlChar *)"priority", NULL);
+    if (prop != NULL) {
+       priority = xmlXPathStringEvalNumber(prop);
+       templ->priority = (float) priority;
+       xmlFree(prop);
+       prop = NULL;
+    }
+    /*
+    * Attribute "name".
+    */
+    prop = xmlGetNsProp(templNode, (const xmlChar *)"name", NULL);
+    if (prop != NULL) {
+        const xmlChar *nameURI;
+       xsltTemplatePtr curTempl;
+       
+       /*
+       * TODO: Don't use xsltGetQNameURI().
+       */
+       nameURI = xsltGetQNameURI(templNode, &prop);
+       if (prop == NULL) {
+           cctxt->style->errors++;
+           goto error;
+       }
+       templ->name = xmlDictLookup(cctxt->style->dict, prop, -1);
+       xmlFree(prop);
+       prop = NULL;
+       if (xmlValidateNCName(templ->name, 0)) {
+           xsltTransformError(NULL, cctxt->style, templNode,
+               "xsl:template: Attribute 'name': The local part '%s' of "
+               "the value is not a valid NCName.\n", templ->name);
+           cctxt->style->errors++;
+           goto error;
+       }       
+       if (nameURI != NULL)
+           templ->nameURI = xmlDictLookup(cctxt->style->dict, nameURI, -1);
+       curTempl = templ->next;
+       while (curTempl != NULL) {
+           if ((nameURI != NULL && xmlStrEqual(curTempl->name, templ->name) &&
+               xmlStrEqual(curTempl->nameURI, nameURI) ) ||
+               (nameURI == NULL && curTempl->nameURI == NULL &&
+               xmlStrEqual(curTempl->name, templ->name)))
+           {
+               xsltTransformError(NULL, cctxt->style, templNode,
+                   "xsl:template: error duplicate name '%s'\n", templ->name);
+               cctxt->style->errors++;
+               goto error;
+           }
+           curTempl = curTempl->next;
+       }
+    }
+    if (templNode->children != NULL) {
+       xsltParseTemplateContent(cctxt->style, templNode);      
+       /*
+       * MAYBE TODO: Custom behaviour: In order to stay compatible with
+       * Xalan and MSXML(.NET), we could allow whitespace
+       * to appear before an xml:param element; this whitespace
+       * will additionally become part of the "template".
+       * NOTE that this is totally deviates from the spec, but
+       * is the de facto behaviour of Xalan and MSXML(.NET).
+       * Personally I wouldn't allow this, since if we have:
+       * <xsl:template ...xml:space="preserve">
+       *   <xsl:param name="foo"/>
+       *   <xsl:param name="bar"/>
+       *   <xsl:param name="zoo"/>
+       * ... the whitespace between every xsl:param would be
+       * added to the result tree.
+       */              
+    }    
+    
+    templ->elem = templNode;
+    templ->content = templNode->children;
+    xsltAddTemplate(cctxt->style, templ, templ->mode, templ->modeURI);
+
+error:
+    xsltCompilerNodePop(cctxt, templNode);
+    return;
+}
+
+#else /* XSLT_REFACTORED */
+
+/**
+ * xsltParseStylesheetTemplate:
+ * @style:  the XSLT stylesheet
+ * @template:  the "template" element
+ *
+ * parse an XSLT stylesheet template building the associated structures
+ */
+
+static void
+xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
+    xsltTemplatePtr ret;
+    xmlChar *prop;
+    xmlChar *mode = NULL;
+    xmlChar *modeURI = NULL;
+    double  priority;
+
+    if (template == NULL)
+       return;
+
+    /*
+     * Create and link the structure
+     */
+    ret = xsltNewTemplate();
+    if (ret == NULL)
+       return;
+    ret->next = style->templates;
+    style->templates = ret;
+    ret->style = style;
+   
+    /*
+     * Get inherited namespaces
+     */
+    /*
+    * TODO: Apply the optimized in-scope-namespace mechanism
+    *   as for the other XSLT instructions.
+    */
+    xsltGetInheritedNsList(style, ret, template);
+
+    /*
+     * Get arguments
+     */
+    prop = xmlGetNsProp(template, (const xmlChar *)"mode", NULL);
+    if (prop != NULL) {
+        const xmlChar *URI;
+
+       /*
+       * TODO: Don't use xsltGetQNameURI().
+       */
+       URI = xsltGetQNameURI(template, &prop);
+       if (prop == NULL) {
+           if (style != NULL) style->errors++;
+           goto error;
+       } else {
+           mode = prop;
+           if (URI != NULL)
+               modeURI = xmlStrdup(URI);
+       }
+       ret->mode = xmlDictLookup(style->dict, mode, -1);
+       ret->modeURI = xmlDictLookup(style->dict, modeURI, -1);
+#ifdef WITH_XSLT_DEBUG_PARSING
+       xsltGenericDebug(xsltGenericDebugContext,
+            "xsltParseStylesheetTemplate: mode %s\n", mode);
+#endif
+        if (mode != NULL) xmlFree(mode);
+       if (modeURI != NULL) xmlFree(modeURI);
+    }
+    prop = xmlGetNsProp(template, (const xmlChar *)"match", NULL);
+    if (prop != NULL) {
+       if (ret->match != NULL) xmlFree(ret->match);
+       ret->match  = prop;
+    }
+
+    prop = xmlGetNsProp(template, (const xmlChar *)"priority", NULL);
+    if (prop != NULL) {
+       priority = xmlXPathStringEvalNumber(prop);
+       ret->priority = (float) priority;
+       xmlFree(prop);
+    }
+
+    prop = xmlGetNsProp(template, (const xmlChar *)"name", NULL);
+    if (prop != NULL) {
+        const xmlChar *URI;
+       xsltTemplatePtr cur;
+       
+       /*
+       * TODO: Don't use xsltGetQNameURI().
+       */
+       URI = xsltGetQNameURI(template, &prop);
+       if (prop == NULL) {
+           if (style != NULL) style->errors++;
+           goto error;
+       } else {
+           if (xmlValidateNCName(prop,0)) {
+               xsltTransformError(NULL, style, template,
+                   "xsl:template : error invalid name '%s'\n", prop);
+               if (style != NULL) style->errors++;
+               goto error;
+           }
+           ret->name = xmlDictLookup(style->dict, BAD_CAST prop, -1);
+           xmlFree(prop);
+           prop = NULL;
+           if (URI != NULL)
+               ret->nameURI = xmlDictLookup(style->dict, BAD_CAST URI, -1);
+           else
+               ret->nameURI = NULL;
+           cur = ret->next;
+           while (cur != NULL) {
+               if ((URI != NULL && xmlStrEqual(cur->name, ret->name) &&
+                               xmlStrEqual(cur->nameURI, URI) ) ||
+                   (URI == NULL && cur->nameURI == NULL &&
+                               xmlStrEqual(cur->name, ret->name))) {
+                   xsltTransformError(NULL, style, template,
+                       "xsl:template: error duplicate name '%s'\n", ret->name);
+                   style->errors++;
+                   goto error;
+               }
+               cur = cur->next;
+           }
+       }
+    }
+
+    /*
+     * parse the content and register the pattern
+     */
+    xsltParseTemplateContent(style, template);
+    ret->elem = template;
+    ret->content = template->children;
+    xsltAddTemplate(style, ret, ret->mode, ret->modeURI);
+
+error:
+    return;
+}
+
+#endif /* else XSLT_REFACTORED */
+
+#ifdef XSLT_REFACTORED
+
+/**
+ * xsltIncludeComp:
+ * @cctxt: the compilation contenxt
+ * @node:  the xsl:include node
+ *
+ * Process the xslt include node on the source node
+ */
+static xsltStyleItemIncludePtr
+xsltCompileXSLTIncludeElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node) {
+    xsltStyleItemIncludePtr item;
+
+    if ((cctxt == NULL) || (node == NULL))
+       return(NULL);
+
+    node->psvi = NULL;
+    item = (xsltStyleItemIncludePtr) xmlMalloc(sizeof(xsltStyleItemInclude));
+    if (item == NULL) {
+       xsltTransformError(NULL, cctxt->style, node,
+               "xsltIncludeComp : malloc failed\n");
+       cctxt->style->errors++;
+       return(NULL);
+    }
+    memset(item, 0, sizeof(xsltStyleItemInclude));
+
+    node->psvi = item;
+    item->inst = node;
+    item->type = XSLT_FUNC_INCLUDE;
+
+    item->next = cctxt->style->preComps;
+    cctxt->style->preComps = (xsltElemPreCompPtr) item;
+
+    return(item);
+}
+
+/**
+ * xsltParseFindTopLevelElem:
+ */
+static int
+xsltParseFindTopLevelElem(xsltCompilerCtxtPtr cctxt,
+                             xmlNodePtr cur,
+                             const xmlChar *name,
+                             const xmlChar *namespaceURI,
+                             int breakOnOtherElem,                           
+                             xmlNodePtr *resultNode)
+{
+    if (name == NULL)
+       return(-1);
+
+    *resultNode = NULL;
+    while (cur != NULL) {
+       if (cur->type == XML_ELEMENT_NODE) {
+           if ((cur->ns != NULL) && (cur->name != NULL)) {
+               if ((*(cur->name) == *name) &&
+                   xmlStrEqual(cur->name, name) &&
+                   xmlStrEqual(cur->ns->href, namespaceURI))               
+               {
+                   *resultNode = cur;
+                   return(1);
+               }
+           }
+           if (breakOnOtherElem)
+               break;
+       }
+       cur = cur->next;
+    }
+    *resultNode = cur;
+    return(0);
+}
+
+static int
+xsltParseTopLevelXSLTElem(xsltCompilerCtxtPtr cctxt,
+                         xmlNodePtr node,
+                         xsltStyleType type)
+{
+    int ret = 0;
+
+    /*
+    * TODO: The reason why this function exists:
+    *  due to historical reasons some of the
+    *  top-level declarations are processed by functions
+    *  in other files. Since we need still to set
+    *  up the node-info and generate information like
+    *  in-scope namespaces, this is a wrapper around
+    *  those old parsing functions.
+    */
+    xsltCompilerNodePush(cctxt, node);
+    if (node->nsDef != NULL)
+       cctxt->inode->inScopeNs =
+           xsltCompilerBuildInScopeNsList(cctxt, node);
+    cctxt->inode->type = type;
+
+    switch (type) {
+       case XSLT_FUNC_INCLUDE:
+           {
+               int oldIsInclude;
+
+               if (xsltCompileXSLTIncludeElem(cctxt, node) == NULL)
+                   goto exit;          
+               /*
+               * Mark this stylesheet tree as being currently included.
+               */
+               oldIsInclude = cctxt->isInclude;
+               cctxt->isInclude = 1;
+                                               
+               if (xsltParseStylesheetInclude(cctxt->style, node) != 0) {
+                   cctxt->style->errors++;
+               }
+               cctxt->isInclude = oldIsInclude;
+           }
+           break;
+       case XSLT_FUNC_PARAM:
+           xsltStylePreCompute(cctxt->style, node);
+           xsltParseGlobalParam(cctxt->style, node);
+           break;
+       case XSLT_FUNC_VARIABLE:
+           xsltStylePreCompute(cctxt->style, node);
+           xsltParseGlobalVariable(cctxt->style, node);
+           break;
+       case XSLT_FUNC_ATTRSET:
+           xsltParseStylesheetAttributeSet(cctxt->style, node);
+           break;
+       default:
+           xsltTransformError(NULL, cctxt->style, node,
+               "Internal error: (xsltParseTopLevelXSLTElem) "
+               "Cannot handle this top-level declaration.\n");
+           cctxt->style->errors++;
+           ret = -1;
+    }
+
+exit:
+    xsltCompilerNodePop(cctxt, node);
+
+    return(ret);
+}
+
+#if 0
+static int
+xsltParseRemoveWhitespace(xmlNodePtr node)
+{
+    if ((node == NULL) || (node->children == NULL))
+       return(0);
+    else {
+       xmlNodePtr delNode = NULL, child = node->children;
+
+       do {
+           if (delNode) {
+               xmlUnlinkNode(delNode);
+               xmlFreeNode(delNode);
+               delNode = NULL;
+           }
+           if (((child->type == XML_TEXT_NODE) ||
+                (child->type == XML_CDATA_SECTION_NODE)) &&
+               (IS_BLANK_NODE(child)))
+               delNode = child;            
+           child = child->next;
+       } while (child != NULL);
+       if (delNode) {
+           xmlUnlinkNode(delNode);
+           xmlFreeNode(delNode);
+           delNode = NULL;
+       }
+    }
+    return(0);
+}
+#endif
+
+static int
+xsltParseXSLTStylesheetElemCore(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
+{
+#ifdef WITH_XSLT_DEBUG_PARSING
+    int templates = 0;
+#endif
+    xmlNodePtr cur, start = NULL;
+    xsltStylesheetPtr style;
+
+    if ((cctxt == NULL) || (node == NULL) ||
+       (node->type != XML_ELEMENT_NODE))
+       return(-1);    
+
+    style = cctxt->style;    
+    /*
+    * At this stage all import declarations of all stylesheet modules
+    * with the same stylesheet level have been processed.
+    * Now we can safely parse the rest of the declarations.
+    */
+    if (IS_XSLT_ELEM_FAST(node) && IS_XSLT_NAME(node, "include"))
+    {
+       xsltDocumentPtr include;
+       /*
+       * URGENT TODO: Make this work with simplified stylesheets!
+       *   I.e., when we won't find an xsl:stylesheet element.
+       */
+       /*
+       * This is as include declaration.
+       */
+       include = ((xsltStyleItemIncludePtr) node->psvi)->include;
+       if (include == NULL) {
+           /* TODO: raise error? */
+           return(-1);
+       }
+       /*
+       * TODO: Actually an xsl:include should locate an embedded
+       *  stylesheet as well; so the document-element won't always
+       *  be the element where the actual stylesheet is rooted at.
+       *  But such embedded stylesheets are not supported by Libxslt yet.
+       */
+       node = xmlDocGetRootElement(include->doc);
+       if (node == NULL) {
+           return(-1);
+       }
+    }    
+    
+    if (node->children == NULL)
+       return(0);
+    /*
+    * Push the xsl:stylesheet/xsl:transform element.
+    */  
+    xsltCompilerNodePush(cctxt, node);
+    cctxt->inode->isRoot = 1;
+    cctxt->inode->nsChanged = 0;
+    /*
+    * Start with the naked dummy info for literal result elements.
+    */
+    cctxt->inode->litResElemInfo = cctxt->inodeList->litResElemInfo;
+
+    /*
+    * In every case, we need to have
+    * the in-scope namespaces of the element, where the
+    * stylesheet is rooted at, regardless if it's an XSLT
+    * instruction or a literal result instruction (or if
+    * this is an embedded stylesheet).
+    */         
+    cctxt->inode->inScopeNs =
+       xsltCompilerBuildInScopeNsList(cctxt, node);
+
+    /*
+    * Process attributes of xsl:stylesheet/xsl:transform.
+    * --------------------------------------------------
+    * Allowed are:
+    *  id = id
+    *  extension-element-prefixes = tokens
+    *  exclude-result-prefixes = tokens
+    *  version = number (mandatory)    
+    */
+    if (xsltParseAttrXSLTVersion(cctxt, node,
+       XSLT_ELEMENT_CATEGORY_XSLT) == 0)
+    {    
+       /*
+       * Attribute "version".
+       * XSLT 1.0: "An xsl:stylesheet element *must* have a version
+       *  attribute, indicating the version of XSLT that the
+       *  stylesheet requires".
+       * The root element of a simplified stylesheet must also have
+       * this attribute.
+       */
+#ifdef XSLT_REFACTORED_MANDATORY_VERSION
+       if (isXsltElem)
+           xsltTransformError(NULL, cctxt->style, node,
+               "The attribute 'version' is missing.\n");
+       cctxt->style->errors++; 
+#else
+       /* OLD behaviour. */
+       xsltTransformError(NULL, cctxt->style, node,
+           "xsl:version is missing: document may not be a stylesheet\n");
+       cctxt->style->warnings++;
+#endif
+    }    
+    /*
+    * The namespaces declared by the attributes
+    *  "extension-element-prefixes" and
+    *  "exclude-result-prefixes" are local to *this*
+    *  stylesheet tree; i.e., they are *not* visible to
+    *  other stylesheet-modules, whether imported or included.
+    * 
+    * Attribute "extension-element-prefixes".
+    */
+    cctxt->inode->extElemNs =
+       xsltParseExtElemPrefixes(cctxt, node, NULL,
+           XSLT_ELEMENT_CATEGORY_XSLT);
+    /*
+    * Attribute "exclude-result-prefixes".
+    */
+    cctxt->inode->exclResultNs =
+       xsltParseExclResultPrefixes(cctxt, node, NULL,
+           XSLT_ELEMENT_CATEGORY_XSLT);
+    /*
+    * Create/reuse info for the literal result element.
+    */
+    if (cctxt->inode->nsChanged)
+       xsltLREInfoCreate(cctxt, node, 0);
+    /*
+    * Processed top-level elements:
+    * ----------------------------
+    *  xsl:variable, xsl:param (QName, in-scope ns,
+    *    expression (vars allowed))
+    *  xsl:attribute-set (QName, in-scope ns)
+    *  xsl:strip-space, xsl:preserve-space (XPath NameTests,
+    *    in-scope ns)
+    *    I *think* global scope, merge with includes
+    *  xsl:output (QName, in-scope ns)
+    *  xsl:key (QName, in-scope ns, pattern,
+    *    expression (vars *not* allowed))
+    *  xsl:decimal-format (QName, needs in-scope ns)
+    *  xsl:namespace-alias (in-scope ns)
+    *    global scope, merge with includes
+    *  xsl:template (last, QName, pattern)
+    *
+    * (whitespace-only text-nodes have *not* been removed
+    *  yet; this will be done in xsltParseSequenceConstructor)
+    *
+    * Report misplaced child-nodes first.
+    */
+    cur = node->children;
+    while (cur != NULL) {
+       if (cur->type == XML_TEXT_NODE) {
+           xsltTransformError(NULL, style, cur,
+               "Misplaced text node (content: '%s').\n",
+               (cur->content != NULL) ? cur->content : BAD_CAST "");
+           style->errors++;
+       } else if (cur->type != XML_ELEMENT_NODE) {
+           xsltTransformError(NULL, style, cur, "Misplaced node.\n");
+           style->errors++;
+       }
+       cur = cur->next;
+    }
+    /*
+    * Skip xsl:import elements; they have been processed
+    * already.
+    */
+    cur = node->children;
+    while ((cur != NULL) && xsltParseFindTopLevelElem(cctxt, cur,
+           BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)
+       cur = cur->next;
+    if (cur == NULL)
+       goto exit;
+
+    start = cur;
+    /*
+    * Process all top-level xsl:param elements.
+    */
+    while ((cur != NULL) &&
+       xsltParseFindTopLevelElem(cctxt, cur,
+       BAD_CAST "param", XSLT_NAMESPACE, 0, &cur) == 1)
+    {
+       xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_PARAM); 
+       cur = cur->next;
+    }  
+    /*
+    * Process all top-level xsl:variable elements.
+    */
+    cur = start;
+    while ((cur != NULL) &&
+       xsltParseFindTopLevelElem(cctxt, cur,
+       BAD_CAST "variable", XSLT_NAMESPACE, 0, &cur) == 1)
+    {
+       xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_VARIABLE);
+       cur = cur->next;
+    }   
+    /*
+    * Process all the rest of top-level elements.
+    */
+    cur = start;
+    while (cur != NULL) {      
+       /*
+       * Process element nodes.
+       */
+       if (cur->type == XML_ELEMENT_NODE) {        
+           if (cur->ns == NULL) {
+               xsltTransformError(NULL, style, cur,
+                   "Unexpected top-level element in no namespace.\n");
+               style->errors++;
+               cur = cur->next;
+               continue;
+           }
+           /*
+           * Process all XSLT elements.
+           */
+           if (IS_XSLT_ELEM_FAST(cur)) {
+               /*
+               * xsl:import is only allowed at the beginning.
+               */
+               if (IS_XSLT_NAME(cur, "import")) {
+                   xsltTransformError(NULL, style, cur,
+                       "Misplaced xsl:import element.\n");
+                   style->errors++;
+                   cur = cur->next;
+                   continue;
+               }
+               /* 
+               * TODO: Change the return type of the parsing functions
+               *  to int.
+               */
+               if (IS_XSLT_NAME(cur, "template")) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+                   templates++;
+#endif
+                   /*
+                   * TODO: Is the position of xsl:template in the
+                   *  tree significant? If not it would be easier to
+                   *  parse them at a later stage.
+                   */
+                   xsltParseXSLTTemplate(cctxt, cur);
+               } else if (IS_XSLT_NAME(cur, "variable")) {
+                   /* NOP; done already */
+               } else if (IS_XSLT_NAME(cur, "param")) {
+                   /* NOP; done already */
+               } else if (IS_XSLT_NAME(cur, "include")) {                  
+                   if (cur->psvi != NULL)                  
+                       xsltParseXSLTStylesheetElemCore(cctxt, cur);
+                   else {
+                       xsltTransformError(NULL, style, cur,
+                           "Internal error: "
+                           "(xsltParseXSLTStylesheetElemCore) "
+                           "The xsl:include element was not compiled.\n");
+                       style->errors++;
+                   }
+               } else if (IS_XSLT_NAME(cur, "strip-space")) {
+                   /* No node info needed. */
+                   xsltParseStylesheetStripSpace(style, cur);
+               } else if (IS_XSLT_NAME(cur, "preserve-space")) {
+                   /* No node info needed. */
+                   xsltParseStylesheetPreserveSpace(style, cur);
+               } else if (IS_XSLT_NAME(cur, "output")) {
+                   /* No node-info needed. */
+                   xsltParseStylesheetOutput(style, cur);
+               } else if (IS_XSLT_NAME(cur, "key")) {
+                   /* TODO: node-info needed for expressions ? */
+                   xsltParseStylesheetKey(style, cur);
+               } else if (IS_XSLT_NAME(cur, "decimal-format")) {
+                   /* No node-info needed. */               
+                   xsltParseStylesheetDecimalFormat(style, cur);
+               } else if (IS_XSLT_NAME(cur, "attribute-set")) {                    
+                   xsltParseTopLevelXSLTElem(cctxt, cur,
+                       XSLT_FUNC_ATTRSET);             
+               } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
+                   /* NOP; done already */                 
+               } else {
+                   if (cctxt->inode->forwardsCompat) {
+                       /*
+                       * Forwards-compatible mode:
+                       *
+                       * XSLT-1: "if it is a top-level element and
+                       *  XSLT 1.0 does not allow such elements as top-level
+                       *  elements, then the element must be ignored along
+                       *  with its content;"
+                       */
+                       /*
+                       * TODO: I don't think we should generate a warning.
+                       */
+                       xsltTransformError(NULL, style, cur,
+                           "Forwards-compatible mode: Ignoring unknown XSLT "
+                           "element '%s'.\n", cur->name);
+                       style->warnings++;
+                   } else {
+                       xsltTransformError(NULL, style, cur,
+                           "Unknown XSLT element '%s'.\n", cur->name);
+                       style->errors++;
+                   }
+               }
+           } else {
+               xsltTopLevelFunction function;
+
+               /*
+               * Process non-XSLT elements, which are in a
+               *  non-NULL namespace.
+               */
+               /*
+               * QUESTION: What does xsltExtModuleTopLevelLookup()
+               *  do exactly?
+               */
+               function = xsltExtModuleTopLevelLookup(cur->name,
+                   cur->ns->href);
+               if (function != NULL)
+                   function(style, cur);
+#ifdef WITH_XSLT_DEBUG_PARSING
+               xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltParseXSLTStylesheetElemCore : User-defined "
+                   "data element '%s'.\n", cur->name);
+#endif
+           }
+       }
+       cur = cur->next;
+    }
+
+exit:
+
+#ifdef WITH_XSLT_DEBUG_PARSING
+    xsltGenericDebug(xsltGenericDebugContext,
+       "### END of parsing top-level elements of doc '%s'.\n",
+       node->doc->URL);
+    xsltGenericDebug(xsltGenericDebugContext,
+       "### Templates: %d\n", templates);
+#ifdef XSLT_REFACTORED
+    xsltGenericDebug(xsltGenericDebugContext,
+       "### Max inodes: %d\n", cctxt->maxNodeInfos);
+    xsltGenericDebug(xsltGenericDebugContext,
+       "### Max LREs  : %d\n", cctxt->maxLREs);
+#endif /* XSLT_REFACTORED */
+#endif /* WITH_XSLT_DEBUG_PARSING */
+
+    xsltCompilerNodePop(cctxt, node);
+    return(0);
+}
+
+/**
+ * xsltParseXSLTStylesheet:
+ * @cctxt: the compiler context
+ * @node: the xsl:stylesheet/xsl:transform element-node
+ *
+ * Parses the xsl:stylesheet and xsl:transform element. 
+ *
+ * <xsl:stylesheet
+ *  id = id
+ *  extension-element-prefixes = tokens
+ *  exclude-result-prefixes = tokens
+ *  version = number>
+ *  <!-- Content: (xsl:import*, top-level-elements) -->
+ * </xsl:stylesheet>
+ *
+ * BIG TODO: The xsl:include stuff.
+ * 
+ * Called by xsltParseStylesheetTree()
+ *
+ * Returns 0 on success, a positive result on errors and
+ *         -1 on API or internal errors.
+ */
+static int
+xsltParseXSLTStylesheetElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
+{
+    xmlNodePtr cur, start;
+
+    if ((cctxt == NULL) || (node == NULL))
+       return(-1);
+    
+    if (node->children == NULL)
+       goto exit;
+
+    /*
+    * Process top-level elements:
+    *  xsl:import (must be first)
+    *  xsl:include (this is just a pre-processing)
+    */
+    cur = node->children;
+    /*
+    * Process xsl:import elements.
+    * XSLT 1.0: "The xsl:import element children must precede all
+    *  other element children of an xsl:stylesheet element,
+    *  including any xsl:include element children."
+    */    
+    while ((cur != NULL) &&
+       xsltParseFindTopLevelElem(cctxt, cur,
+           BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)
+    {
+       if (xsltParseStylesheetImport(cctxt->style, cur) != 0) {
+           cctxt->style->errors++;
+       }
+       cur = cur->next;
+    }
+    if (cur == NULL)
+       goto exit;
+    start = cur;
+    /*
+    * Pre-process all xsl:include elements.
+    */
+    cur = start;
+    while ((cur != NULL) &&
+       xsltParseFindTopLevelElem(cctxt, cur,
+           BAD_CAST "include", XSLT_NAMESPACE, 0, &cur) == 1)
+    {
+       xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_INCLUDE);
+       cur = cur->next;
+    }
+    /*
+    * Pre-process all xsl:namespace-alias elements.
+    * URGENT TODO: This won't work correctly: the order of included
+    *  aliases and aliases defined here is significant.
+    */
+    cur = start;
+    while ((cur != NULL) &&
+       xsltParseFindTopLevelElem(cctxt, cur,
+           BAD_CAST "namespace-alias", XSLT_NAMESPACE, 0, &cur) == 1)
+    {
+       xsltNamespaceAlias(cctxt->style, cur);
+       cur = cur->next;
+    }
+
+    if (cctxt->isInclude) {
+       /*
+       * If this stylesheet is intended for inclusion, then
+       * we will process only imports and includes. 
+       */
+       goto exit;
+    } 
+    /*
+    * Now parse the rest of the top-level elements.
+    */
+    xsltParseXSLTStylesheetElemCore(cctxt, node);      
+exit:
+
+    return(0);
+}
+
+#else /* XSLT_REFACTORED */
+
+/**
+ * xsltParseStylesheetTop:
+ * @style:  the XSLT stylesheet
+ * @top:  the top level "stylesheet" or "transform" element
+ *
+ * scan the top level elements of an XSL stylesheet
+ */
+static void
+xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
+    xmlNodePtr cur;
+    xmlChar *prop;
+#ifdef WITH_XSLT_DEBUG_PARSING
+    int templates = 0;
+#endif
+
+    if (top == NULL)
+       return;
+
+    prop = xmlGetNsProp(top, (const xmlChar *)"version", NULL);
+    if (prop == NULL) {
+       xsltTransformError(NULL, style, top,
+           "xsl:version is missing: document may not be a stylesheet\n");
+       if (style != NULL) style->warnings++;
+    } else {
+       if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
+            (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
+           xsltTransformError(NULL, style, top,
+               "xsl:version: only 1.0 features are supported\n");
+            /* TODO set up compatibility when not XSLT 1.0 */
+           if (style != NULL) style->warnings++;
+       }
+       xmlFree(prop);
+    }
+
+    cur = top->children;
+
+    /*
+     * process xsl:import elements
+     */
+    while (cur != NULL) {
+           if (IS_BLANK_NODE(cur)) {
+                   cur = cur->next;
+                   continue;
+           }
+           if (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "import")) {
+                   if (xsltParseStylesheetImport(style, cur) != 0)
+                           if (style != NULL) style->errors++;
+           } 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_TEXT_NODE) {
+           if (cur->content != NULL) {
+               xsltTransformError(NULL, style, cur,
+                   "misplaced text node: '%s'\n", cur->content);
+           }
+           if (style != NULL) style->errors++;
+            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);
+           if (style != NULL) style->errors++;
+           cur = cur->next;
+           continue;
+       }
+       if ((cur->type == XML_ELEMENT_NODE) && (!(IS_XSLT_ELEM(cur)))) {
+           xsltTopLevelFunction 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",
+                   cur->name);
+#endif
+            cur = cur->next;
+           continue;
+       }
+       if (IS_XSLT_NAME(cur, "import")) {
+           xsltTransformError(NULL, style, cur,
+                       "xsltParseStylesheetTop: ignoring misplaced import element\n");
+           if (style != NULL) style->errors++;
+    } else if (IS_XSLT_NAME(cur, "include")) {
+           if (xsltParseStylesheetInclude(style, cur) != 0)
+               if (style != NULL) style->errors++;
+    } else if (IS_XSLT_NAME(cur, "strip-space")) {
+           xsltParseStylesheetStripSpace(style, cur);
+    } else if (IS_XSLT_NAME(cur, "preserve-space")) {
+           xsltParseStylesheetPreserveSpace(style, cur);
+    } else if (IS_XSLT_NAME(cur, "output")) {
+           xsltParseStylesheetOutput(style, cur);
+    } else if (IS_XSLT_NAME(cur, "key")) {
+           xsltParseStylesheetKey(style, cur);
+    } else if (IS_XSLT_NAME(cur, "decimal-format")) {
+           xsltParseStylesheetDecimalFormat(style, cur);
+    } else if (IS_XSLT_NAME(cur, "attribute-set")) {
+           xsltParseStylesheetAttributeSet(style, cur);
+    } else if (IS_XSLT_NAME(cur, "variable")) {
+           xsltParseGlobalVariable(style, cur);
+    } else if (IS_XSLT_NAME(cur, "param")) {
+           xsltParseGlobalParam(style, cur);
+    } else if (IS_XSLT_NAME(cur, "template")) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+           templates++;
+#endif
+           xsltParseStylesheetTemplate(style, cur);
+    } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
+           xsltNamespaceAlias(style, cur);
+       } else {
+           /*
+           * BUG TODO: The version of the *doc* is irrelevant for
+           *  the forwards-compatible mode.
+           */
+            if ((style != NULL) && (style->doc->version != NULL) &&
+               (!strncmp((const char *) style->doc->version, "1.0", 3))) {
+               xsltTransformError(NULL, style, cur,
+                       "xsltParseStylesheetTop: unknown %s element\n",
+                       cur->name);
+               if (style != NULL) style->errors++;
+           }
+           else {
+                /* do Forwards-Compatible Processing */
+               xsltTransformError(NULL, style, cur,
+                       "xsltParseStylesheetTop: ignoring unknown %s element\n",
+                       cur->name);
+               if (style != NULL) style->warnings++;
+            }
+       }
+       cur = cur->next;
+    }
+#ifdef WITH_XSLT_DEBUG_PARSING
+    xsltGenericDebug(xsltGenericDebugContext,
+                   "parsed %d templates\n", templates);
+#endif
+}
+
+#endif /* else of XSLT_REFACTORED */
+
+#ifdef XSLT_REFACTORED
+/**
+ * xsltParseSimplifiedStylesheetTree:
+ *
+ * @style: the stylesheet (TODO: Change this to the compiler context)
+ * @doc: the document containing the stylesheet.
+ * @node: the node where the stylesheet is rooted at
+ *
+ * Returns 0 in case of success, a positive result if an error occurred
+ *         and -1 on API and internal errors.
+ */
+static int
+xsltParseSimplifiedStylesheetTree(xsltCompilerCtxtPtr cctxt,
+                                 xmlDocPtr doc,
+                                 xmlNodePtr node)
+{
+    xsltTemplatePtr templ;
+    
+    if ((cctxt == NULL) || (node == NULL))
+       return(-1);
+
+    if (xsltParseAttrXSLTVersion(cctxt, node, 0) == XSLT_ELEMENT_CATEGORY_LRE)
+    {
+       /*
+       * TODO: Adjust report, since this might be an
+       * embedded stylesheet.
+       */
+       xsltTransformError(NULL, cctxt->style, node,
+           "The attribute 'xsl:version' is missing; cannot identify "
+           "this document as an XSLT stylesheet document.\n");
+       cctxt->style->errors++;
+       return(1);
+    }
+    
+#ifdef WITH_XSLT_DEBUG_PARSING
+    xsltGenericDebug(xsltGenericDebugContext,
+       "xsltParseSimplifiedStylesheetTree: document is stylesheet\n");
+#endif        
+    
+    /*
+    * Create and link the template
+    */
+    templ = xsltNewTemplate();
+    if (templ == NULL) {
+       return(-1);
+    }
+    templ->next = cctxt->style->templates;
+    cctxt->style->templates = templ;
+    templ->match = xmlStrdup(BAD_CAST "/");
+
+    /*
+    * Note that we push the document-node in this special case.
+    */
+    xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);
+    /*
+    * In every case, we need to have
+    * the in-scope namespaces of the element, where the
+    * stylesheet is rooted at, regardless if it's an XSLT
+    * instruction or a literal result instruction (or if
+    * this is an embedded stylesheet).
+    */
+    cctxt->inode->inScopeNs =
+       xsltCompilerBuildInScopeNsList(cctxt, node);
+    /*
+    * Parse the content and register the match-pattern.
+    */
+    xsltParseSequenceConstructor(cctxt, node);
+    xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);
+
+    templ->elem = (xmlNodePtr) doc;
+    templ->content = node;
+    xsltAddTemplate(cctxt->style, templ, NULL, NULL);
+    cctxt->style->literal_result = 1;
+    return(0);
+}
+
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+int
+xsltRestoreDocumentNamespaces(xsltNsMapPtr ns, xmlDocPtr doc)
+{
+    if (doc == NULL)
+       return(-1);
+    /*
+    * Revert the changes we have applied to the namespace-URIs of
+    * ns-decls.
+    */    
+    while (ns != NULL) {
+       if ((ns->doc == doc) && (ns->ns != NULL)) {
+           ns->ns->href = ns->origNsName;
+           ns->origNsName = NULL;
+           ns->ns = NULL;          
+       }
+       ns = ns->next;
+    }
+    return(0);
+}
+#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
+
+/**
+ * xsltParseStylesheetProcess:
+ * @style:  the XSLT stylesheet (the current stylesheet-level)
+ * @doc:  and xmlDoc parsed XML
+ *
+ * Parses an XSLT stylesheet, adding the associated structures.
+ * Called by:
+ *  xsltParseStylesheetImportedDoc() (xslt.c)
+ *  xsltParseStylesheetInclude() (imports.c)
+ *
+ * Returns the value of the @style parameter if everything
+ * went right, NULL if something went amiss.
+ */
+xsltStylesheetPtr
+xsltParseStylesheetProcess(xsltStylesheetPtr style, xmlDocPtr doc)
+{
+    xsltCompilerCtxtPtr cctxt;
+    xmlNodePtr cur;
+    int oldIsSimplifiedStylesheet;
+
+
+    if ((style == NULL) || (doc == NULL))
+       return(NULL);
+
+    cctxt = XSLT_CCTXT(style);
+
+    cur = xmlDocGetRootElement(doc);
+    if (cur == NULL) {
+       xsltTransformError(NULL, style, (xmlNodePtr) doc,
+               "xsltParseStylesheetProcess : empty stylesheet\n");
+       return(NULL);
+    }
+    oldIsSimplifiedStylesheet = cctxt->simplified;
+
+    if ((IS_XSLT_ELEM(cur)) && 
+       ((IS_XSLT_NAME(cur, "stylesheet")) ||
+        (IS_XSLT_NAME(cur, "transform")))) {   
+#ifdef WITH_XSLT_DEBUG_PARSING
+       xsltGenericDebug(xsltGenericDebugContext,
+               "xsltParseStylesheetProcess : found stylesheet\n");
+#endif
+       cctxt->simplified = 0;
+       style->literal_result = 0;
+    } else {
+       cctxt->simplified = 1;
+       style->literal_result = 1;
+    }
+    /*
+    * Pre-process the stylesheet if not already done before.
+    *  This will remove PIs and comments, merge adjacent
+    *  text nodes, internalize strings, etc.
+    */
+    if (! style->nopreproc)
+       xsltParsePreprocessStylesheetTree(cctxt, cur);
+    /*
+    * Parse and compile the stylesheet.
+    */
+    if (style->literal_result == 0) {
+       if (xsltParseXSLTStylesheetElem(cctxt, cur) != 0)
+           return(NULL);
+    } else {
+       if (xsltParseSimplifiedStylesheetTree(cctxt, doc, cur) != 0)
+           return(NULL);
+    }    
+
+    cctxt->simplified = oldIsSimplifiedStylesheet;
+
+    return(style);
+}
+
+#else /* XSLT_REFACTORED */
+
+xsltStylesheetPtr
+xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
+    xmlNodePtr cur;
+
+    if (doc == NULL)
+       return(NULL);
+    if (ret == NULL)
+       return(ret);
+    
+    /*
+     * First steps, remove blank nodes,
+     * locate the xsl:stylesheet element and the
+     * namespace declaration.
+     */
+    cur = xmlDocGetRootElement(doc);
+    if (cur == NULL) {
+       xsltTransformError(NULL, ret, (xmlNodePtr) doc,
+               "xsltParseStylesheetProcess : empty stylesheet\n");
+       return(NULL);
+    }
+
+    if ((IS_XSLT_ELEM(cur)) && 
+       ((IS_XSLT_NAME(cur, "stylesheet")) ||
+        (IS_XSLT_NAME(cur, "transform")))) {   
+#ifdef WITH_XSLT_DEBUG_PARSING
+       xsltGenericDebug(xsltGenericDebugContext,
+               "xsltParseStylesheetProcess : found stylesheet\n");
+#endif
+       ret->literal_result = 0;
+       xsltParseStylesheetExcludePrefix(ret, cur, 1);
+       xsltParseStylesheetExtPrefix(ret, cur, 1);
+    } else {
+       xsltParseStylesheetExcludePrefix(ret, cur, 0);
+       xsltParseStylesheetExtPrefix(ret, cur, 0);
+       ret->literal_result = 1;
+    }
+    if (!ret->nopreproc) {
+       xsltPrecomputeStylesheet(ret, cur);
+    }
+    if (ret->literal_result == 0) {
+       xsltParseStylesheetTop(ret, cur);
+    } else {
+       xmlChar *prop;
+       xsltTemplatePtr template;
+
+       /*
+        * the document itself might be the template, check xsl:version
+        */
+       prop = xmlGetNsProp(cur, (const xmlChar *)"version", XSLT_NAMESPACE);
+       if (prop == NULL) {
+           xsltTransformError(NULL, ret, cur,
+               "xsltParseStylesheetProcess : document is not a stylesheet\n");
+           return(NULL);
+       }
+
+#ifdef WITH_XSLT_DEBUG_PARSING
+        xsltGenericDebug(xsltGenericDebugContext,
+               "xsltParseStylesheetProcess : document is stylesheet\n");
+#endif
+       
+       if (!xmlStrEqual(prop, (const xmlChar *)"1.0")) {
+           xsltTransformError(NULL, ret, cur,
+               "xsl:version: only 1.0 features are supported\n");
+            /* TODO set up compatibility when not XSLT 1.0 */
+           ret->warnings++;
+       }
+       xmlFree(prop);
+
+       /*
+        * Create and link the template
+        */
+       template = xsltNewTemplate();
+       if (template == NULL) {
+           return(NULL);
+       }
+       template->next = ret->templates;
+       ret->templates = template;
+       template->match = xmlStrdup((const xmlChar *)"/");
+
+       /*
+        * parse the content and register the pattern
+        */
+       xsltParseTemplateContent(ret, (xmlNodePtr) doc);
+       template->elem = (xmlNodePtr) doc;
+       template->content = doc->children;
+       xsltAddTemplate(ret, template, NULL, NULL);
+       ret->literal_result = 1;        
+    }
+
+    return(ret);
+}
+
+#endif /* else of XSLT_REFACTORED */
+
+/**
+ * xsltParseStylesheetImportedDoc:
+ * @doc:  an xmlDoc parsed XML
+ * @style: pointer to the parent stylesheet (if it exists)
+ *
+ * parse an XSLT stylesheet building the associated structures
+ * except the processing not needed for imported documents.
+ *
+ * Returns a new XSLT stylesheet structure.
+ */
+
+xsltStylesheetPtr
+xsltParseStylesheetImportedDoc(xmlDocPtr doc,
+                              xsltStylesheetPtr parentStyle) {
+    xsltStylesheetPtr retStyle;
+
+    if (doc == NULL)
+       return(NULL);
+
+    retStyle = xsltNewStylesheet();
+    if (retStyle == NULL)
+       return(NULL);
+    /*
+    * Set the importing stylesheet module; also used to detect recursion.
+    */
+    retStyle->parent = parentStyle;
+    /*
+    * Adjust the string dict.
+    */
+    if (doc->dict != NULL) {
+        xmlDictFree(retStyle->dict);
+       retStyle->dict = doc->dict;
+#ifdef WITH_XSLT_DEBUG
+        xsltGenericDebug(xsltGenericDebugContext,
+           "reusing dictionary from %s for stylesheet\n",
+           doc->URL);
+#endif
+       xmlDictReference(retStyle->dict);
+    }          
+    
+    /*
+    * TODO: Eliminate xsltGatherNamespaces(); we must not restrict
+    *  the stylesheet to containt distinct namespace prefixes.
+    */
+    xsltGatherNamespaces(retStyle);
+
+#ifdef XSLT_REFACTORED
+    {
+       xsltCompilerCtxtPtr cctxt;
+       xsltStylesheetPtr oldCurSheet;
+           
+       if (parentStyle == NULL) {
+           xsltPrincipalStylesheetDataPtr principalData;
+           /*
+           * Principal stylesheet
+           * --------------------
+           */
+           retStyle->principal = retStyle;
+           /*
+           * Create extra data for the principal stylesheet.
+           */
+           principalData = xsltNewPrincipalStylesheetData();
+           if (principalData == NULL) {
+               xsltFreeStylesheet(retStyle);
+               return(NULL);
+           }
+           retStyle->principalData = principalData;
+           /*
+           * Create the compilation context
+           * ------------------------------
+           * (only once; for the principal stylesheet).
+           * This is currently the only function where the
+           * compilation context is created.
+           */
+           cctxt = xsltCompilationCtxtCreate(retStyle);
+           if (cctxt == NULL) {
+               xsltFreeStylesheet(retStyle);
+               return(NULL);
+           }               
+           retStyle->compCtxt = (void *) cctxt;
+           cctxt->style = retStyle;
+           cctxt->dict = retStyle->dict;
+           cctxt->psData = principalData;
+           /*
+           * Push initial dummy node info.
+           */
+           cctxt->depth = -1;
+           xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);
+       } else {
+           /*
+           * Imported stylesheet.
+           */
+           retStyle->principal = parentStyle->principal;
+           cctxt = parentStyle->compCtxt;
+           retStyle->compCtxt = cctxt;
+       }
+       /*
+       * Save the old and set the current stylesheet structure in the
+       * compilation context.
+       */
+       oldCurSheet = cctxt->style;
+       cctxt->style = retStyle;
+       
+       retStyle->doc = doc;
+       xsltParseStylesheetProcess(retStyle, doc);
+       
+       cctxt->style = oldCurSheet;
+       if (parentStyle == NULL) {
+           /*
+           * Pop the initial dummy node info.
+           */
+           xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);
+       } else {
+           /*
+           * Clear the compilation context of imported
+           * stylesheets.
+           * TODO: really?
+           */
+           /* retStyle->compCtxt = NULL; */
+       }
+       /*
+       * Free the stylesheet if there were errors.
+       */
+       if (retStyle != NULL) {
+           if (retStyle->errors != 0) {
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+               /*
+               * Restore all changes made to namespace URIs of ns-decls.
+               */
+               if (cctxt->psData->nsMap)               
+                   xsltRestoreDocumentNamespaces(cctxt->psData->nsMap, doc);
+#endif
+               /*
+               * Detach the doc from the stylesheet; otherwise the doc
+               * will be freed in xsltFreeStylesheet().
+               */
+               retStyle->doc = NULL;
+               /*
+               * Cleanup the doc if its the main stylesheet.
+               */
+               if (parentStyle == NULL) {
+                   xsltCleanupStylesheetTree(doc, xmlDocGetRootElement(doc));
+                   if (retStyle->compCtxt != NULL) {                   
+                       xsltCompilationCtxtFree(retStyle->compCtxt);
+                       retStyle->compCtxt = NULL;
+                   }
+               }
+
+               xsltFreeStylesheet(retStyle);
+               retStyle = NULL;
+           }
+       }
+    }
+        
+#else /* XSLT_REFACTORED */
+    /*
+    * Old behaviour.
+    */
+    retStyle->doc = doc;
+    xsltParseStylesheetProcess(retStyle, doc);
+    if (retStyle != NULL) {
+       if (retStyle->errors != 0) {
+           retStyle->doc = NULL;
+           if (parentStyle == NULL)
+               xsltCleanupStylesheetTree(doc,
+                   xmlDocGetRootElement(doc));
+           xsltFreeStylesheet(retStyle);
+           retStyle = NULL;
+       }
+    }
+#endif /* else of XSLT_REFACTORED */
+        
+    return(retStyle);
+}
+
+/**
+ * xsltParseStylesheetDoc:
+ * @doc:  and xmlDoc parsed XML
+ *
+ * parse an XSLT stylesheet building the associated structures
+ *
+ * Returns a new XSLT stylesheet structure.
+ */
+
+xsltStylesheetPtr
+xsltParseStylesheetDoc(xmlDocPtr doc) {
+    xsltStylesheetPtr ret;
+
+    ret = xsltParseStylesheetImportedDoc(doc, NULL);
+    if (ret == NULL)
+       return(NULL);
+
+    xsltResolveStylesheetAttributeSet(ret);
+#ifdef XSLT_REFACTORED
+    /*
+    * Free the compilation context.
+    * TODO: Check if it's better to move this cleanup to
+    *   xsltParseStylesheetImportedDoc().
+    */
+    if (ret->compCtxt != NULL) {
+       xsltCompilationCtxtFree(XSLT_CCTXT(ret));
+       ret->compCtxt = NULL;
+    }
+#endif
+    return(ret);
+}
+
+/**
+ * xsltParseStylesheetFile:
+ * @filename:  the filename/URL to the stylesheet
+ *
+ * Load and parse an XSLT stylesheet
+ *
+ * Returns a new XSLT stylesheet structure.
+ */
+
+xsltStylesheetPtr
+xsltParseStylesheetFile(const xmlChar* filename) {
+    xsltSecurityPrefsPtr sec;
+    xsltStylesheetPtr ret;
+    xmlDocPtr doc;
+    
+
+    if (filename == NULL)
+       return(NULL);
+
+#ifdef WITH_XSLT_DEBUG_PARSING
+    xsltGenericDebug(xsltGenericDebugContext,
+           "xsltParseStylesheetFile : parse %s\n", filename);
+#endif
+
+    /*
+     * Security framework check
+     */
+    sec = xsltGetDefaultSecurityPrefs();
+    if (sec != NULL) {
+       int res;
+
+       res = xsltCheckRead(sec, NULL, filename);
+       if (res == 0) {
+           xsltTransformError(NULL, NULL, NULL,
+                "xsltParseStylesheetFile: read rights for %s denied\n",
+                            filename);
+           return(NULL);
+       }
+    }
+
+    doc = xsltDocDefaultLoader(filename, NULL, XSLT_PARSE_OPTIONS,
+                               NULL, XSLT_LOAD_START);
+    if (doc == NULL) {
+       xsltTransformError(NULL, NULL, NULL,
+               "xsltParseStylesheetFile : cannot parse %s\n", filename);
+       return(NULL);
+    }
+    ret = xsltParseStylesheetDoc(doc);
+    if (ret == NULL) {
+       xmlFreeDoc(doc);
+       return(NULL);
+    }
+
+    return(ret);
+}
+
+/************************************************************************
+ *                                                                     *
+ *                     Handling of Stylesheet PI                       *
+ *                                                                     *
+ ************************************************************************/
+
+#define CUR (*cur)
+#define SKIP(val) cur += (val)
+#define NXT(val) cur[(val)]
+#define SKIP_BLANKS                                            \
+    while (IS_BLANK(CUR)) NEXT
+#define NEXT ((*cur) ?  cur++ : cur)
+
+/**
+ * xsltParseStylesheetPI:
+ * @value: the value of the PI
+ *
+ * This function checks that the type is text/xml and extracts
+ * the URI-Reference for the stylesheet
+ *
+ * Returns the URI-Reference for the stylesheet or NULL (it need to
+ *         be freed by the caller)
+ */
+static xmlChar *
+xsltParseStylesheetPI(const xmlChar *value) {
+    const xmlChar *cur;
+    const xmlChar *start;
+    xmlChar *val;
+    xmlChar tmp;
+    xmlChar *href = NULL;
+    int isXml = 0;
+
+    if (value == NULL)
+       return(NULL);
+
+    cur = value;
+    while (CUR != 0) {
+       SKIP_BLANKS;
+       if ((CUR == 't') && (NXT(1) == 'y') && (NXT(2) == 'p') &&
+           (NXT(3) == 'e')) {
+           SKIP(4);
+           SKIP_BLANKS;
+           if (CUR != '=')
+               continue;
+           NEXT;
+           if ((CUR != '\'') && (CUR != '"'))
+               continue;
+           tmp = CUR;
+           NEXT;
+           start = cur;
+           while ((CUR != 0) && (CUR != tmp))
+               NEXT;
+           if (CUR != tmp)
+               continue;
+           val = xmlStrndup(start, cur - start);
+           NEXT;
+           if (val == NULL) 
+               return(NULL);
+           if ((xmlStrcasecmp(val, BAD_CAST "text/xml")) &&
+               (xmlStrcasecmp(val, BAD_CAST "text/xsl"))) {
+                xmlFree(val);
+               break;
+           }
+           isXml = 1;
+           xmlFree(val);
+       } else if ((CUR == 'h') && (NXT(1) == 'r') && (NXT(2) == 'e') &&
+           (NXT(3) == 'f')) {
+           SKIP(4);
+           SKIP_BLANKS;
+           if (CUR != '=')
+               continue;
+           NEXT;
+           if ((CUR != '\'') && (CUR != '"'))
+               continue;
+           tmp = CUR;
+           NEXT;
+           start = cur;
+           while ((CUR != 0) && (CUR != tmp))
+               NEXT;
+           if (CUR != tmp)
+               continue;
+           if (href == NULL)
+               href = xmlStrndup(start, cur - start);
+           NEXT;
+       } else {
+           while ((CUR != 0) && (!IS_BLANK(CUR)))
+               NEXT;
+       }
+            
+    }
+
+    if (!isXml) {
+       if (href != NULL)
+           xmlFree(href);
+       href = NULL;
+    }
+    return(href);
+}
+
+/**
+ * xsltLoadStylesheetPI:
+ * @doc:  a document to process
+ *
+ * This function tries to locate the stylesheet PI in the given document
+ * If found, and if contained within the document, it will extract 
+ * that subtree to build the stylesheet to process @doc (doc itself will
+ * be modified). If found but referencing an external document it will
+ * attempt to load it and generate a stylesheet from it. In both cases,
+ * the resulting stylesheet and the document need to be freed once the
+ * transformation is done.
+ *
+ * Returns a new XSLT stylesheet structure or NULL if not found.
+ */
+xsltStylesheetPtr
+xsltLoadStylesheetPI(xmlDocPtr doc) {
+    xmlNodePtr child;
+    xsltStylesheetPtr ret = NULL;
+    xmlChar *href = NULL;
+    xmlURIPtr URI;
+
+    if (doc == NULL)
+       return(NULL);
+
+    /*
+     * Find the text/xml stylesheet PI id any before the root
+     */
+    child = doc->children;
+    while ((child != NULL) && (child->type != XML_ELEMENT_NODE)) {
+       if ((child->type == XML_PI_NODE) &&
+           (xmlStrEqual(child->name, BAD_CAST "xml-stylesheet"))) {
+           href = xsltParseStylesheetPI(child->content);
+           if (href != NULL)
+               break;
+       }
+       child = child->next;
+    }
+
+    /*
+     * If found check the href to select processing
+     */
+    if (href != NULL) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+       xsltGenericDebug(xsltGenericDebugContext,
+               "xsltLoadStylesheetPI : found PI href=%s\n", href);
+#endif
+       URI = xmlParseURI((const char *) href);
+       if (URI == NULL) {
+           xsltTransformError(NULL, NULL, child,
+                   "xml-stylesheet : href %s is not valid\n", href);
+           xmlFree(href);
+           return(NULL);
+       }
+       if ((URI->fragment != NULL) && (URI->scheme == NULL) &&
+            (URI->opaque == NULL) && (URI->authority == NULL) &&
+            (URI->server == NULL) && (URI->user == NULL) &&
+            (URI->path == NULL) && (URI->query == NULL)) {
+           xmlAttrPtr ID;
+
+#ifdef WITH_XSLT_DEBUG_PARSING
+           xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltLoadStylesheetPI : Reference to ID %s\n", href);
+#endif
+           if (URI->fragment[0] == '#')
+               ID = xmlGetID(doc, (const xmlChar *) &(URI->fragment[1]));
+           else
+               ID = xmlGetID(doc, (const xmlChar *) URI->fragment);
+           if (ID == NULL) {
+               xsltTransformError(NULL, NULL, child,
+                   "xml-stylesheet : no ID %s found\n", URI->fragment);
+           } else {
+               xmlDocPtr fake;
+               xmlNodePtr subtree;
+
+               /*
+                * move the subtree in a new document passed to
+                * the stylesheet analyzer
+                */
+               subtree = ID->parent;
+               fake = xmlNewDoc(NULL);
+               if (fake != NULL) {
+                    /*
+                    * the dictionnary should be shared since nodes are
+                    * moved over.
+                    */
+                   fake->dict = doc->dict;
+                   xmlDictReference(doc->dict);
+#ifdef WITH_XSLT_DEBUG
+                   xsltGenericDebug(xsltGenericDebugContext,
+                         "reusing dictionary from %s for stylesheet\n",
+                        doc->URL);
+#endif
+
+                   xmlUnlinkNode(subtree);
+                   xmlAddChild((xmlNodePtr) fake, subtree);
+                   ret = xsltParseStylesheetDoc(fake);
+                   if (ret == NULL)
+                       xmlFreeDoc(fake);
+               }
+           }
+       } else {
+           xmlChar *URL, *base;
+
+           /*
+            * Reference to an external stylesheet
+            */
+
+           base = xmlNodeGetBase(doc, (xmlNodePtr) doc);
+           URL = xmlBuildURI(href, base);
+           if (URL != NULL) {
+#ifdef WITH_XSLT_DEBUG_PARSING
+               xsltGenericDebug(xsltGenericDebugContext,
+                       "xsltLoadStylesheetPI : fetching %s\n", URL);
+#endif
+               ret = xsltParseStylesheetFile(URL);
+               xmlFree(URL);
+           } else {
+#ifdef WITH_XSLT_DEBUG_PARSING
+               xsltGenericDebug(xsltGenericDebugContext,
+                       "xsltLoadStylesheetPI : fetching %s\n", href);
+#endif
+               ret = xsltParseStylesheetFile(href);
+           }
+           if (base != NULL)
+               xmlFree(base);
+       }
+       xmlFreeURI(URI);
+       xmlFree(href);
+    }
+    return(ret);
+}
index fc60961..62062c5 100644 (file)
-/*\r
- * Summary: internal data structures, constants and functions\r
- * Description: Internal data structures, constants and functions used\r
- *              by the XSLT engine. \r
- *              They are not part of the API or ABI, i.e. they can change\r
- *              without prior notice, use carefully.\r
- *\r
- * Copy: See Copyright for the status of this software.\r
- *\r
- * Author: Daniel Veillard\r
- */\r
-\r
-#ifndef __XML_XSLT_INTERNALS_H__\r
-#define __XML_XSLT_INTERNALS_H__\r
-\r
-#include <libxml/tree.h>\r
-#include <libxml/hash.h>\r
-#include <libxml/xpath.h>\r
-#include <libxml/xmlerror.h>\r
-#include <libxml/dict.h>\r
-#include <libxml/xmlstring.h>\r
-#include <libxslt/xslt.h>\r
-#include "xsltexports.h"\r
-#include "numbersInternals.h"\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-/* #define XSLT_DEBUG_PROFILE_CACHE */\r
-\r
-#define XSLT_IS_TEXT_NODE(n) ((n != NULL) && \\r
-    (((n)->type == XML_TEXT_NODE) || \\r
-     ((n)->type == XML_CDATA_SECTION_NODE)))\r
-\r
-\r
-#define XSLT_MARK_RES_TREE_FRAG(n) \\r
-    (n)->name = (char *) xmlStrdup(BAD_CAST " fake node libxslt");\r
-\r
-#define XSLT_IS_RES_TREE_FRAG(n) \\r
-    ((n != NULL) && ((n)->type == XML_DOCUMENT_NODE) && \\r
-     ((n)->name != NULL) && ((n)->name[0] == ' '))\r
-\r
-/**\r
- * XSLT_REFACTORED_KEYCOMP:\r
- *\r
- * Internal define to enable on-demand xsl:key computation.\r
- */\r
-#define XSLT_REFACTORED_KEYCOMP\r
-\r
-/**\r
- * XSLT_FAST_IF:\r
- *\r
- * Internal define to enable usage of xmlXPathCompiledEvalToBoolean()\r
- * for XSLT "tests"; e.g. in <xsl:if test="/foo/bar">\r
- */\r
-#define XSLT_FAST_IF\r
-\r
-/**\r
- * XSLT_REFACTORED:\r
- *\r
- * Internal define to enable the refactored parts of Libxslt.\r
- */\r
-/* #define XSLT_REFACTORED */\r
-/* ==================================================================== */\r
-\r
-#define XSLT_REFACTORED_VARS\r
-\r
-#ifdef XSLT_REFACTORED\r
-\r
-extern const xmlChar *xsltXSLTAttrMarker;\r
-\r
-\r
-/* TODO: REMOVE: #define XSLT_REFACTORED_EXCLRESNS */\r
-\r
-/* TODO: REMOVE: #define XSLT_REFACTORED_NSALIAS */\r
-\r
-/**\r
- * XSLT_REFACTORED_XSLT_NSCOMP\r
- *\r
- * Internal define to enable the pointer-comparison of\r
- * namespaces of XSLT elements. \r
- */\r
-/* #define XSLT_REFACTORED_XSLT_NSCOMP */\r
-\r
-/**\r
- * XSLT_REFACTORED_XPATHCOMP\r
- *\r
- * Internal define to enable the optimization of the\r
- * compilation of XPath expressions.\r
- */\r
-#define XSLT_REFACTORED_XPATHCOMP\r
-\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-\r
-extern const xmlChar *xsltConstNamespaceNameXSLT;\r
-\r
-#define IS_XSLT_ELEM_FAST(n) \\r
-    (((n) != NULL) && ((n)->ns != NULL) && \\r
-    ((n)->ns->href == xsltConstNamespaceNameXSLT))\r
-\r
-#define IS_XSLT_ATTR_FAST(a) \\r
-    (((a) != NULL) && ((a)->ns != NULL) && \\r
-    ((a)->ns->href == xsltConstNamespaceNameXSLT))\r
-\r
-#define XSLT_HAS_INTERNAL_NSMAP(s) \\r
-    (((s) != NULL) && ((s)->principal) && \\r
-     ((s)->principal->principalData) && \\r
-     ((s)->principal->principalData->nsMap))\r
-\r
-#define XSLT_GET_INTERNAL_NSMAP(s) ((s)->principal->principalData->nsMap)\r
-\r
-#else /* XSLT_REFACTORED_XSLT_NSCOMP */\r
-\r
-#define IS_XSLT_ELEM_FAST(n) \\r
-    (((n) != NULL) && ((n)->ns != NULL) && \\r
-     (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE)))\r
-\r
-#define IS_XSLT_ATTR_FAST(a) \\r
-    (((a) != NULL) && ((a)->ns != NULL) && \\r
-     (xmlStrEqual((a)->ns->href, XSLT_NAMESPACE)))\r
-\r
-\r
-#endif /* XSLT_REFACTORED_XSLT_NSCOMP */\r
-\r
-\r
-/**\r
- * XSLT_REFACTORED_MANDATORY_VERSION:\r
- *\r
- * TODO: Currently disabled to surpress regression test failures, since\r
- *  the old behaviour was that a missing version attribute\r
- *  produced a only a warning and not an error, which was incerrect.\r
- *  So the regression tests need to be fixed if this is enabled.\r
- */\r
-/* #define XSLT_REFACTORED_MANDATORY_VERSION */\r
-\r
-/**\r
- * xsltPointerList:\r
- *\r
- * Pointer-list for various purposes.\r
- */\r
-typedef struct _xsltPointerList xsltPointerList;\r
-typedef xsltPointerList *xsltPointerListPtr;\r
-struct _xsltPointerList {\r
-    void **items;\r
-    int number;\r
-    int size;\r
-};\r
-\r
-#endif\r
-\r
-/**\r
- * XSLT_REFACTORED_PARSING:\r
- *\r
- * Internal define to enable the refactored parts of Libxslt\r
- * related to parsing.\r
- */\r
-/* #define XSLT_REFACTORED_PARSING */\r
-\r
-/**\r
- * XSLT_MAX_SORT:\r
- *\r
- * Max number of specified xsl:sort on an element.\r
- */\r
-#define XSLT_MAX_SORT 15\r
-\r
-/**\r
- * XSLT_PAT_NO_PRIORITY:\r
- *\r
- * Specific value for pattern without priority expressed.\r
- */\r
-#define XSLT_PAT_NO_PRIORITY -12345789\r
-\r
-/**\r
- * xsltRuntimeExtra:\r
- *\r
- * Extra information added to the transformation context.\r
- */\r
-typedef struct _xsltRuntimeExtra xsltRuntimeExtra;\r
-typedef xsltRuntimeExtra *xsltRuntimeExtraPtr;\r
-struct _xsltRuntimeExtra {\r
-    void       *info;          /* pointer to the extra data */\r
-    xmlFreeFunc deallocate;    /* pointer to the deallocation routine */\r
-    union {                    /* dual-purpose field */\r
-        void   *ptr;           /* data not needing deallocation */\r
-       int    ival;            /* integer value storage */\r
-    } val;\r
-};\r
-\r
-/**\r
- * XSLT_RUNTIME_EXTRA_LST:\r
- * @ctxt: the transformation context\r
- * @nr: the index\r
- *\r
- * Macro used to access extra information stored in the context\r
- */\r
-#define XSLT_RUNTIME_EXTRA_LST(ctxt, nr) (ctxt)->extras[(nr)].info\r
-/**\r
- * XSLT_RUNTIME_EXTRA_FREE:\r
- * @ctxt: the transformation context\r
- * @nr: the index\r
- *\r
- * Macro used to free extra information stored in the context\r
- */\r
-#define XSLT_RUNTIME_EXTRA_FREE(ctxt, nr) (ctxt)->extras[(nr)].deallocate\r
-/**\r
- * XSLT_RUNTIME_EXTRA:\r
- * @ctxt: the transformation context\r
- * @nr: the index\r
- *\r
- * Macro used to define extra information stored in the context\r
- */\r
-#define        XSLT_RUNTIME_EXTRA(ctxt, nr, typ) (ctxt)->extras[(nr)].val.typ\r
-\r
-/**\r
- * xsltTemplate:\r
- *\r
- * The in-memory structure corresponding to an XSLT Template.\r
- */\r
-typedef struct _xsltTemplate xsltTemplate;\r
-typedef xsltTemplate *xsltTemplatePtr;\r
-struct _xsltTemplate {\r
-    struct _xsltTemplate *next;/* chained list sorted by priority */\r
-    struct _xsltStylesheet *style;/* the containing stylesheet */\r
-    xmlChar *match;    /* the matching string */\r
-    float priority;    /* as given from the stylesheet, not computed */\r
-    const xmlChar *name; /* the local part of the name QName */\r
-    const xmlChar *nameURI; /* the URI part of the name QName */\r
-    const xmlChar *mode;/* the local part of the mode QName */\r
-    const xmlChar *modeURI;/* the URI part of the mode QName */\r
-    xmlNodePtr content;        /* the template replacement value */\r
-    xmlNodePtr elem;   /* the source element */\r
-\r
-    /*\r
-    * TODO: @inheritedNsNr and @inheritedNs won't be used in the\r
-    *  refactored code.\r
-    */\r
-    int inheritedNsNr;  /* number of inherited namespaces */\r
-    xmlNsPtr *inheritedNs;/* inherited non-excluded namespaces */\r
-\r
-    /* Profiling informations */\r
-    int nbCalls;        /* the number of time the template was called */\r
-    unsigned long time; /* the time spent in this template */\r
-    void *params;       /* xsl:param instructions */\r
-};\r
-\r
-/**\r
- * xsltDecimalFormat:\r
- *\r
- * Data structure of decimal-format.\r
- */\r
-typedef struct _xsltDecimalFormat xsltDecimalFormat;\r
-typedef xsltDecimalFormat *xsltDecimalFormatPtr;\r
-struct _xsltDecimalFormat {\r
-    struct _xsltDecimalFormat *next; /* chained list */\r
-    xmlChar *name;\r
-    /* Used for interpretation of pattern */\r
-    xmlChar *digit;\r
-    xmlChar *patternSeparator;\r
-    /* May appear in result */\r
-    xmlChar *minusSign;\r
-    xmlChar *infinity;\r
-    xmlChar *noNumber; /* Not-a-number */\r
-    /* Used for interpretation of pattern and may appear in result */\r
-    xmlChar *decimalPoint;\r
-    xmlChar *grouping;\r
-    xmlChar *percent;\r
-    xmlChar *permille;\r
-    xmlChar *zeroDigit;\r
-};\r
-\r
-/**\r
- * xsltDocument:\r
- *\r
- * Data structure associated to a parsed document.\r
- */\r
-typedef struct _xsltDocument xsltDocument;\r
-typedef xsltDocument *xsltDocumentPtr;\r
-struct _xsltDocument {\r
-    struct _xsltDocument *next;        /* documents are kept in a chained list */\r
-    int main;                  /* is this the main document */\r
-    xmlDocPtr doc;             /* the parsed document */\r
-    void *keys;                        /* key tables storage */\r
-    struct _xsltDocument *includes; /* subsidiary includes */\r
-    int preproc;               /* pre-processing already done */\r
-    int nbKeysComputed;\r
-};\r
-\r
-/**\r
- * xsltKeyDef:\r
- *\r
- * Representation of an xsl:key.\r
- */\r
-typedef struct _xsltKeyDef xsltKeyDef;\r
-typedef xsltKeyDef *xsltKeyDefPtr;\r
-struct _xsltKeyDef {\r
-    struct _xsltKeyDef *next;\r
-    xmlNodePtr inst;\r
-    xmlChar *name;\r
-    xmlChar *nameURI;\r
-    xmlChar *match;\r
-    xmlChar *use;\r
-    xmlXPathCompExprPtr comp;\r
-    xmlXPathCompExprPtr usecomp;\r
-    xmlNsPtr *nsList;           /* the namespaces in scope */\r
-    int nsNr;                   /* the number of namespaces in scope */\r
-};\r
-\r
-/**\r
- * xsltKeyTable:\r
- *\r
- * Holds the computed keys for key definitions of the same QName.\r
- * Is owned by an xsltDocument.\r
- */\r
-typedef struct _xsltKeyTable xsltKeyTable;\r
-typedef xsltKeyTable *xsltKeyTablePtr;\r
-struct _xsltKeyTable {\r
-    struct _xsltKeyTable *next;\r
-    xmlChar *name;\r
-    xmlChar *nameURI;\r
-    xmlHashTablePtr keys;\r
-};\r
-\r
-/*\r
- * The in-memory structure corresponding to an XSLT Stylesheet.\r
- * NOTE: most of the content is simply linked from the doc tree\r
- *       structure, no specific allocation is made.\r
- */\r
-typedef struct _xsltStylesheet xsltStylesheet;\r
-typedef xsltStylesheet *xsltStylesheetPtr;\r
-\r
-typedef struct _xsltTransformContext xsltTransformContext;\r
-typedef xsltTransformContext *xsltTransformContextPtr;\r
-\r
-/**\r
- * xsltElemPreComp:\r
- *\r
- * The in-memory structure corresponding to element precomputed data,\r
- * designed to be extended by extension implementors.\r
- */\r
-typedef struct _xsltElemPreComp xsltElemPreComp;\r
-typedef xsltElemPreComp *xsltElemPreCompPtr;\r
-\r
-/**\r
- * xsltTransformFunction:\r
- * @ctxt: the XSLT transformation context\r
- * @node: the input node\r
- * @inst: the stylesheet node\r
- * @comp: the compiled information from the stylesheet\r
- *\r
- * Signature of the function associated to elements part of the\r
- * stylesheet language like xsl:if or xsl:apply-templates.\r
- */\r
-typedef void (*xsltTransformFunction) (xsltTransformContextPtr ctxt,\r
-                                      xmlNodePtr node,\r
-                                      xmlNodePtr inst,\r
-                                      xsltElemPreCompPtr comp);\r
-\r
-/**\r
- * xsltSortFunc:\r
- * @ctxt:    a transformation context\r
- * @sorts:   the node-set to sort\r
- * @nbsorts: the number of sorts\r
- *\r
- * Signature of the function to use during sorting\r
- */\r
-typedef void (*xsltSortFunc) (xsltTransformContextPtr ctxt, xmlNodePtr *sorts,\r
-                             int nbsorts);\r
-\r
-typedef enum {\r
-    XSLT_FUNC_COPY=1,\r
-    XSLT_FUNC_SORT,\r
-    XSLT_FUNC_TEXT,\r
-    XSLT_FUNC_ELEMENT,\r
-    XSLT_FUNC_ATTRIBUTE,\r
-    XSLT_FUNC_COMMENT,\r
-    XSLT_FUNC_PI,\r
-    XSLT_FUNC_COPYOF,\r
-    XSLT_FUNC_VALUEOF,\r
-    XSLT_FUNC_NUMBER,\r
-    XSLT_FUNC_APPLYIMPORTS,\r
-    XSLT_FUNC_CALLTEMPLATE,\r
-    XSLT_FUNC_APPLYTEMPLATES,\r
-    XSLT_FUNC_CHOOSE,\r
-    XSLT_FUNC_IF,\r
-    XSLT_FUNC_FOREACH,\r
-    XSLT_FUNC_DOCUMENT,\r
-    XSLT_FUNC_WITHPARAM,\r
-    XSLT_FUNC_PARAM,\r
-    XSLT_FUNC_VARIABLE,\r
-    XSLT_FUNC_WHEN,\r
-    XSLT_FUNC_EXTENSION,\r
-#ifdef XSLT_REFACTORED\r
-    XSLT_FUNC_OTHERWISE,\r
-    XSLT_FUNC_FALLBACK,\r
-    XSLT_FUNC_MESSAGE,\r
-    XSLT_FUNC_INCLUDE,\r
-    XSLT_FUNC_ATTRSET,\r
-    XSLT_FUNC_LITERAL_RESULT_ELEMENT,\r
-    XSLT_FUNC_UNKOWN_FORWARDS_COMPAT,\r
-#endif\r
-} xsltStyleType;\r
-\r
-/**\r
- * xsltElemPreCompDeallocator:\r
- * @comp:  the #xsltElemPreComp to free up\r
- *\r
- * Deallocates an #xsltElemPreComp structure.\r
- */\r
-typedef void (*xsltElemPreCompDeallocator) (xsltElemPreCompPtr comp);\r
-\r
-/**\r
- * xsltElemPreComp:\r
- *\r
- * The basic structure for compiled items of the AST of the XSLT processor.\r
- * This structure is also intended to be extended by extension implementors.\r
- * TODO: This is somehow not nice, since it has a "free" field, which\r
- *   derived stylesheet-structs do not have.\r
- */\r
-struct _xsltElemPreComp {\r
-    xsltElemPreCompPtr next;           /* next item in the global chained\r
-                                          list hold by xsltStylesheet. */\r
-    xsltStyleType type;                /* type of the element */\r
-    xsltTransformFunction func;        /* handling function */\r
-    xmlNodePtr inst;                   /* the node in the stylesheet's tree\r
-                                          corresponding to this item */\r
-\r
-    /* end of common part */\r
-    xsltElemPreCompDeallocator free;   /* the deallocator */\r
-};\r
-\r
-/**\r
- * xsltStylePreComp:\r
- *\r
- * The abstract basic structure for items of the XSLT processor.\r
- * This includes:\r
- * 1) compiled forms of XSLT instructions (xsl:if, xsl:attribute, etc.)\r
- * 2) compiled forms of literal result elements\r
- * 3) compiled forms of extension elements\r
- */\r
-typedef struct _xsltStylePreComp xsltStylePreComp;\r
-typedef xsltStylePreComp *xsltStylePreCompPtr;\r
-\r
-#ifdef XSLT_REFACTORED\r
-\r
-/*\r
-* Some pointer-list utility functions.\r
-*/\r
-XSLTPUBFUN xsltPointerListPtr XSLTCALL\r
-               xsltPointerListCreate           (int initialSize);\r
-XSLTPUBFUN void XSLTCALL\r
-               xsltPointerListFree             (xsltPointerListPtr list);\r
-XSLTPUBFUN void XSLTCALL\r
-               xsltPointerListClear            (xsltPointerListPtr list);\r
-XSLTPUBFUN int XSLTCALL\r
-               xsltPointerListAddSize          (xsltPointerListPtr list,                                                \r
-                                                void *item,\r
-                                                int initialSize);\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- * Refactored structures                                                *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-typedef struct _xsltNsListContainer xsltNsListContainer;\r
-typedef xsltNsListContainer *xsltNsListContainerPtr;\r
-struct _xsltNsListContainer {\r
-    xmlNsPtr *list;\r
-    int totalNumber;\r
-    int xpathNumber;    \r
-};\r
-\r
-/**\r
- * XSLT_ITEM_COMPATIBILITY_FIELDS:\r
- * \r
- * Fields for API compatibility to the structure\r
- * _xsltElemPreComp which is used for extension functions.\r
- * Note that @next is used for storage; it does not reflect a next\r
- * sibling in the tree.\r
- * TODO: Evaluate if we really need such a compatibility.\r
- */\r
-#define XSLT_ITEM_COMPATIBILITY_FIELDS \\r
-    xsltElemPreCompPtr next;\\r
-    xsltStyleType type;\\r
-    xsltTransformFunction func;\\r
-    xmlNodePtr inst;\r
-\r
-/**\r
- * XSLT_ITEM_NAVIGATION_FIELDS:\r
- *\r
- * Currently empty.\r
- * TODO: It is intended to hold navigational fields in the future.\r
- */\r
-#define XSLT_ITEM_NAVIGATION_FIELDS\r
-/*\r
-    xsltStylePreCompPtr parent;\\r
-    xsltStylePreCompPtr children;\\r
-    xsltStylePreCompPtr nextItem; \r
-*/\r
-\r
-/**\r
- * XSLT_ITEM_NSINSCOPE_FIELDS:\r
- *\r
- * The in-scope namespaces.\r
- */\r
-#define XSLT_ITEM_NSINSCOPE_FIELDS xsltNsListContainerPtr inScopeNs;\r
-\r
-/**\r
- * XSLT_ITEM_COMMON_FIELDS:\r
- *\r
- * Common fields used for all items.\r
- */\r
-#define XSLT_ITEM_COMMON_FIELDS \\r
-    XSLT_ITEM_COMPATIBILITY_FIELDS \\r
-    XSLT_ITEM_NAVIGATION_FIELDS \\r
-    XSLT_ITEM_NSINSCOPE_FIELDS\r
-\r
-/**\r
- * _xsltStylePreComp: \r
- *\r
- * The abstract basic structure for items of the XSLT processor.\r
- * This includes:\r
- * 1) compiled forms of XSLT instructions (e.g. xsl:if, xsl:attribute, etc.)\r
- * 2) compiled forms of literal result elements\r
- * 3) various properties for XSLT instructions (e.g. xsl:when,\r
- *    xsl:with-param)\r
- *\r
- * REVISIT TODO: Keep this structure equal to the fields\r
- *   defined by XSLT_ITEM_COMMON_FIELDS\r
- */\r
-struct _xsltStylePreComp {\r
-    xsltElemPreCompPtr next;    /* next item in the global chained\r
-                                  list hold by xsltStylesheet */\r
-    xsltStyleType type;         /* type of the item */ \r
-    xsltTransformFunction func; /* handling function */\r
-    xmlNodePtr inst;           /* the node in the stylesheet's tree\r
-                                  corresponding to this item. */\r
-    /* Currently no navigational fields. */\r
-    xsltNsListContainerPtr inScopeNs;\r
-};\r
-\r
-/**\r
- * xsltStyleBasicEmptyItem:\r
- * \r
- * Abstract structure only used as a short-cut for\r
- * XSLT items with no extra fields.\r
- * NOTE that it is intended that this structure looks the same as\r
- *  _xsltStylePreComp.\r
- */\r
-typedef struct _xsltStyleBasicEmptyItem xsltStyleBasicEmptyItem;\r
-typedef xsltStyleBasicEmptyItem *xsltStyleBasicEmptyItemPtr;\r
-\r
-struct _xsltStyleBasicEmptyItem {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-};\r
-\r
-/**\r
- * xsltStyleBasicExpressionItem:\r
- * \r
- * Abstract structure only used as a short-cut for\r
- * XSLT items with just an expression.\r
- */\r
-typedef struct _xsltStyleBasicExpressionItem xsltStyleBasicExpressionItem;\r
-typedef xsltStyleBasicExpressionItem *xsltStyleBasicExpressionItemPtr;\r
-\r
-struct _xsltStyleBasicExpressionItem {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-\r
-    const xmlChar *select; /* TODO: Change this to "expression". */\r
-    xmlXPathCompExprPtr comp; /* TODO: Change this to compExpr. */\r
-};\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- * XSLT-instructions/declarations                                       *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltStyleItemElement:\r
- * \r
- * <!-- Category: instruction -->\r
- * <xsl:element\r
- *  name = { qname }\r
- *  namespace = { uri-reference }\r
- *  use-attribute-sets = qnames>\r
- *  <!-- Content: template -->\r
- * </xsl:element>\r
- */\r
-typedef struct _xsltStyleItemElement xsltStyleItemElement;\r
-typedef xsltStyleItemElement *xsltStyleItemElementPtr;\r
-\r
-struct _xsltStyleItemElement {\r
-    XSLT_ITEM_COMMON_FIELDS \r
-\r
-    const xmlChar *use;\r
-    int      has_use;\r
-    const xmlChar *name;    \r
-    int      has_name;\r
-    const xmlChar *ns;\r
-    const xmlChar *nsPrefix;\r
-    int      has_ns;\r
-};\r
-\r
-/**\r
- * xsltStyleItemAttribute:\r
- *\r
- * <!-- Category: instruction -->\r
- * <xsl:attribute\r
- *  name = { qname }\r
- *  namespace = { uri-reference }>\r
- *  <!-- Content: template -->\r
- * </xsl:attribute>\r
- */\r
-typedef struct _xsltStyleItemAttribute xsltStyleItemAttribute;\r
-typedef xsltStyleItemAttribute *xsltStyleItemAttributePtr;\r
-\r
-struct _xsltStyleItemAttribute {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-    const xmlChar *name;\r
-    int      has_name;\r
-    const xmlChar *ns;\r
-    const xmlChar *nsPrefix;\r
-    int      has_ns;\r
-};\r
-\r
-/**\r
- * xsltStyleItemText:\r
- *\r
- * <!-- Category: instruction -->\r
- * <xsl:text\r
- *  disable-output-escaping = "yes" | "no">\r
- *  <!-- Content: #PCDATA -->\r
- * </xsl:text>\r
- */\r
-typedef struct _xsltStyleItemText xsltStyleItemText;\r
-typedef xsltStyleItemText *xsltStyleItemTextPtr;\r
-\r
-struct _xsltStyleItemText {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-    int      noescape;         /* text */\r
-};\r
-\r
-/**\r
- * xsltStyleItemComment:\r
- *\r
- * <!-- Category: instruction -->\r
- *  <xsl:comment>\r
- *  <!-- Content: template -->\r
- * </xsl:comment>\r
- */\r
-typedef xsltStyleBasicEmptyItem xsltStyleItemComment;\r
-typedef xsltStyleItemComment *xsltStyleItemCommentPtr;\r
-\r
-/**\r
- * xsltStyleItemPI:\r
- *\r
- * <!-- Category: instruction -->\r
- *  <xsl:processing-instruction\r
- *  name = { ncname }>\r
- *  <!-- Content: template -->\r
- * </xsl:processing-instruction>\r
- */\r
-typedef struct _xsltStyleItemPI xsltStyleItemPI;\r
-typedef xsltStyleItemPI *xsltStyleItemPIPtr;\r
-\r
-struct _xsltStyleItemPI {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-    const xmlChar *name;\r
-    int      has_name;\r
-};\r
-\r
-/**\r
- * xsltStyleItemApplyImports:\r
- *\r
- * <!-- Category: instruction -->\r
- * <xsl:apply-imports />\r
- */\r
-typedef xsltStyleBasicEmptyItem xsltStyleItemApplyImports;\r
-typedef xsltStyleItemApplyImports *xsltStyleItemApplyImportsPtr;\r
-\r
-/**\r
- * xsltStyleItemApplyTemplates:\r
- *\r
- * <!-- Category: instruction -->\r
- *  <xsl:apply-templates\r
- *  select = node-set-expression\r
- *  mode = qname>\r
- *  <!-- Content: (xsl:sort | xsl:with-param)* -->\r
- * </xsl:apply-templates>\r
- */\r
-typedef struct _xsltStyleItemApplyTemplates xsltStyleItemApplyTemplates;\r
-typedef xsltStyleItemApplyTemplates *xsltStyleItemApplyTemplatesPtr;\r
-\r
-struct _xsltStyleItemApplyTemplates {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-\r
-    const xmlChar *mode;       /* apply-templates */\r
-    const xmlChar *modeURI;    /* apply-templates */\r
-    const xmlChar *select;     /* sort, copy-of, value-of, apply-templates */\r
-    xmlXPathCompExprPtr comp;  /* a precompiled XPath expression */\r
-    /* TODO: with-params */\r
-};\r
-\r
-/**\r
- * xsltStyleItemCallTemplate:\r
- *\r
- * <!-- Category: instruction -->\r
- *  <xsl:call-template\r
- *  name = qname>\r
- *  <!-- Content: xsl:with-param* -->\r
- * </xsl:call-template>\r
- */\r
-typedef struct _xsltStyleItemCallTemplate xsltStyleItemCallTemplate;\r
-typedef xsltStyleItemCallTemplate *xsltStyleItemCallTemplatePtr;\r
-\r
-struct _xsltStyleItemCallTemplate {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-\r
-    xsltTemplatePtr templ;     /* call-template */\r
-    const xmlChar *name;       /* element, attribute, pi */\r
-    int      has_name;         /* element, attribute, pi */\r
-    const xmlChar *ns;         /* element */\r
-    int      has_ns;           /* element */\r
-    /* TODO: with-params */\r
-};\r
-\r
-/**\r
- * xsltStyleItemCopy:\r
- *\r
- * <!-- Category: instruction -->\r
- * <xsl:copy\r
- *  use-attribute-sets = qnames>\r
- *  <!-- Content: template -->\r
- * </xsl:copy>\r
- */\r
-typedef struct _xsltStyleItemCopy xsltStyleItemCopy;\r
-typedef xsltStyleItemCopy *xsltStyleItemCopyPtr;\r
-\r
-struct _xsltStyleItemCopy {\r
-   XSLT_ITEM_COMMON_FIELDS\r
-    const xmlChar *use;                /* copy, element */\r
-    int      has_use;          /* copy, element */    \r
-};\r
-\r
-/**\r
- * xsltStyleItemIf:\r
- *\r
- * <!-- Category: instruction -->\r
- *  <xsl:if\r
- *  test = boolean-expression>\r
- *  <!-- Content: template -->\r
- * </xsl:if>\r
- */\r
-typedef struct _xsltStyleItemIf xsltStyleItemIf;\r
-typedef xsltStyleItemIf *xsltStyleItemIfPtr;\r
-\r
-struct _xsltStyleItemIf {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-\r
-    const xmlChar *test;       /* if */\r
-    xmlXPathCompExprPtr comp;  /* a precompiled XPath expression */\r
-};\r
-\r
-\r
-/**\r
- * xsltStyleItemCopyOf:\r
- *\r
- * <!-- Category: instruction -->\r
- * <xsl:copy-of\r
- *  select = expression />\r
- */\r
-typedef xsltStyleBasicExpressionItem xsltStyleItemCopyOf;\r
-typedef xsltStyleItemCopyOf *xsltStyleItemCopyOfPtr;\r
-\r
-/**\r
- * xsltStyleItemValueOf:\r
- *\r
- * <!-- Category: instruction -->\r
- * <xsl:value-of\r
- *  select = string-expression\r
- *  disable-output-escaping = "yes" | "no" />\r
- */\r
-typedef struct _xsltStyleItemValueOf xsltStyleItemValueOf;\r
-typedef xsltStyleItemValueOf *xsltStyleItemValueOfPtr;\r
-\r
-struct _xsltStyleItemValueOf {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-\r
-    const xmlChar *select;\r
-    xmlXPathCompExprPtr comp;  /* a precompiled XPath expression */\r
-    int      noescape;\r
-};\r
-\r
-/**\r
- * xsltStyleItemNumber:\r
- *\r
- * <!-- Category: instruction -->\r
- *  <xsl:number\r
- *  level = "single" | "multiple" | "any"\r
- *  count = pattern\r
- *  from = pattern\r
- *  value = number-expression\r
- *  format = { string }\r
- *  lang = { nmtoken }\r
- *  letter-value = { "alphabetic" | "traditional" }\r
- *  grouping-separator = { char }\r
- *  grouping-size = { number } />\r
- */\r
-typedef struct _xsltStyleItemNumber xsltStyleItemNumber;\r
-typedef xsltStyleItemNumber *xsltStyleItemNumberPtr;\r
-\r
-struct _xsltStyleItemNumber {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-    xsltNumberData numdata;    /* number */\r
-};\r
-\r
-/**\r
- * xsltStyleItemChoose:\r
- *\r
- * <!-- Category: instruction -->\r
- *  <xsl:choose>\r
- *  <!-- Content: (xsl:when+, xsl:otherwise?) -->\r
- * </xsl:choose>\r
- */\r
-typedef xsltStyleBasicEmptyItem xsltStyleItemChoose;\r
-typedef xsltStyleItemChoose *xsltStyleItemChoosePtr;\r
-\r
-/**\r
- * xsltStyleItemFallback:\r
- *\r
- * <!-- Category: instruction -->\r
- *  <xsl:fallback>\r
- *  <!-- Content: template -->\r
- * </xsl:fallback>\r
- */\r
-typedef xsltStyleBasicEmptyItem xsltStyleItemFallback;\r
-typedef xsltStyleItemFallback *xsltStyleItemFallbackPtr;\r
-\r
-/**\r
- * xsltStyleItemForEach:\r
- *\r
- * <!-- Category: instruction -->\r
- * <xsl:for-each\r
- *   select = node-set-expression>\r
- *   <!-- Content: (xsl:sort*, template) -->\r
- * </xsl:for-each>\r
- */\r
-typedef xsltStyleBasicExpressionItem xsltStyleItemForEach;\r
-typedef xsltStyleItemForEach *xsltStyleItemForEachPtr;\r
-\r
-/**\r
- * xsltStyleItemMessage:\r
- *\r
- * <!-- Category: instruction -->\r
- * <xsl:message\r
- *   terminate = "yes" | "no">\r
- *   <!-- Content: template -->\r
- * </xsl:message>\r
- */\r
-typedef struct _xsltStyleItemMessage xsltStyleItemMessage;\r
-typedef xsltStyleItemMessage *xsltStyleItemMessagePtr;\r
-\r
-struct _xsltStyleItemMessage {\r
-    XSLT_ITEM_COMMON_FIELDS    \r
-    int terminate;\r
-};\r
-\r
-/**\r
- * xsltStyleItemDocument:\r
- *\r
- * NOTE: This is not an instruction of XSLT 1.0.\r
- */\r
-typedef struct _xsltStyleItemDocument xsltStyleItemDocument;\r
-typedef xsltStyleItemDocument *xsltStyleItemDocumentPtr;\r
-\r
-struct _xsltStyleItemDocument {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-    int      ver11;            /* assigned: in xsltDocumentComp;\r
-                                  read: nowhere;\r
-                                  TODO: Check if we need. */\r
-    const xmlChar *filename;   /* document URL */\r
-    int has_filename;\r
-};   \r
-\r
-/************************************************************************\r
- *                                                                     *\r
- * Non-instructions (actually properties of instructions/declarations)  *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltStyleBasicItemVariable:\r
- *\r
- * Basic struct for xsl:variable, xsl:param and xsl:with-param.\r
- * It's currently important to have equal fields, since\r
- * xsltParseStylesheetCallerParam() is used with xsl:with-param from\r
- * the xslt side and with xsl:param from the exslt side (in\r
- * exsltFuncFunctionFunction()).\r
- *\r
- * FUTURE NOTE: In XSLT 2.0 xsl:param, xsl:variable and xsl:with-param\r
- *   have additional different fields.\r
- */\r
-typedef struct _xsltStyleBasicItemVariable xsltStyleBasicItemVariable;\r
-typedef xsltStyleBasicItemVariable *xsltStyleBasicItemVariablePtr;\r
-\r
-struct _xsltStyleBasicItemVariable {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-\r
-    const xmlChar *select;\r
-    xmlXPathCompExprPtr comp;\r
-\r
-    const xmlChar *name;\r
-    int      has_name;\r
-    const xmlChar *ns;\r
-    int      has_ns;\r
-};\r
-\r
-/**\r
- * xsltStyleItemVariable:\r
- *\r
- * <!-- Category: top-level-element -->\r
- * <xsl:param\r
- *   name = qname\r
- *   select = expression>\r
- *   <!-- Content: template -->\r
- * </xsl:param>\r
- */\r
-typedef xsltStyleBasicItemVariable xsltStyleItemVariable;\r
-typedef xsltStyleItemVariable *xsltStyleItemVariablePtr;\r
-\r
-/**\r
- * xsltStyleItemParam:\r
- *\r
- * <!-- Category: top-level-element -->\r
- * <xsl:param\r
- *   name = qname\r
- *   select = expression>\r
- *   <!-- Content: template -->\r
- * </xsl:param>\r
- */\r
-typedef struct _xsltStyleItemParam xsltStyleItemParam;\r
-typedef xsltStyleItemParam *xsltStyleItemParamPtr;\r
-\r
-struct _xsltStyleItemParam {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-\r
-    const xmlChar *select;\r
-    xmlXPathCompExprPtr comp;\r
-\r
-    const xmlChar *name;\r
-    int      has_name;\r
-    const xmlChar *ns;\r
-    int      has_ns;    \r
-};\r
-\r
-/**\r
- * xsltStyleItemWithParam:\r
- *\r
- * <xsl:with-param\r
- *  name = qname\r
- *  select = expression>\r
- *  <!-- Content: template -->\r
- * </xsl:with-param>\r
- */\r
-typedef xsltStyleBasicItemVariable xsltStyleItemWithParam;\r
-typedef xsltStyleItemWithParam *xsltStyleItemWithParamPtr;\r
-\r
-/**\r
- * xsltStyleItemSort:\r
- *\r
- * Reflects the XSLT xsl:sort item.\r
- * Allowed parents: xsl:apply-templates, xsl:for-each\r
- * <xsl:sort\r
- *   select = string-expression\r
- *   lang = { nmtoken }\r
- *   data-type = { "text" | "number" | qname-but-not-ncname }\r
- *   order = { "ascending" | "descending" }\r
- *   case-order = { "upper-first" | "lower-first" } />\r
- */\r
-typedef struct _xsltStyleItemSort xsltStyleItemSort;\r
-typedef xsltStyleItemSort *xsltStyleItemSortPtr;\r
-\r
-struct _xsltStyleItemSort {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-\r
-    const xmlChar *stype;       /* sort */\r
-    int      has_stype;                /* sort */\r
-    int      number;           /* sort */\r
-    const xmlChar *order;      /* sort */\r
-    int      has_order;                /* sort */\r
-    int      descending;       /* sort */\r
-    const xmlChar *lang;       /* sort */\r
-    int      has_lang;         /* sort */\r
-    const xmlChar *case_order; /* sort */\r
-    int      lower_first;      /* sort */\r
-\r
-    const xmlChar *use;\r
-    int      has_use;\r
-\r
-    const xmlChar *select;     /* sort, copy-of, value-of, apply-templates */\r
-\r
-    xmlXPathCompExprPtr comp;  /* a precompiled XPath expression */\r
-};\r
-\r
-\r
-/**\r
- * xsltStyleItemWhen:\r
- * \r
- * <xsl:when\r
- *   test = boolean-expression>\r
- *   <!-- Content: template -->\r
- * </xsl:when>\r
- * Allowed parent: xsl:choose\r
- */\r
-typedef struct _xsltStyleItemWhen xsltStyleItemWhen;\r
-typedef xsltStyleItemWhen *xsltStyleItemWhenPtr;\r
-\r
-struct _xsltStyleItemWhen {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-\r
-    const xmlChar *test;\r
-    xmlXPathCompExprPtr comp;\r
-};\r
-\r
-/**\r
- * xsltStyleItemOtherwise:\r
- *\r
- * Allowed parent: xsl:choose\r
- * <xsl:otherwise>\r
- *   <!-- Content: template -->\r
- * </xsl:otherwise>\r
- */\r
-typedef struct _xsltStyleItemOtherwise xsltStyleItemOtherwise;\r
-typedef xsltStyleItemOtherwise *xsltStyleItemOtherwisePtr;\r
-\r
-struct _xsltStyleItemOtherwise {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-};\r
-\r
-typedef struct _xsltStyleItemInclude xsltStyleItemInclude;\r
-typedef xsltStyleItemInclude *xsltStyleItemIncludePtr;\r
-\r
-struct _xsltStyleItemInclude {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-    xsltDocumentPtr include;\r
-};\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *  XSLT elements in forwards-compatible mode                           *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-typedef struct _xsltStyleItemUknown xsltStyleItemUknown;\r
-typedef xsltStyleItemUknown *xsltStyleItemUknownPtr;\r
-struct _xsltStyleItemUknown {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-};\r
-\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *  Extension elements                                                  *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/*\r
- * xsltStyleItemExtElement:\r
- *\r
- * Reflects extension elements.\r
- *\r
- * NOTE: Due to the fact that the structure xsltElemPreComp is most\r
- * probably already heavily in use out there by users, so we cannot\r
- * easily change it, we'll create an intermediate structure which will\r
- * hold an xsltElemPreCompPtr.\r
- * BIG NOTE: The only problem I see here is that the user processes the\r
- *  content of the stylesheet tree, possibly he'll lookup the node->psvi\r
- *  fields in order to find subsequent extension functions.\r
- *  In this case, the user's code will break, since the node->psvi\r
- *  field will hold now the xsltStyleItemExtElementPtr and not\r
- *  the xsltElemPreCompPtr.\r
- *  However the place where the structure is anchored in the node-tree,\r
- *  namely node->psvi, has beed already once been moved from node->_private\r
- *  to node->psvi, so we have a precedent here, which, I think, should allow\r
- *  us to change such semantics without headaches.\r
- */\r
-typedef struct _xsltStyleItemExtElement xsltStyleItemExtElement;\r
-typedef xsltStyleItemExtElement *xsltStyleItemExtElementPtr;\r
-struct _xsltStyleItemExtElement {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-    xsltElemPreCompPtr item;   \r
-};\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *  Literal result elements                                             *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-typedef struct _xsltEffectiveNs xsltEffectiveNs;\r
-typedef xsltEffectiveNs *xsltEffectiveNsPtr;\r
-struct _xsltEffectiveNs {\r
-    xsltEffectiveNsPtr nextInStore; /* storage next */\r
-    xsltEffectiveNsPtr next; /* next item in the list */\r
-    const xmlChar *prefix;\r
-    const xmlChar *nsName;\r
-    /* \r
-    * Indicates if eclared on the literal result element; dunno if really\r
-    * needed.\r
-    */\r
-    int holdByElem;\r
-};\r
-\r
-/*\r
- * Info for literal result elements.\r
- * This will be set on the elem->psvi field and will be\r
- * shared by literal result elements, which have the same\r
- * excluded result namespaces; i.e., this *won't* be created uniquely\r
- * for every literal result element.\r
- */\r
-typedef struct _xsltStyleItemLRElementInfo xsltStyleItemLRElementInfo;\r
-typedef xsltStyleItemLRElementInfo *xsltStyleItemLRElementInfoPtr;\r
-struct _xsltStyleItemLRElementInfo {\r
-    XSLT_ITEM_COMMON_FIELDS\r
-    /*\r
-    * @effectiveNs is the set of effective ns-nodes\r
-    *  on the literal result element, which will be added to the result\r
-    *  element if not already existing in the result tree.\r
-    *  This means that excluded namespaces (via exclude-result-prefixes,\r
-    *  extension-element-prefixes and the XSLT namespace) not added\r
-    *  to the set.\r
-    *  Namespace-aliasing was applied on the @effectiveNs.\r
-    */\r
-    xsltEffectiveNsPtr effectiveNs;\r
-\r
-};\r
-\r
-#ifdef XSLT_REFACTORED\r
-\r
-typedef struct _xsltNsAlias xsltNsAlias;\r
-typedef xsltNsAlias *xsltNsAliasPtr;\r
-struct _xsltNsAlias {\r
-    xsltNsAliasPtr next; /* next in the list */    \r
-    xmlNsPtr literalNs;\r
-    xmlNsPtr targetNs;\r
-    xmlDocPtr docOfTargetNs;\r
-};\r
-#endif\r
-\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-\r
-typedef struct _xsltNsMap xsltNsMap;\r
-typedef xsltNsMap *xsltNsMapPtr;\r
-struct _xsltNsMap {\r
-    xsltNsMapPtr next; /* next in the list */\r
-    xmlDocPtr doc;\r
-    xmlNodePtr elem; /* the element holding the ns-decl */\r
-    xmlNsPtr ns; /* the xmlNs structure holding the XML namespace name */\r
-    const xmlChar *origNsName; /* the original XML namespace name */\r
-    const xmlChar *newNsName; /* the mapped XML namespace name */    \r
-};\r
-#endif\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *  Compile-time structures for *internal* use only                     *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-typedef struct _xsltPrincipalStylesheetData xsltPrincipalStylesheetData;\r
-typedef xsltPrincipalStylesheetData *xsltPrincipalStylesheetDataPtr;\r
-\r
-typedef struct _xsltNsList xsltNsList;\r
-typedef xsltNsList *xsltNsListPtr;\r
-struct _xsltNsList {\r
-    xsltNsListPtr next; /* next in the list */\r
-    xmlNsPtr ns;\r
-};\r
-\r
-/*\r
-* xsltVarInfo:\r
-*\r
-* Used at compilation time for parameters and variables.\r
-*/\r
-typedef struct _xsltVarInfo xsltVarInfo;\r
-typedef xsltVarInfo *xsltVarInfoPtr;\r
-struct _xsltVarInfo {\r
-    xsltVarInfoPtr next; /* next in the list */\r
-    xsltVarInfoPtr prev;\r
-    int depth; /* the depth in the tree */\r
-    const xmlChar *name;\r
-    const xmlChar *nsName;\r
-};\r
-\r
-#define XSLT_ELEMENT_CATEGORY_XSLT 0\r
-#define XSLT_ELEMENT_CATEGORY_EXTENSION 1\r
-#define XSLT_ELEMENT_CATEGORY_LRE 2\r
-\r
-/**\r
- * xsltCompilerNodeInfo:\r
- *\r
- * Per-node information during compile-time.\r
- */\r
-typedef struct _xsltCompilerNodeInfo xsltCompilerNodeInfo;\r
-typedef xsltCompilerNodeInfo *xsltCompilerNodeInfoPtr;\r
-struct _xsltCompilerNodeInfo {\r
-    xsltCompilerNodeInfoPtr next;\r
-    xsltCompilerNodeInfoPtr prev;\r
-    xmlNodePtr node;\r
-    int depth;\r
-    xsltTemplatePtr templ;   /* The owning template */\r
-    int category;           /* XSLT element, LR-element or\r
-                                extension element */\r
-    xsltStyleType type;\r
-    xsltElemPreCompPtr item; /* The compiled information */\r
-    /* The current in-scope namespaces */\r
-    xsltNsListContainerPtr inScopeNs;\r
-    /* The current excluded result namespaces */\r
-    xsltPointerListPtr exclResultNs; \r
-    /* The current extension instruction namespaces */\r
-    xsltPointerListPtr extElemNs;\r
-\r
-    /* The current info for literal result elements. */\r
-    xsltStyleItemLRElementInfoPtr litResElemInfo;\r
-    /* \r
-    * Set to 1 if in-scope namespaces changed,\r
-    *  or excluded result namespaces changed,\r
-    *  or extension element namespaces changed.\r
-    * This will trigger creation of new infos\r
-    *  for literal result elements.\r
-    */\r
-    int nsChanged;\r
-    int preserveWhitespace;\r
-    int stripWhitespace;\r
-    int isRoot; /* whether this is the stylesheet's root node */\r
-    int forwardsCompat; /* whether forwards-compatible mode is enabled */\r
-    /* whether the content of an extension element was processed */\r
-    int extContentHandled;\r
-    /* the type of the current child */\r
-    xsltStyleType curChildType;    \r
-};\r
-\r
-#define XSLT_CCTXT(style) ((xsltCompilerCtxtPtr) style->compCtxt) \r
-\r
-typedef enum {\r
-    XSLT_ERROR_SEVERITY_ERROR = 0,\r
-    XSLT_ERROR_SEVERITY_WARNING\r
-} xsltErrorSeverityType;\r
-\r
-typedef struct _xsltCompilerCtxt xsltCompilerCtxt;\r
-typedef xsltCompilerCtxt *xsltCompilerCtxtPtr;\r
-struct _xsltCompilerCtxt {\r
-    void *errorCtxt;            /* user specific error context */\r
-    /*\r
-    * used for error/warning reports; e.g. XSLT_ERROR_SEVERITY_WARNING */\r
-    xsltErrorSeverityType errSeverity;         \r
-    int warnings;              /* TODO: number of warnings found at\r
-                                   compilation */\r
-    int errors;                        /* TODO: number of errors found at\r
-                                   compilation */\r
-    xmlDictPtr dict;\r
-    xsltStylesheetPtr style;\r
-    int simplified; /* whether this is a simplified stylesheet */\r
-    /* TODO: structured/unstructured error contexts. */\r
-    int depth; /* Current depth of processing */\r
-    \r
-    xsltCompilerNodeInfoPtr inode;\r
-    xsltCompilerNodeInfoPtr inodeList;\r
-    xsltCompilerNodeInfoPtr inodeLast;\r
-    xsltPointerListPtr tmpList; /* Used for various purposes */\r
-    /*\r
-    * The XSLT version as specified by the stylesheet's root element.\r
-    */\r
-    int isInclude;\r
-    int hasForwardsCompat; /* whether forwards-compatible mode was used\r
-                            in a parsing episode */\r
-    int maxNodeInfos; /* TEMP TODO: just for the interest */\r
-    int maxLREs;  /* TEMP TODO: just for the interest */\r
-    /* \r
-    * In order to keep the old behaviour, applying strict rules of\r
-    * the spec can be turned off. This has effect only on special\r
-    * mechanisms like whitespace-stripping in the stylesheet.\r
-    */\r
-    int strict;\r
-    xsltPrincipalStylesheetDataPtr psData;\r
-#ifdef XSLT_REFACTORED_XPATHCOMP\r
-    xmlXPathContextPtr xpathCtxt;\r
-#endif\r
-    xsltStyleItemUknownPtr unknownItem;\r
-    int hasNsAliases; /* Indicator if there was an xsl:namespace-alias. */\r
-    xsltNsAliasPtr nsAliases;\r
-    xsltVarInfoPtr ivars; /* Storage of local in-scope variables/params. */\r
-    xsltVarInfoPtr ivar; /* topmost local variable/param. */\r
-};   \r
-\r
-#else /* XSLT_REFACTORED */\r
-/*\r
-* The old structures before refactoring.\r
-*/\r
-\r
-/**\r
- * _xsltStylePreComp:\r
- *\r
- * The in-memory structure corresponding to XSLT stylesheet constructs\r
- * precomputed data.\r
- */\r
-struct _xsltStylePreComp {\r
-    xsltElemPreCompPtr next;   /* chained list */\r
-    xsltStyleType type;                /* type of the element */\r
-    xsltTransformFunction func; /* handling function */\r
-    xmlNodePtr inst;           /* the instruction */\r
-\r
-    /*\r
-     * Pre computed values.\r
-     */\r
-\r
-    const xmlChar *stype;       /* sort */\r
-    int      has_stype;                /* sort */\r
-    int      number;           /* sort */\r
-    const xmlChar *order;      /* sort */\r
-    int      has_order;                /* sort */\r
-    int      descending;       /* sort */\r
-    const xmlChar *lang;       /* sort */\r
-    int      has_lang;         /* sort */\r
-    const xmlChar *case_order; /* sort */\r
-    int      lower_first;      /* sort */\r
-\r
-    const xmlChar *use;                /* copy, element */\r
-    int      has_use;          /* copy, element */\r
-\r
-    int      noescape;         /* text */\r
-\r
-    const xmlChar *name;       /* element, attribute, pi */\r
-    int      has_name;         /* element, attribute, pi */\r
-    const xmlChar *ns;         /* element */\r
-    int      has_ns;           /* element */\r
-\r
-    const xmlChar *mode;       /* apply-templates */\r
-    const xmlChar *modeURI;    /* apply-templates */\r
-\r
-    const xmlChar *test;       /* if */\r
-\r
-    xsltTemplatePtr templ;     /* call-template */\r
-\r
-    const xmlChar *select;     /* sort, copy-of, value-of, apply-templates */\r
-\r
-    int      ver11;            /* document */\r
-    const xmlChar *filename;   /* document URL */\r
-    int      has_filename;     /* document */\r
-\r
-    xsltNumberData numdata;    /* number */\r
-\r
-    xmlXPathCompExprPtr comp;  /* a precompiled XPath expression */\r
-    xmlNsPtr *nsList;          /* the namespaces in scope */\r
-    int nsNr;                  /* the number of namespaces in scope */\r
-};\r
-\r
-#endif /* XSLT_REFACTORED */\r
-\r
-\r
-#define XSLT_VAR_GLOBAL 1<<0\r
-#define XSLT_VAR_IN_SELECT 1<<1\r
-#define XSLT_TCTXT_VARIABLE(c) ((xsltStackElemPtr) (c)->contextVariable)\r
-/*\r
- * The in-memory structure corresponding to an XSLT Variable\r
- * or Param.\r
- */\r
-typedef struct _xsltStackElem xsltStackElem;\r
-typedef xsltStackElem *xsltStackElemPtr;\r
-struct _xsltStackElem {\r
-    struct _xsltStackElem *next;/* chained list */\r
-    xsltStylePreCompPtr comp;   /* the compiled form */\r
-    int computed;              /* was the evaluation done */\r
-    const xmlChar *name;       /* the local part of the name QName */\r
-    const xmlChar *nameURI;    /* the URI part of the name QName */\r
-    const xmlChar *select;     /* the eval string */\r
-    xmlNodePtr tree;           /* the sequence constructor if no eval\r
-                                   string or the location */\r
-    xmlXPathObjectPtr value;   /* The value if computed */\r
-    xmlDocPtr fragment;                /* The Result Tree Fragments (needed for XSLT 1.0)\r
-                                  which are bound to the variable's lifetime. */\r
-    int level;                  /* the depth in the tree;\r
-                                   -1 if persistent (e.g. a given xsl:with-param) */\r
-    xsltTransformContextPtr context; /* The transformation context; needed to cache\r
-                                        the variables */\r
-    int flags;\r
-};\r
-\r
-#ifdef XSLT_REFACTORED\r
-\r
-struct _xsltPrincipalStylesheetData {\r
-    /*\r
-    * Namespace dictionary for ns-prefixes and ns-names:\r
-    * TODO: Shared between stylesheets, and XPath mechanisms.\r
-    *   Not used yet.\r
-    */\r
-    xmlDictPtr namespaceDict;\r
-    /*\r
-    * Global list of in-scope namespaces.\r
-    */\r
-    xsltPointerListPtr inScopeNamespaces;\r
-    /*\r
-    * Global list of information for [xsl:]excluded-result-prefixes.\r
-    */\r
-    xsltPointerListPtr exclResultNamespaces;\r
-    /*\r
-    * Global list of information for [xsl:]extension-element-prefixes.\r
-    */\r
-    xsltPointerListPtr extElemNamespaces;\r
-    xsltEffectiveNsPtr effectiveNs;\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-    /*\r
-    * Namespace name map to get rid of string comparison of namespace names.\r
-    */\r
-    xsltNsMapPtr nsMap;\r
-#endif\r
-};\r
-\r
-    \r
-#endif\r
-/*\r
- * Note that we added a @compCtxt field to anchor an stylesheet compilation\r
- * context, since, due to historical reasons, various compile-time function\r
- * take only the stylesheet as argument and not a compilation context.\r
- */\r
-struct _xsltStylesheet {\r
-    /*\r
-     * The stylesheet import relation is kept as a tree.\r
-     */\r
-    struct _xsltStylesheet *parent;\r
-    struct _xsltStylesheet *next;\r
-    struct _xsltStylesheet *imports;\r
-\r
-    xsltDocumentPtr docList;           /* the include document list */\r
-\r
-    /*\r
-     * General data on the style sheet document.\r
-     */\r
-    xmlDocPtr doc;             /* the parsed XML stylesheet */\r
-    xmlHashTablePtr stripSpaces;/* the hash table of the strip-space and\r
-                                  preserve space elements */\r
-    int             stripAll;  /* strip-space * (1) preserve-space * (-1) */\r
-    xmlHashTablePtr cdataSection;/* the hash table of the cdata-section */\r
-\r
-    /*\r
-     * Global variable or parameters.\r
-     */\r
-    xsltStackElemPtr variables; /* linked list of param and variables */\r
-\r
-    /*\r
-     * Template descriptions.\r
-     */\r
-    xsltTemplatePtr templates; /* the ordered list of templates */\r
-    void *templatesHash;       /* hash table or wherever compiled templates\r
-                                  informations are stored */\r
-    void *rootMatch;           /* template based on / */\r
-    void *keyMatch;            /* template based on key() */\r
-    void *elemMatch;           /* template based on * */\r
-    void *attrMatch;           /* template based on @* */\r
-    void *parentMatch;         /* template based on .. */\r
-    void *textMatch;           /* template based on text() */\r
-    void *piMatch;             /* template based on processing-instruction() */\r
-    void *commentMatch;                /* template based on comment() */\r
-    \r
-    /*\r
-     * Namespace aliases.\r
-     * NOTE: Not used in the refactored code.\r
-     */\r
-    xmlHashTablePtr nsAliases; /* the namespace alias hash tables */\r
-\r
-    /*\r
-     * Attribute sets.\r
-     */\r
-    xmlHashTablePtr attributeSets;/* the attribute sets hash tables */\r
-\r
-    /*\r
-     * Namespaces.\r
-     * TODO: Eliminate this.\r
-     */\r
-    xmlHashTablePtr nsHash;     /* the set of namespaces in use:\r
-                                   ATTENTION: This is used for\r
-                                   execution of XPath expressions; unfortunately\r
-                                   it restricts the stylesheet to have distinct\r
-                                   prefixes.\r
-                                  TODO: We need to get rid of this.    \r
-                                */\r
-    void           *nsDefs;     /* ATTENTION TODO: This is currently used to store\r
-                                  xsltExtDefPtr (in extensions.c) and\r
-                                   *not* xmlNsPtr.\r
-                                */\r
-\r
-    /*\r
-     * Key definitions.\r
-     */\r
-    void *keys;                        /* key definitions */\r
-\r
-    /*\r
-     * Output related stuff.\r
-     */\r
-    xmlChar *method;           /* the output method */\r
-    xmlChar *methodURI;                /* associated namespace if any */\r
-    xmlChar *version;          /* version string */\r
-    xmlChar *encoding;         /* encoding string */\r
-    int omitXmlDeclaration;     /* omit-xml-declaration = "yes" | "no" */\r
-\r
-    /* \r
-     * Number formatting.\r
-     */\r
-    xsltDecimalFormatPtr decimalFormat;\r
-    int standalone;             /* standalone = "yes" | "no" */\r
-    xmlChar *doctypePublic;     /* doctype-public string */\r
-    xmlChar *doctypeSystem;     /* doctype-system string */\r
-    int indent;                        /* should output being indented */\r
-    xmlChar *mediaType;                /* media-type string */\r
-\r
-    /*\r
-     * Precomputed blocks.\r
-     */\r
-    xsltElemPreCompPtr preComps;/* list of precomputed blocks */\r
-    int warnings;              /* number of warnings found at compilation */\r
-    int errors;                        /* number of errors found at compilation */\r
-\r
-    xmlChar  *exclPrefix;      /* last excluded prefixes */\r
-    xmlChar **exclPrefixTab;   /* array of excluded prefixes */\r
-    int       exclPrefixNr;    /* number of excluded prefixes in scope */\r
-    int       exclPrefixMax;   /* size of the array */\r
-\r
-    void     *_private;                /* user defined data */\r
-\r
-    /*\r
-     * Extensions.\r
-     */\r
-    xmlHashTablePtr extInfos;  /* the extension data */\r
-    int                    extrasNr;   /* the number of extras required */\r
-\r
-    /*\r
-     * For keeping track of nested includes\r
-     */\r
-    xsltDocumentPtr includes;  /* points to last nested include */\r
-\r
-    /*\r
-     * dictionary: shared between stylesheet, context and documents.\r
-     */\r
-    xmlDictPtr dict;\r
-    /*\r
-     * precompiled attribute value templates.\r
-     */\r
-    void *attVTs;\r
-    /*\r
-     * if namespace-alias has an alias for the default stylesheet prefix\r
-     * NOTE: Not used in the refactored code.\r
-     */\r
-    const xmlChar *defaultAlias;\r
-    /*\r
-     * bypass pre-processing (already done) (used in imports)\r
-     */\r
-    int nopreproc;\r
-    /*\r
-     * all document text strings were internalized\r
-     */\r
-    int internalized;\r
-    /*\r
-     * Literal Result Element as Stylesheet c.f. section 2.3\r
-     */\r
-    int literal_result;\r
-    /*\r
-    * The principal stylesheet\r
-    */\r
-    xsltStylesheetPtr principal;\r
-#ifdef XSLT_REFACTORED\r
-    /*\r
-    * Compilation context used during compile-time.\r
-    */\r
-    xsltCompilerCtxtPtr compCtxt; /* TODO: Change this to (void *). */\r
-\r
-    xsltPrincipalStylesheetDataPtr principalData;    \r
-#endif\r
-};\r
-\r
-typedef struct _xsltTransformCache xsltTransformCache;\r
-typedef xsltTransformCache *xsltTransformCachePtr;\r
-struct _xsltTransformCache {\r
-    xmlDocPtr RVT;\r
-    int nbRVT;\r
-    xsltStackElemPtr stackItems;\r
-    int nbStackItems;\r
-#ifdef XSLT_DEBUG_PROFILE_CACHE\r
-    int dbgCachedRVTs;\r
-    int dbgReusedRVTs;\r
-    int dbgCachedVars;\r
-    int dbgReusedVars;\r
-#endif\r
-};\r
-\r
-/*\r
- * The in-memory structure corresponding to an XSLT Transformation.\r
- */\r
-typedef enum {\r
-    XSLT_OUTPUT_XML = 0,\r
-    XSLT_OUTPUT_HTML,\r
-    XSLT_OUTPUT_TEXT\r
-} xsltOutputType;\r
-\r
-typedef enum {\r
-    XSLT_STATE_OK = 0,\r
-    XSLT_STATE_ERROR,\r
-    XSLT_STATE_STOPPED\r
-} xsltTransformState;\r
-\r
-struct _xsltTransformContext {\r
-    xsltStylesheetPtr style;           /* the stylesheet used */\r
-    xsltOutputType type;               /* the type of output */\r
-\r
-    xsltTemplatePtr  templ;            /* the current template */\r
-    int              templNr;          /* Nb of templates in the stack */\r
-    int              templMax;         /* Size of the templtes stack */\r
-    xsltTemplatePtr *templTab;         /* the template stack */\r
-\r
-    xsltStackElemPtr  vars;            /* the current variable list */\r
-    int               varsNr;          /* Nb of variable list in the stack */\r
-    int               varsMax;         /* Size of the variable list stack */\r
-    xsltStackElemPtr *varsTab;         /* the variable list stack */\r
-    int               varsBase;                /* the var base for current templ */\r
-\r
-    /*\r
-     * Extensions\r
-     */\r
-    xmlHashTablePtr   extFunctions;    /* the extension functions */\r
-    xmlHashTablePtr   extElements;     /* the extension elements */\r
-    xmlHashTablePtr   extInfos;                /* the extension data */\r
-\r
-    const xmlChar *mode;               /* the current mode */\r
-    const xmlChar *modeURI;            /* the current mode URI */\r
-\r
-    xsltDocumentPtr docList;           /* the document list */\r
-\r
-    xsltDocumentPtr document;          /* the current source document; can be NULL if an RTF */\r
-    xmlNodePtr node;                   /* the current node being processed */\r
-    xmlNodeSetPtr nodeList;            /* the current node list */\r
-    /* xmlNodePtr current;                     the node */\r
-\r
-    xmlDocPtr output;                  /* the resulting document */\r
-    xmlNodePtr insert;                 /* the insertion node */\r
-\r
-    xmlXPathContextPtr xpathCtxt;      /* the XPath context */\r
-    xsltTransformState state;          /* the current state */\r
-\r
-    /*\r
-     * Global variables\r
-     */\r
-    xmlHashTablePtr   globalVars;      /* the global variables and params */\r
-\r
-    xmlNodePtr inst;                   /* the instruction in the stylesheet */\r
-\r
-    int xinclude;                      /* should XInclude be processed */\r
-\r
-    const char *      outputFile;      /* the output URI if known */\r
-\r
-    int profile;                        /* is this run profiled */\r
-    long             prof;             /* the current profiled value */\r
-    int              profNr;           /* Nb of templates in the stack */\r
-    int              profMax;          /* Size of the templtaes stack */\r
-    long            *profTab;          /* the profile template stack */\r
-\r
-    void            *_private;         /* user defined data */\r
-\r
-    int              extrasNr;         /* the number of extras used */\r
-    int              extrasMax;                /* the number of extras allocated */\r
-    xsltRuntimeExtraPtr extras;                /* extra per runtime informations */\r
-\r
-    xsltDocumentPtr  styleList;                /* the stylesheet docs list */\r
-    void                 * sec;                /* the security preferences if any */\r
-\r
-    xmlGenericErrorFunc  error;                /* a specific error handler */\r
-    void              * errctx;                /* context for the error handler */\r
-\r
-    xsltSortFunc      sortfunc;                /* a ctxt specific sort routine */\r
-\r
-    /*\r
-     * handling of temporary Result Value Tree\r
-     * (XSLT 1.0 term: "Result Tree Fragment")\r
-     */\r
-    xmlDocPtr       tmpRVT;            /* list of RVT without persistance */\r
-    xmlDocPtr       persistRVT;                /* list of persistant RVTs */\r
-    int             ctxtflags;          /* context processing flags */\r
-\r
-    /*\r
-     * Speed optimization when coalescing text nodes\r
-     */\r
-    const xmlChar  *lasttext;          /* last text node content */\r
-    unsigned int    lasttsize;         /* last text node size */\r
-    unsigned int    lasttuse;          /* last text node use */\r
-    /*\r
-     * Per Context Debugging\r
-     */\r
-    int debugStatus;                   /* the context level debug status */\r
-    unsigned long* traceCode;          /* pointer to the variable holding the mask */\r
-\r
-    int parserOptions;                 /* parser options xmlParserOption */\r
-\r
-    /*\r
-     * dictionnary: shared between stylesheet, context and documents.\r
-     */\r
-    xmlDictPtr dict;\r
-    /*\r
-     * The current source doc; one of: the initial source doc, a RTF\r
-     * or a source doc aquired via the document() function.\r
-     */\r
-    xmlDocPtr          tmpDoc;\r
-    /*\r
-     * all document text strings are internalized\r
-     */\r
-    int internalized;\r
-    int nbKeys;\r
-    int hasTemplKeyPatterns;    \r
-    xsltTemplatePtr currentTemplateRule; /* the Current Template Rule */    \r
-    xmlNodePtr initialContextNode;\r
-    xmlDocPtr initialContextDoc;\r
-    xsltTransformCachePtr cache;\r
-    void *contextVariable; /* the current variable item */\r
-    xmlDocPtr localRVT; /* list of local tree fragments; will be freed when\r
-                          the instruction which created the fragment\r
-                           exits */\r
-    xmlDocPtr localRVTBase;    \r
-};\r
-\r
-/**\r
- * CHECK_STOPPED:\r
- *\r
- * Macro to check if the XSLT processing should be stopped.\r
- * Will return from the function.\r
- */\r
-#define CHECK_STOPPED if (ctxt->state == XSLT_STATE_STOPPED) return;\r
-\r
-/**\r
- * CHECK_STOPPEDE:\r
- *\r
- * Macro to check if the XSLT processing should be stopped.\r
- * Will goto the error: label.\r
- */\r
-#define CHECK_STOPPEDE if (ctxt->state == XSLT_STATE_STOPPED) goto error;\r
-\r
-/**\r
- * CHECK_STOPPED0:\r
- *\r
- * Macro to check if the XSLT processing should be stopped.\r
- * Will return from the function with a 0 value.\r
- */\r
-#define CHECK_STOPPED0 if (ctxt->state == XSLT_STATE_STOPPED) return(0);\r
-\r
-/*\r
- * The macro XML_CAST_FPTR is a hack to avoid a gcc warning about\r
- * possible incompatibilities between function pointers and object\r
- * pointers.  It is defined in libxml/hash.h within recent versions\r
- * of libxml2, but is put here for compatibility.\r
- */\r
-#ifndef XML_CAST_FPTR\r
-/**\r
- * XML_CAST_FPTR:\r
- * @fptr:  pointer to a function\r
- *\r
- * Macro to do a casting from an object pointer to a\r
- * function pointer without encountering a warning from\r
- * gcc\r
- *\r
- * #define XML_CAST_FPTR(fptr) (*(void **)(&fptr))\r
- * This macro violated ISO C aliasing rules (gcc4 on s390 broke)\r
- * so it is disabled now\r
- */\r
-\r
-#define XML_CAST_FPTR(fptr) fptr\r
-#endif\r
-/*\r
- * Functions associated to the internal types\r
-xsltDecimalFormatPtr   xsltDecimalFormatGetByName(xsltStylesheetPtr sheet,\r
-                                                  xmlChar *name);\r
- */\r
-XSLTPUBFUN xsltStylesheetPtr XSLTCALL  \r
-                       xsltNewStylesheet       (void);\r
-XSLTPUBFUN xsltStylesheetPtr XSLTCALL  \r
-                       xsltParseStylesheetFile (const xmlChar* filename);\r
-XSLTPUBFUN void XSLTCALL                       \r
-                       xsltFreeStylesheet      (xsltStylesheetPtr style);\r
-XSLTPUBFUN int XSLTCALL                        \r
-                       xsltIsBlank             (xmlChar *str);\r
-XSLTPUBFUN void XSLTCALL                       \r
-                       xsltFreeStackElemList   (xsltStackElemPtr elem);\r
-XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL       \r
-                       xsltDecimalFormatGetByName(xsltStylesheetPtr style,\r
-                                                xmlChar *name);\r
-\r
-XSLTPUBFUN xsltStylesheetPtr XSLTCALL  \r
-                       xsltParseStylesheetProcess(xsltStylesheetPtr ret,\r
-                                                xmlDocPtr doc);\r
-XSLTPUBFUN void XSLTCALL                       \r
-                       xsltParseStylesheetOutput(xsltStylesheetPtr style,\r
-                                                xmlNodePtr cur);\r
-XSLTPUBFUN xsltStylesheetPtr XSLTCALL  \r
-                       xsltParseStylesheetDoc  (xmlDocPtr doc);\r
-XSLTPUBFUN xsltStylesheetPtr XSLTCALL  \r
-                       xsltParseStylesheetImportedDoc(xmlDocPtr doc,\r
-                                               xsltStylesheetPtr style);\r
-XSLTPUBFUN xsltStylesheetPtr XSLTCALL  \r
-                       xsltLoadStylesheetPI    (xmlDocPtr doc);\r
-XSLTPUBFUN void XSLTCALL                       \r
-                       xsltNumberFormat        (xsltTransformContextPtr ctxt,\r
-                                                xsltNumberDataPtr data,\r
-                                                xmlNodePtr node);\r
-XSLTPUBFUN xmlXPathError XSLTCALL               \r
-                       xsltFormatNumberConversion(xsltDecimalFormatPtr self,\r
-                                                xmlChar *format,\r
-                                                double number,\r
-                                                xmlChar **result);\r
-\r
-XSLTPUBFUN void XSLTCALL                       \r
-                       xsltParseTemplateContent(xsltStylesheetPtr style,\r
-                                                xmlNodePtr templ);\r
-XSLTPUBFUN int XSLTCALL                        \r
-                       xsltAllocateExtra       (xsltStylesheetPtr style);\r
-XSLTPUBFUN int XSLTCALL                        \r
-                       xsltAllocateExtraCtxt   (xsltTransformContextPtr ctxt);\r
-/*\r
- * Extra functions for Result Value Trees\r
- */\r
-XSLTPUBFUN xmlDocPtr XSLTCALL          \r
-                       xsltCreateRVT           (xsltTransformContextPtr ctxt);\r
-XSLTPUBFUN int XSLTCALL                        \r
-                       xsltRegisterTmpRVT      (xsltTransformContextPtr ctxt,\r
-                                                xmlDocPtr RVT);\r
-XSLTPUBFUN int XSLTCALL                        \r
-                       xsltRegisterLocalRVT    (xsltTransformContextPtr ctxt,\r
-                                                xmlDocPtr RVT);\r
-XSLTPUBFUN int XSLTCALL                        \r
-                       xsltRegisterPersistRVT  (xsltTransformContextPtr ctxt,\r
-                                                xmlDocPtr RVT);\r
-XSLTPUBFUN int XSLTCALL\r
-                       xsltExtensionInstructionResultRegister(\r
-                                                xsltTransformContextPtr ctxt,\r
-                                                xmlXPathObjectPtr obj);\r
-XSLTPUBFUN int XSLTCALL\r
-                       xsltExtensionInstructionResultFinalize(\r
-                                                xsltTransformContextPtr ctxt);\r
-XSLTPUBFUN void XSLTCALL\r
-                       xsltFreeRVTs            (xsltTransformContextPtr ctxt);\r
-XSLTPUBFUN void XSLTCALL\r
-                       xsltReleaseRVT          (xsltTransformContextPtr ctxt,\r
-                                                xmlDocPtr RVT);\r
-XSLTPUBFUN int XSLTCALL\r
-                       xsltTransStorageAdd     (xsltTransformContextPtr ctxt,\r
-                                                void *id,\r
-                                                void *data);\r
-XSLTPUBFUN void * XSLTCALL\r
-                       xsltTransStorageRemove  (xsltTransformContextPtr ctxt,\r
-                                                void *id);\r
-\r
-/*\r
- * Extra functions for Attribute Value Templates\r
- */\r
-XSLTPUBFUN void XSLTCALL\r
-                       xsltCompileAttr         (xsltStylesheetPtr style,\r
-                                                xmlAttrPtr attr);\r
-XSLTPUBFUN xmlChar * XSLTCALL\r
-                       xsltEvalAVT             (xsltTransformContextPtr ctxt,\r
-                                                void *avt,\r
-                                                xmlNodePtr node);\r
-XSLTPUBFUN void XSLTCALL\r
-                       xsltFreeAVTList         (void *avt);\r
-\r
-/*\r
- * Extra function for successful xsltCleanupGlobals / xsltInit sequence.\r
- */\r
-\r
-XSLTPUBFUN void XSLTCALL\r
-                       xsltUninit              (void);\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *  Compile-time functions for *internal* use only                      *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-#ifdef XSLT_REFACTORED  \r
-XSLTPUBFUN void XSLTCALL\r
-                       xsltParseSequenceConstructor(\r
-                                                xsltCompilerCtxtPtr cctxt,\r
-                                                xmlNodePtr start);\r
-XSLTPUBFUN int XSLTCALL\r
-                       xsltParseAnyXSLTElem    (xsltCompilerCtxtPtr cctxt,\r
-                                                xmlNodePtr elem);\r
-#ifdef XSLT_REFACTORED_XSLT_NSCOMP\r
-XSLTPUBFUN int XSLTCALL\r
-                       xsltRestoreDocumentNamespaces(\r
-                                                xsltNsMapPtr ns,\r
-                                                xmlDocPtr doc);\r
-#endif\r
-#endif /* XSLT_REFACTORED */\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *  Transformation-time functions for *internal* use only               *\r
- *                                                                     *\r
- ************************************************************************/\r
-XSLTPUBFUN int XSLTCALL\r
-                       xsltInitCtxtKey         (xsltTransformContextPtr ctxt,\r
-                                                xsltDocumentPtr doc,\r
-                                                xsltKeyDefPtr keyd);\r
-\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-\r
-#endif /* __XML_XSLT_H__ */\r
-\r
+/*
+ * Summary: internal data structures, constants and functions
+ * Description: Internal data structures, constants and functions used
+ *              by the XSLT engine. 
+ *              They are not part of the API or ABI, i.e. they can change
+ *              without prior notice, use carefully.
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Daniel Veillard
+ */
+
+#ifndef __XML_XSLT_INTERNALS_H__
+#define __XML_XSLT_INTERNALS_H__
+
+#include <libxml/tree.h>
+#include <libxml/hash.h>
+#include <libxml/xpath.h>
+#include <libxml/xmlerror.h>
+#include <libxml/dict.h>
+#include <libxml/xmlstring.h>
+#include <libxslt/xslt.h>
+#include "xsltexports.h"
+#include "numbersInternals.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* #define XSLT_DEBUG_PROFILE_CACHE */
+
+#define XSLT_IS_TEXT_NODE(n) ((n != NULL) && \
+    (((n)->type == XML_TEXT_NODE) || \
+     ((n)->type == XML_CDATA_SECTION_NODE)))
+
+
+#define XSLT_MARK_RES_TREE_FRAG(n) \
+    (n)->name = (char *) xmlStrdup(BAD_CAST " fake node libxslt");
+
+#define XSLT_IS_RES_TREE_FRAG(n) \
+    ((n != NULL) && ((n)->type == XML_DOCUMENT_NODE) && \
+     ((n)->name != NULL) && ((n)->name[0] == ' '))
+
+/**
+ * XSLT_REFACTORED_KEYCOMP:
+ *
+ * Internal define to enable on-demand xsl:key computation.
+ */
+#define XSLT_REFACTORED_KEYCOMP
+
+/**
+ * XSLT_FAST_IF:
+ *
+ * Internal define to enable usage of xmlXPathCompiledEvalToBoolean()
+ * for XSLT "tests"; e.g. in <xsl:if test="/foo/bar">
+ */
+#define XSLT_FAST_IF
+
+/**
+ * XSLT_REFACTORED:
+ *
+ * Internal define to enable the refactored parts of Libxslt.
+ */
+/* #define XSLT_REFACTORED */
+/* ==================================================================== */
+
+#define XSLT_REFACTORED_VARS
+
+#ifdef XSLT_REFACTORED
+
+extern const xmlChar *xsltXSLTAttrMarker;
+
+
+/* TODO: REMOVE: #define XSLT_REFACTORED_EXCLRESNS */
+
+/* TODO: REMOVE: #define XSLT_REFACTORED_NSALIAS */
+
+/**
+ * XSLT_REFACTORED_XSLT_NSCOMP
+ *
+ * Internal define to enable the pointer-comparison of
+ * namespaces of XSLT elements. 
+ */
+/* #define XSLT_REFACTORED_XSLT_NSCOMP */
+
+/**
+ * XSLT_REFACTORED_XPATHCOMP
+ *
+ * Internal define to enable the optimization of the
+ * compilation of XPath expressions.
+ */
+#define XSLT_REFACTORED_XPATHCOMP
+
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+
+extern const xmlChar *xsltConstNamespaceNameXSLT;
+
+#define IS_XSLT_ELEM_FAST(n) \
+    (((n) != NULL) && ((n)->ns != NULL) && \
+    ((n)->ns->href == xsltConstNamespaceNameXSLT))
+
+#define IS_XSLT_ATTR_FAST(a) \
+    (((a) != NULL) && ((a)->ns != NULL) && \
+    ((a)->ns->href == xsltConstNamespaceNameXSLT))
+
+#define XSLT_HAS_INTERNAL_NSMAP(s) \
+    (((s) != NULL) && ((s)->principal) && \
+     ((s)->principal->principalData) && \
+     ((s)->principal->principalData->nsMap))
+
+#define XSLT_GET_INTERNAL_NSMAP(s) ((s)->principal->principalData->nsMap)
+
+#else /* XSLT_REFACTORED_XSLT_NSCOMP */
+
+#define IS_XSLT_ELEM_FAST(n) \
+    (((n) != NULL) && ((n)->ns != NULL) && \
+     (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE)))
+
+#define IS_XSLT_ATTR_FAST(a) \
+    (((a) != NULL) && ((a)->ns != NULL) && \
+     (xmlStrEqual((a)->ns->href, XSLT_NAMESPACE)))
+
+
+#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
+
+
+/**
+ * XSLT_REFACTORED_MANDATORY_VERSION:
+ *
+ * TODO: Currently disabled to surpress regression test failures, since
+ *  the old behaviour was that a missing version attribute
+ *  produced a only a warning and not an error, which was incerrect.
+ *  So the regression tests need to be fixed if this is enabled.
+ */
+/* #define XSLT_REFACTORED_MANDATORY_VERSION */
+
+/**
+ * xsltPointerList:
+ *
+ * Pointer-list for various purposes.
+ */
+typedef struct _xsltPointerList xsltPointerList;
+typedef xsltPointerList *xsltPointerListPtr;
+struct _xsltPointerList {
+    void **items;
+    int number;
+    int size;
+};
+
+#endif
+
+/**
+ * XSLT_REFACTORED_PARSING:
+ *
+ * Internal define to enable the refactored parts of Libxslt
+ * related to parsing.
+ */
+/* #define XSLT_REFACTORED_PARSING */
+
+/**
+ * XSLT_MAX_SORT:
+ *
+ * Max number of specified xsl:sort on an element.
+ */
+#define XSLT_MAX_SORT 15
+
+/**
+ * XSLT_PAT_NO_PRIORITY:
+ *
+ * Specific value for pattern without priority expressed.
+ */
+#define XSLT_PAT_NO_PRIORITY -12345789
+
+/**
+ * xsltRuntimeExtra:
+ *
+ * Extra information added to the transformation context.
+ */
+typedef struct _xsltRuntimeExtra xsltRuntimeExtra;
+typedef xsltRuntimeExtra *xsltRuntimeExtraPtr;
+struct _xsltRuntimeExtra {
+    void       *info;          /* pointer to the extra data */
+    xmlFreeFunc deallocate;    /* pointer to the deallocation routine */
+    union {                    /* dual-purpose field */
+        void   *ptr;           /* data not needing deallocation */
+       int    ival;            /* integer value storage */
+    } val;
+};
+
+/**
+ * XSLT_RUNTIME_EXTRA_LST:
+ * @ctxt: the transformation context
+ * @nr: the index
+ *
+ * Macro used to access extra information stored in the context
+ */
+#define XSLT_RUNTIME_EXTRA_LST(ctxt, nr) (ctxt)->extras[(nr)].info
+/**
+ * XSLT_RUNTIME_EXTRA_FREE:
+ * @ctxt: the transformation context
+ * @nr: the index
+ *
+ * Macro used to free extra information stored in the context
+ */
+#define XSLT_RUNTIME_EXTRA_FREE(ctxt, nr) (ctxt)->extras[(nr)].deallocate
+/**
+ * XSLT_RUNTIME_EXTRA:
+ * @ctxt: the transformation context
+ * @nr: the index
+ *
+ * Macro used to define extra information stored in the context
+ */
+#define        XSLT_RUNTIME_EXTRA(ctxt, nr, typ) (ctxt)->extras[(nr)].val.typ
+
+/**
+ * xsltTemplate:
+ *
+ * The in-memory structure corresponding to an XSLT Template.
+ */
+typedef struct _xsltTemplate xsltTemplate;
+typedef xsltTemplate *xsltTemplatePtr;
+struct _xsltTemplate {
+    struct _xsltTemplate *next;/* chained list sorted by priority */
+    struct _xsltStylesheet *style;/* the containing stylesheet */
+    xmlChar *match;    /* the matching string */
+    float priority;    /* as given from the stylesheet, not computed */
+    const xmlChar *name; /* the local part of the name QName */
+    const xmlChar *nameURI; /* the URI part of the name QName */
+    const xmlChar *mode;/* the local part of the mode QName */
+    const xmlChar *modeURI;/* the URI part of the mode QName */
+    xmlNodePtr content;        /* the template replacement value */
+    xmlNodePtr elem;   /* the source element */
+
+    /*
+    * TODO: @inheritedNsNr and @inheritedNs won't be used in the
+    *  refactored code.
+    */
+    int inheritedNsNr;  /* number of inherited namespaces */
+    xmlNsPtr *inheritedNs;/* inherited non-excluded namespaces */
+
+    /* Profiling informations */
+    int nbCalls;        /* the number of time the template was called */
+    unsigned long time; /* the time spent in this template */
+    void *params;       /* xsl:param instructions */
+};
+
+/**
+ * xsltDecimalFormat:
+ *
+ * Data structure of decimal-format.
+ */
+typedef struct _xsltDecimalFormat xsltDecimalFormat;
+typedef xsltDecimalFormat *xsltDecimalFormatPtr;
+struct _xsltDecimalFormat {
+    struct _xsltDecimalFormat *next; /* chained list */
+    xmlChar *name;
+    /* Used for interpretation of pattern */
+    xmlChar *digit;
+    xmlChar *patternSeparator;
+    /* May appear in result */
+    xmlChar *minusSign;
+    xmlChar *infinity;
+    xmlChar *noNumber; /* Not-a-number */
+    /* Used for interpretation of pattern and may appear in result */
+    xmlChar *decimalPoint;
+    xmlChar *grouping;
+    xmlChar *percent;
+    xmlChar *permille;
+    xmlChar *zeroDigit;
+};
+
+/**
+ * xsltDocument:
+ *
+ * Data structure associated to a parsed document.
+ */
+typedef struct _xsltDocument xsltDocument;
+typedef xsltDocument *xsltDocumentPtr;
+struct _xsltDocument {
+    struct _xsltDocument *next;        /* documents are kept in a chained list */
+    int main;                  /* is this the main document */
+    xmlDocPtr doc;             /* the parsed document */
+    void *keys;                        /* key tables storage */
+    struct _xsltDocument *includes; /* subsidiary includes */
+    int preproc;               /* pre-processing already done */
+    int nbKeysComputed;
+};
+
+/**
+ * xsltKeyDef:
+ *
+ * Representation of an xsl:key.
+ */
+typedef struct _xsltKeyDef xsltKeyDef;
+typedef xsltKeyDef *xsltKeyDefPtr;
+struct _xsltKeyDef {
+    struct _xsltKeyDef *next;
+    xmlNodePtr inst;
+    xmlChar *name;
+    xmlChar *nameURI;
+    xmlChar *match;
+    xmlChar *use;
+    xmlXPathCompExprPtr comp;
+    xmlXPathCompExprPtr usecomp;
+    xmlNsPtr *nsList;           /* the namespaces in scope */
+    int nsNr;                   /* the number of namespaces in scope */
+};
+
+/**
+ * xsltKeyTable:
+ *
+ * Holds the computed keys for key definitions of the same QName.
+ * Is owned by an xsltDocument.
+ */
+typedef struct _xsltKeyTable xsltKeyTable;
+typedef xsltKeyTable *xsltKeyTablePtr;
+struct _xsltKeyTable {
+    struct _xsltKeyTable *next;
+    xmlChar *name;
+    xmlChar *nameURI;
+    xmlHashTablePtr keys;
+};
+
+/*
+ * The in-memory structure corresponding to an XSLT Stylesheet.
+ * NOTE: most of the content is simply linked from the doc tree
+ *       structure, no specific allocation is made.
+ */
+typedef struct _xsltStylesheet xsltStylesheet;
+typedef xsltStylesheet *xsltStylesheetPtr;
+
+typedef struct _xsltTransformContext xsltTransformContext;
+typedef xsltTransformContext *xsltTransformContextPtr;
+
+/**
+ * xsltElemPreComp:
+ *
+ * The in-memory structure corresponding to element precomputed data,
+ * designed to be extended by extension implementors.
+ */
+typedef struct _xsltElemPreComp xsltElemPreComp;
+typedef xsltElemPreComp *xsltElemPreCompPtr;
+
+/**
+ * xsltTransformFunction:
+ * @ctxt: the XSLT transformation context
+ * @node: the input node
+ * @inst: the stylesheet node
+ * @comp: the compiled information from the stylesheet
+ *
+ * Signature of the function associated to elements part of the
+ * stylesheet language like xsl:if or xsl:apply-templates.
+ */
+typedef void (*xsltTransformFunction) (xsltTransformContextPtr ctxt,
+                                      xmlNodePtr node,
+                                      xmlNodePtr inst,
+                                      xsltElemPreCompPtr comp);
+
+/**
+ * xsltSortFunc:
+ * @ctxt:    a transformation context
+ * @sorts:   the node-set to sort
+ * @nbsorts: the number of sorts
+ *
+ * Signature of the function to use during sorting
+ */
+typedef void (*xsltSortFunc) (xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
+                             int nbsorts);
+
+typedef enum {
+    XSLT_FUNC_COPY=1,
+    XSLT_FUNC_SORT,
+    XSLT_FUNC_TEXT,
+    XSLT_FUNC_ELEMENT,
+    XSLT_FUNC_ATTRIBUTE,
+    XSLT_FUNC_COMMENT,
+    XSLT_FUNC_PI,
+    XSLT_FUNC_COPYOF,
+    XSLT_FUNC_VALUEOF,
+    XSLT_FUNC_NUMBER,
+    XSLT_FUNC_APPLYIMPORTS,
+    XSLT_FUNC_CALLTEMPLATE,
+    XSLT_FUNC_APPLYTEMPLATES,
+    XSLT_FUNC_CHOOSE,
+    XSLT_FUNC_IF,
+    XSLT_FUNC_FOREACH,
+    XSLT_FUNC_DOCUMENT,
+    XSLT_FUNC_WITHPARAM,
+    XSLT_FUNC_PARAM,
+    XSLT_FUNC_VARIABLE,
+    XSLT_FUNC_WHEN,
+    XSLT_FUNC_EXTENSION,
+#ifdef XSLT_REFACTORED
+    XSLT_FUNC_OTHERWISE,
+    XSLT_FUNC_FALLBACK,
+    XSLT_FUNC_MESSAGE,
+    XSLT_FUNC_INCLUDE,
+    XSLT_FUNC_ATTRSET,
+    XSLT_FUNC_LITERAL_RESULT_ELEMENT,
+    XSLT_FUNC_UNKOWN_FORWARDS_COMPAT,
+#endif
+} xsltStyleType;
+
+/**
+ * xsltElemPreCompDeallocator:
+ * @comp:  the #xsltElemPreComp to free up
+ *
+ * Deallocates an #xsltElemPreComp structure.
+ */
+typedef void (*xsltElemPreCompDeallocator) (xsltElemPreCompPtr comp);
+
+/**
+ * xsltElemPreComp:
+ *
+ * The basic structure for compiled items of the AST of the XSLT processor.
+ * This structure is also intended to be extended by extension implementors.
+ * TODO: This is somehow not nice, since it has a "free" field, which
+ *   derived stylesheet-structs do not have.
+ */
+struct _xsltElemPreComp {
+    xsltElemPreCompPtr next;           /* next item in the global chained
+                                          list hold by xsltStylesheet. */
+    xsltStyleType type;                /* type of the element */
+    xsltTransformFunction func;        /* handling function */
+    xmlNodePtr inst;                   /* the node in the stylesheet's tree
+                                          corresponding to this item */
+
+    /* end of common part */
+    xsltElemPreCompDeallocator free;   /* the deallocator */
+};
+
+/**
+ * xsltStylePreComp:
+ *
+ * The abstract basic structure for items of the XSLT processor.
+ * This includes:
+ * 1) compiled forms of XSLT instructions (xsl:if, xsl:attribute, etc.)
+ * 2) compiled forms of literal result elements
+ * 3) compiled forms of extension elements
+ */
+typedef struct _xsltStylePreComp xsltStylePreComp;
+typedef xsltStylePreComp *xsltStylePreCompPtr;
+
+#ifdef XSLT_REFACTORED
+
+/*
+* Some pointer-list utility functions.
+*/
+XSLTPUBFUN xsltPointerListPtr XSLTCALL
+               xsltPointerListCreate           (int initialSize);
+XSLTPUBFUN void XSLTCALL
+               xsltPointerListFree             (xsltPointerListPtr list);
+XSLTPUBFUN void XSLTCALL
+               xsltPointerListClear            (xsltPointerListPtr list);
+XSLTPUBFUN int XSLTCALL
+               xsltPointerListAddSize          (xsltPointerListPtr list,                                                
+                                                void *item,
+                                                int initialSize);
+
+/************************************************************************
+ *                                                                     *
+ * Refactored structures                                                *
+ *                                                                     *
+ ************************************************************************/
+
+typedef struct _xsltNsListContainer xsltNsListContainer;
+typedef xsltNsListContainer *xsltNsListContainerPtr;
+struct _xsltNsListContainer {
+    xmlNsPtr *list;
+    int totalNumber;
+    int xpathNumber;    
+};
+
+/**
+ * XSLT_ITEM_COMPATIBILITY_FIELDS:
+ * 
+ * Fields for API compatibility to the structure
+ * _xsltElemPreComp which is used for extension functions.
+ * Note that @next is used for storage; it does not reflect a next
+ * sibling in the tree.
+ * TODO: Evaluate if we really need such a compatibility.
+ */
+#define XSLT_ITEM_COMPATIBILITY_FIELDS \
+    xsltElemPreCompPtr next;\
+    xsltStyleType type;\
+    xsltTransformFunction func;\
+    xmlNodePtr inst;
+
+/**
+ * XSLT_ITEM_NAVIGATION_FIELDS:
+ *
+ * Currently empty.
+ * TODO: It is intended to hold navigational fields in the future.
+ */
+#define XSLT_ITEM_NAVIGATION_FIELDS
+/*
+    xsltStylePreCompPtr parent;\
+    xsltStylePreCompPtr children;\
+    xsltStylePreCompPtr nextItem; 
+*/
+
+/**
+ * XSLT_ITEM_NSINSCOPE_FIELDS:
+ *
+ * The in-scope namespaces.
+ */
+#define XSLT_ITEM_NSINSCOPE_FIELDS xsltNsListContainerPtr inScopeNs;
+
+/**
+ * XSLT_ITEM_COMMON_FIELDS:
+ *
+ * Common fields used for all items.
+ */
+#define XSLT_ITEM_COMMON_FIELDS \
+    XSLT_ITEM_COMPATIBILITY_FIELDS \
+    XSLT_ITEM_NAVIGATION_FIELDS \
+    XSLT_ITEM_NSINSCOPE_FIELDS
+
+/**
+ * _xsltStylePreComp: 
+ *
+ * The abstract basic structure for items of the XSLT processor.
+ * This includes:
+ * 1) compiled forms of XSLT instructions (e.g. xsl:if, xsl:attribute, etc.)
+ * 2) compiled forms of literal result elements
+ * 3) various properties for XSLT instructions (e.g. xsl:when,
+ *    xsl:with-param)
+ *
+ * REVISIT TODO: Keep this structure equal to the fields
+ *   defined by XSLT_ITEM_COMMON_FIELDS
+ */
+struct _xsltStylePreComp {
+    xsltElemPreCompPtr next;    /* next item in the global chained
+                                  list hold by xsltStylesheet */
+    xsltStyleType type;         /* type of the item */ 
+    xsltTransformFunction func; /* handling function */
+    xmlNodePtr inst;           /* the node in the stylesheet's tree
+                                  corresponding to this item. */
+    /* Currently no navigational fields. */
+    xsltNsListContainerPtr inScopeNs;
+};
+
+/**
+ * xsltStyleBasicEmptyItem:
+ * 
+ * Abstract structure only used as a short-cut for
+ * XSLT items with no extra fields.
+ * NOTE that it is intended that this structure looks the same as
+ *  _xsltStylePreComp.
+ */
+typedef struct _xsltStyleBasicEmptyItem xsltStyleBasicEmptyItem;
+typedef xsltStyleBasicEmptyItem *xsltStyleBasicEmptyItemPtr;
+
+struct _xsltStyleBasicEmptyItem {
+    XSLT_ITEM_COMMON_FIELDS
+};
+
+/**
+ * xsltStyleBasicExpressionItem:
+ * 
+ * Abstract structure only used as a short-cut for
+ * XSLT items with just an expression.
+ */
+typedef struct _xsltStyleBasicExpressionItem xsltStyleBasicExpressionItem;
+typedef xsltStyleBasicExpressionItem *xsltStyleBasicExpressionItemPtr;
+
+struct _xsltStyleBasicExpressionItem {
+    XSLT_ITEM_COMMON_FIELDS
+
+    const xmlChar *select; /* TODO: Change this to "expression". */
+    xmlXPathCompExprPtr comp; /* TODO: Change this to compExpr. */
+};
+
+/************************************************************************
+ *                                                                     *
+ * XSLT-instructions/declarations                                       *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltStyleItemElement:
+ * 
+ * <!-- Category: instruction -->
+ * <xsl:element
+ *  name = { qname }
+ *  namespace = { uri-reference }
+ *  use-attribute-sets = qnames>
+ *  <!-- Content: template -->
+ * </xsl:element>
+ */
+typedef struct _xsltStyleItemElement xsltStyleItemElement;
+typedef xsltStyleItemElement *xsltStyleItemElementPtr;
+
+struct _xsltStyleItemElement {
+    XSLT_ITEM_COMMON_FIELDS 
+
+    const xmlChar *use;
+    int      has_use;
+    const xmlChar *name;    
+    int      has_name;
+    const xmlChar *ns;
+    const xmlChar *nsPrefix;
+    int      has_ns;
+};
+
+/**
+ * xsltStyleItemAttribute:
+ *
+ * <!-- Category: instruction -->
+ * <xsl:attribute
+ *  name = { qname }
+ *  namespace = { uri-reference }>
+ *  <!-- Content: template -->
+ * </xsl:attribute>
+ */
+typedef struct _xsltStyleItemAttribute xsltStyleItemAttribute;
+typedef xsltStyleItemAttribute *xsltStyleItemAttributePtr;
+
+struct _xsltStyleItemAttribute {
+    XSLT_ITEM_COMMON_FIELDS
+    const xmlChar *name;
+    int      has_name;
+    const xmlChar *ns;
+    const xmlChar *nsPrefix;
+    int      has_ns;
+};
+
+/**
+ * xsltStyleItemText:
+ *
+ * <!-- Category: instruction -->
+ * <xsl:text
+ *  disable-output-escaping = "yes" | "no">
+ *  <!-- Content: #PCDATA -->
+ * </xsl:text>
+ */
+typedef struct _xsltStyleItemText xsltStyleItemText;
+typedef xsltStyleItemText *xsltStyleItemTextPtr;
+
+struct _xsltStyleItemText {
+    XSLT_ITEM_COMMON_FIELDS
+    int      noescape;         /* text */
+};
+
+/**
+ * xsltStyleItemComment:
+ *
+ * <!-- Category: instruction -->
+ *  <xsl:comment>
+ *  <!-- Content: template -->
+ * </xsl:comment>
+ */
+typedef xsltStyleBasicEmptyItem xsltStyleItemComment;
+typedef xsltStyleItemComment *xsltStyleItemCommentPtr;
+
+/**
+ * xsltStyleItemPI:
+ *
+ * <!-- Category: instruction -->
+ *  <xsl:processing-instruction
+ *  name = { ncname }>
+ *  <!-- Content: template -->
+ * </xsl:processing-instruction>
+ */
+typedef struct _xsltStyleItemPI xsltStyleItemPI;
+typedef xsltStyleItemPI *xsltStyleItemPIPtr;
+
+struct _xsltStyleItemPI {
+    XSLT_ITEM_COMMON_FIELDS
+    const xmlChar *name;
+    int      has_name;
+};
+
+/**
+ * xsltStyleItemApplyImports:
+ *
+ * <!-- Category: instruction -->
+ * <xsl:apply-imports />
+ */
+typedef xsltStyleBasicEmptyItem xsltStyleItemApplyImports;
+typedef xsltStyleItemApplyImports *xsltStyleItemApplyImportsPtr;
+
+/**
+ * xsltStyleItemApplyTemplates:
+ *
+ * <!-- Category: instruction -->
+ *  <xsl:apply-templates
+ *  select = node-set-expression
+ *  mode = qname>
+ *  <!-- Content: (xsl:sort | xsl:with-param)* -->
+ * </xsl:apply-templates>
+ */
+typedef struct _xsltStyleItemApplyTemplates xsltStyleItemApplyTemplates;
+typedef xsltStyleItemApplyTemplates *xsltStyleItemApplyTemplatesPtr;
+
+struct _xsltStyleItemApplyTemplates {
+    XSLT_ITEM_COMMON_FIELDS
+
+    const xmlChar *mode;       /* apply-templates */
+    const xmlChar *modeURI;    /* apply-templates */
+    const xmlChar *select;     /* sort, copy-of, value-of, apply-templates */
+    xmlXPathCompExprPtr comp;  /* a precompiled XPath expression */
+    /* TODO: with-params */
+};
+
+/**
+ * xsltStyleItemCallTemplate:
+ *
+ * <!-- Category: instruction -->
+ *  <xsl:call-template
+ *  name = qname>
+ *  <!-- Content: xsl:with-param* -->
+ * </xsl:call-template>
+ */
+typedef struct _xsltStyleItemCallTemplate xsltStyleItemCallTemplate;
+typedef xsltStyleItemCallTemplate *xsltStyleItemCallTemplatePtr;
+
+struct _xsltStyleItemCallTemplate {
+    XSLT_ITEM_COMMON_FIELDS
+
+    xsltTemplatePtr templ;     /* call-template */
+    const xmlChar *name;       /* element, attribute, pi */
+    int      has_name;         /* element, attribute, pi */
+    const xmlChar *ns;         /* element */
+    int      has_ns;           /* element */
+    /* TODO: with-params */
+};
+
+/**
+ * xsltStyleItemCopy:
+ *
+ * <!-- Category: instruction -->
+ * <xsl:copy
+ *  use-attribute-sets = qnames>
+ *  <!-- Content: template -->
+ * </xsl:copy>
+ */
+typedef struct _xsltStyleItemCopy xsltStyleItemCopy;
+typedef xsltStyleItemCopy *xsltStyleItemCopyPtr;
+
+struct _xsltStyleItemCopy {
+   XSLT_ITEM_COMMON_FIELDS
+    const xmlChar *use;                /* copy, element */
+    int      has_use;          /* copy, element */    
+};
+
+/**
+ * xsltStyleItemIf:
+ *
+ * <!-- Category: instruction -->
+ *  <xsl:if
+ *  test = boolean-expression>
+ *  <!-- Content: template -->
+ * </xsl:if>
+ */
+typedef struct _xsltStyleItemIf xsltStyleItemIf;
+typedef xsltStyleItemIf *xsltStyleItemIfPtr;
+
+struct _xsltStyleItemIf {
+    XSLT_ITEM_COMMON_FIELDS
+
+    const xmlChar *test;       /* if */
+    xmlXPathCompExprPtr comp;  /* a precompiled XPath expression */
+};
+
+
+/**
+ * xsltStyleItemCopyOf:
+ *
+ * <!-- Category: instruction -->
+ * <xsl:copy-of
+ *  select = expression />
+ */
+typedef xsltStyleBasicExpressionItem xsltStyleItemCopyOf;
+typedef xsltStyleItemCopyOf *xsltStyleItemCopyOfPtr;
+
+/**
+ * xsltStyleItemValueOf:
+ *
+ * <!-- Category: instruction -->
+ * <xsl:value-of
+ *  select = string-expression
+ *  disable-output-escaping = "yes" | "no" />
+ */
+typedef struct _xsltStyleItemValueOf xsltStyleItemValueOf;
+typedef xsltStyleItemValueOf *xsltStyleItemValueOfPtr;
+
+struct _xsltStyleItemValueOf {
+    XSLT_ITEM_COMMON_FIELDS
+
+    const xmlChar *select;
+    xmlXPathCompExprPtr comp;  /* a precompiled XPath expression */
+    int      noescape;
+};
+
+/**
+ * xsltStyleItemNumber:
+ *
+ * <!-- Category: instruction -->
+ *  <xsl:number
+ *  level = "single" | "multiple" | "any"
+ *  count = pattern
+ *  from = pattern
+ *  value = number-expression
+ *  format = { string }
+ *  lang = { nmtoken }
+ *  letter-value = { "alphabetic" | "traditional" }
+ *  grouping-separator = { char }
+ *  grouping-size = { number } />
+ */
+typedef struct _xsltStyleItemNumber xsltStyleItemNumber;
+typedef xsltStyleItemNumber *xsltStyleItemNumberPtr;
+
+struct _xsltStyleItemNumber {
+    XSLT_ITEM_COMMON_FIELDS
+    xsltNumberData numdata;    /* number */
+};
+
+/**
+ * xsltStyleItemChoose:
+ *
+ * <!-- Category: instruction -->
+ *  <xsl:choose>
+ *  <!-- Content: (xsl:when+, xsl:otherwise?) -->
+ * </xsl:choose>
+ */
+typedef xsltStyleBasicEmptyItem xsltStyleItemChoose;
+typedef xsltStyleItemChoose *xsltStyleItemChoosePtr;
+
+/**
+ * xsltStyleItemFallback:
+ *
+ * <!-- Category: instruction -->
+ *  <xsl:fallback>
+ *  <!-- Content: template -->
+ * </xsl:fallback>
+ */
+typedef xsltStyleBasicEmptyItem xsltStyleItemFallback;
+typedef xsltStyleItemFallback *xsltStyleItemFallbackPtr;
+
+/**
+ * xsltStyleItemForEach:
+ *
+ * <!-- Category: instruction -->
+ * <xsl:for-each
+ *   select = node-set-expression>
+ *   <!-- Content: (xsl:sort*, template) -->
+ * </xsl:for-each>
+ */
+typedef xsltStyleBasicExpressionItem xsltStyleItemForEach;
+typedef xsltStyleItemForEach *xsltStyleItemForEachPtr;
+
+/**
+ * xsltStyleItemMessage:
+ *
+ * <!-- Category: instruction -->
+ * <xsl:message
+ *   terminate = "yes" | "no">
+ *   <!-- Content: template -->
+ * </xsl:message>
+ */
+typedef struct _xsltStyleItemMessage xsltStyleItemMessage;
+typedef xsltStyleItemMessage *xsltStyleItemMessagePtr;
+
+struct _xsltStyleItemMessage {
+    XSLT_ITEM_COMMON_FIELDS    
+    int terminate;
+};
+
+/**
+ * xsltStyleItemDocument:
+ *
+ * NOTE: This is not an instruction of XSLT 1.0.
+ */
+typedef struct _xsltStyleItemDocument xsltStyleItemDocument;
+typedef xsltStyleItemDocument *xsltStyleItemDocumentPtr;
+
+struct _xsltStyleItemDocument {
+    XSLT_ITEM_COMMON_FIELDS
+    int      ver11;            /* assigned: in xsltDocumentComp;
+                                  read: nowhere;
+                                  TODO: Check if we need. */
+    const xmlChar *filename;   /* document URL */
+    int has_filename;
+};   
+
+/************************************************************************
+ *                                                                     *
+ * Non-instructions (actually properties of instructions/declarations)  *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltStyleBasicItemVariable:
+ *
+ * Basic struct for xsl:variable, xsl:param and xsl:with-param.
+ * It's currently important to have equal fields, since
+ * xsltParseStylesheetCallerParam() is used with xsl:with-param from
+ * the xslt side and with xsl:param from the exslt side (in
+ * exsltFuncFunctionFunction()).
+ *
+ * FUTURE NOTE: In XSLT 2.0 xsl:param, xsl:variable and xsl:with-param
+ *   have additional different fields.
+ */
+typedef struct _xsltStyleBasicItemVariable xsltStyleBasicItemVariable;
+typedef xsltStyleBasicItemVariable *xsltStyleBasicItemVariablePtr;
+
+struct _xsltStyleBasicItemVariable {
+    XSLT_ITEM_COMMON_FIELDS
+
+    const xmlChar *select;
+    xmlXPathCompExprPtr comp;
+
+    const xmlChar *name;
+    int      has_name;
+    const xmlChar *ns;
+    int      has_ns;
+};
+
+/**
+ * xsltStyleItemVariable:
+ *
+ * <!-- Category: top-level-element -->
+ * <xsl:param
+ *   name = qname
+ *   select = expression>
+ *   <!-- Content: template -->
+ * </xsl:param>
+ */
+typedef xsltStyleBasicItemVariable xsltStyleItemVariable;
+typedef xsltStyleItemVariable *xsltStyleItemVariablePtr;
+
+/**
+ * xsltStyleItemParam:
+ *
+ * <!-- Category: top-level-element -->
+ * <xsl:param
+ *   name = qname
+ *   select = expression>
+ *   <!-- Content: template -->
+ * </xsl:param>
+ */
+typedef struct _xsltStyleItemParam xsltStyleItemParam;
+typedef xsltStyleItemParam *xsltStyleItemParamPtr;
+
+struct _xsltStyleItemParam {
+    XSLT_ITEM_COMMON_FIELDS
+
+    const xmlChar *select;
+    xmlXPathCompExprPtr comp;
+
+    const xmlChar *name;
+    int      has_name;
+    const xmlChar *ns;
+    int      has_ns;    
+};
+
+/**
+ * xsltStyleItemWithParam:
+ *
+ * <xsl:with-param
+ *  name = qname
+ *  select = expression>
+ *  <!-- Content: template -->
+ * </xsl:with-param>
+ */
+typedef xsltStyleBasicItemVariable xsltStyleItemWithParam;
+typedef xsltStyleItemWithParam *xsltStyleItemWithParamPtr;
+
+/**
+ * xsltStyleItemSort:
+ *
+ * Reflects the XSLT xsl:sort item.
+ * Allowed parents: xsl:apply-templates, xsl:for-each
+ * <xsl:sort
+ *   select = string-expression
+ *   lang = { nmtoken }
+ *   data-type = { "text" | "number" | qname-but-not-ncname }
+ *   order = { "ascending" | "descending" }
+ *   case-order = { "upper-first" | "lower-first" } />
+ */
+typedef struct _xsltStyleItemSort xsltStyleItemSort;
+typedef xsltStyleItemSort *xsltStyleItemSortPtr;
+
+struct _xsltStyleItemSort {
+    XSLT_ITEM_COMMON_FIELDS
+
+    const xmlChar *stype;       /* sort */
+    int      has_stype;                /* sort */
+    int      number;           /* sort */
+    const xmlChar *order;      /* sort */
+    int      has_order;                /* sort */
+    int      descending;       /* sort */
+    const xmlChar *lang;       /* sort */
+    int      has_lang;         /* sort */
+    const xmlChar *case_order; /* sort */
+    int      lower_first;      /* sort */
+
+    const xmlChar *use;
+    int      has_use;
+
+    const xmlChar *select;     /* sort, copy-of, value-of, apply-templates */
+
+    xmlXPathCompExprPtr comp;  /* a precompiled XPath expression */
+};
+
+
+/**
+ * xsltStyleItemWhen:
+ * 
+ * <xsl:when
+ *   test = boolean-expression>
+ *   <!-- Content: template -->
+ * </xsl:when>
+ * Allowed parent: xsl:choose
+ */
+typedef struct _xsltStyleItemWhen xsltStyleItemWhen;
+typedef xsltStyleItemWhen *xsltStyleItemWhenPtr;
+
+struct _xsltStyleItemWhen {
+    XSLT_ITEM_COMMON_FIELDS
+
+    const xmlChar *test;
+    xmlXPathCompExprPtr comp;
+};
+
+/**
+ * xsltStyleItemOtherwise:
+ *
+ * Allowed parent: xsl:choose
+ * <xsl:otherwise>
+ *   <!-- Content: template -->
+ * </xsl:otherwise>
+ */
+typedef struct _xsltStyleItemOtherwise xsltStyleItemOtherwise;
+typedef xsltStyleItemOtherwise *xsltStyleItemOtherwisePtr;
+
+struct _xsltStyleItemOtherwise {
+    XSLT_ITEM_COMMON_FIELDS
+};
+
+typedef struct _xsltStyleItemInclude xsltStyleItemInclude;
+typedef xsltStyleItemInclude *xsltStyleItemIncludePtr;
+
+struct _xsltStyleItemInclude {
+    XSLT_ITEM_COMMON_FIELDS
+    xsltDocumentPtr include;
+};
+
+/************************************************************************
+ *                                                                     *
+ *  XSLT elements in forwards-compatible mode                           *
+ *                                                                     *
+ ************************************************************************/
+
+typedef struct _xsltStyleItemUknown xsltStyleItemUknown;
+typedef xsltStyleItemUknown *xsltStyleItemUknownPtr;
+struct _xsltStyleItemUknown {
+    XSLT_ITEM_COMMON_FIELDS
+};
+
+
+/************************************************************************
+ *                                                                     *
+ *  Extension elements                                                  *
+ *                                                                     *
+ ************************************************************************/
+
+/*
+ * xsltStyleItemExtElement:
+ *
+ * Reflects extension elements.
+ *
+ * NOTE: Due to the fact that the structure xsltElemPreComp is most
+ * probably already heavily in use out there by users, so we cannot
+ * easily change it, we'll create an intermediate structure which will
+ * hold an xsltElemPreCompPtr.
+ * BIG NOTE: The only problem I see here is that the user processes the
+ *  content of the stylesheet tree, possibly he'll lookup the node->psvi
+ *  fields in order to find subsequent extension functions.
+ *  In this case, the user's code will break, since the node->psvi
+ *  field will hold now the xsltStyleItemExtElementPtr and not
+ *  the xsltElemPreCompPtr.
+ *  However the place where the structure is anchored in the node-tree,
+ *  namely node->psvi, has beed already once been moved from node->_private
+ *  to node->psvi, so we have a precedent here, which, I think, should allow
+ *  us to change such semantics without headaches.
+ */
+typedef struct _xsltStyleItemExtElement xsltStyleItemExtElement;
+typedef xsltStyleItemExtElement *xsltStyleItemExtElementPtr;
+struct _xsltStyleItemExtElement {
+    XSLT_ITEM_COMMON_FIELDS
+    xsltElemPreCompPtr item;   
+};
+
+/************************************************************************
+ *                                                                     *
+ *  Literal result elements                                             *
+ *                                                                     *
+ ************************************************************************/
+
+typedef struct _xsltEffectiveNs xsltEffectiveNs;
+typedef xsltEffectiveNs *xsltEffectiveNsPtr;
+struct _xsltEffectiveNs {
+    xsltEffectiveNsPtr nextInStore; /* storage next */
+    xsltEffectiveNsPtr next; /* next item in the list */
+    const xmlChar *prefix;
+    const xmlChar *nsName;
+    /* 
+    * Indicates if eclared on the literal result element; dunno if really
+    * needed.
+    */
+    int holdByElem;
+};
+
+/*
+ * Info for literal result elements.
+ * This will be set on the elem->psvi field and will be
+ * shared by literal result elements, which have the same
+ * excluded result namespaces; i.e., this *won't* be created uniquely
+ * for every literal result element.
+ */
+typedef struct _xsltStyleItemLRElementInfo xsltStyleItemLRElementInfo;
+typedef xsltStyleItemLRElementInfo *xsltStyleItemLRElementInfoPtr;
+struct _xsltStyleItemLRElementInfo {
+    XSLT_ITEM_COMMON_FIELDS
+    /*
+    * @effectiveNs is the set of effective ns-nodes
+    *  on the literal result element, which will be added to the result
+    *  element if not already existing in the result tree.
+    *  This means that excluded namespaces (via exclude-result-prefixes,
+    *  extension-element-prefixes and the XSLT namespace) not added
+    *  to the set.
+    *  Namespace-aliasing was applied on the @effectiveNs.
+    */
+    xsltEffectiveNsPtr effectiveNs;
+
+};
+
+#ifdef XSLT_REFACTORED
+
+typedef struct _xsltNsAlias xsltNsAlias;
+typedef xsltNsAlias *xsltNsAliasPtr;
+struct _xsltNsAlias {
+    xsltNsAliasPtr next; /* next in the list */    
+    xmlNsPtr literalNs;
+    xmlNsPtr targetNs;
+    xmlDocPtr docOfTargetNs;
+};
+#endif
+
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+
+typedef struct _xsltNsMap xsltNsMap;
+typedef xsltNsMap *xsltNsMapPtr;
+struct _xsltNsMap {
+    xsltNsMapPtr next; /* next in the list */
+    xmlDocPtr doc;
+    xmlNodePtr elem; /* the element holding the ns-decl */
+    xmlNsPtr ns; /* the xmlNs structure holding the XML namespace name */
+    const xmlChar *origNsName; /* the original XML namespace name */
+    const xmlChar *newNsName; /* the mapped XML namespace name */    
+};
+#endif
+
+/************************************************************************
+ *                                                                     *
+ *  Compile-time structures for *internal* use only                     *
+ *                                                                     *
+ ************************************************************************/
+
+typedef struct _xsltPrincipalStylesheetData xsltPrincipalStylesheetData;
+typedef xsltPrincipalStylesheetData *xsltPrincipalStylesheetDataPtr;
+
+typedef struct _xsltNsList xsltNsList;
+typedef xsltNsList *xsltNsListPtr;
+struct _xsltNsList {
+    xsltNsListPtr next; /* next in the list */
+    xmlNsPtr ns;
+};
+
+/*
+* xsltVarInfo:
+*
+* Used at compilation time for parameters and variables.
+*/
+typedef struct _xsltVarInfo xsltVarInfo;
+typedef xsltVarInfo *xsltVarInfoPtr;
+struct _xsltVarInfo {
+    xsltVarInfoPtr next; /* next in the list */
+    xsltVarInfoPtr prev;
+    int depth; /* the depth in the tree */
+    const xmlChar *name;
+    const xmlChar *nsName;
+};
+
+#define XSLT_ELEMENT_CATEGORY_XSLT 0
+#define XSLT_ELEMENT_CATEGORY_EXTENSION 1
+#define XSLT_ELEMENT_CATEGORY_LRE 2
+
+/**
+ * xsltCompilerNodeInfo:
+ *
+ * Per-node information during compile-time.
+ */
+typedef struct _xsltCompilerNodeInfo xsltCompilerNodeInfo;
+typedef xsltCompilerNodeInfo *xsltCompilerNodeInfoPtr;
+struct _xsltCompilerNodeInfo {
+    xsltCompilerNodeInfoPtr next;
+    xsltCompilerNodeInfoPtr prev;
+    xmlNodePtr node;
+    int depth;
+    xsltTemplatePtr templ;   /* The owning template */
+    int category;           /* XSLT element, LR-element or
+                                extension element */
+    xsltStyleType type;
+    xsltElemPreCompPtr item; /* The compiled information */
+    /* The current in-scope namespaces */
+    xsltNsListContainerPtr inScopeNs;
+    /* The current excluded result namespaces */
+    xsltPointerListPtr exclResultNs; 
+    /* The current extension instruction namespaces */
+    xsltPointerListPtr extElemNs;
+
+    /* The current info for literal result elements. */
+    xsltStyleItemLRElementInfoPtr litResElemInfo;
+    /* 
+    * Set to 1 if in-scope namespaces changed,
+    *  or excluded result namespaces changed,
+    *  or extension element namespaces changed.
+    * This will trigger creation of new infos
+    *  for literal result elements.
+    */
+    int nsChanged;
+    int preserveWhitespace;
+    int stripWhitespace;
+    int isRoot; /* whether this is the stylesheet's root node */
+    int forwardsCompat; /* whether forwards-compatible mode is enabled */
+    /* whether the content of an extension element was processed */
+    int extContentHandled;
+    /* the type of the current child */
+    xsltStyleType curChildType;    
+};
+
+#define XSLT_CCTXT(style) ((xsltCompilerCtxtPtr) style->compCtxt) 
+
+typedef enum {
+    XSLT_ERROR_SEVERITY_ERROR = 0,
+    XSLT_ERROR_SEVERITY_WARNING
+} xsltErrorSeverityType;
+
+typedef struct _xsltCompilerCtxt xsltCompilerCtxt;
+typedef xsltCompilerCtxt *xsltCompilerCtxtPtr;
+struct _xsltCompilerCtxt {
+    void *errorCtxt;            /* user specific error context */
+    /*
+    * used for error/warning reports; e.g. XSLT_ERROR_SEVERITY_WARNING */
+    xsltErrorSeverityType errSeverity;         
+    int warnings;              /* TODO: number of warnings found at
+                                   compilation */
+    int errors;                        /* TODO: number of errors found at
+                                   compilation */
+    xmlDictPtr dict;
+    xsltStylesheetPtr style;
+    int simplified; /* whether this is a simplified stylesheet */
+    /* TODO: structured/unstructured error contexts. */
+    int depth; /* Current depth of processing */
+    
+    xsltCompilerNodeInfoPtr inode;
+    xsltCompilerNodeInfoPtr inodeList;
+    xsltCompilerNodeInfoPtr inodeLast;
+    xsltPointerListPtr tmpList; /* Used for various purposes */
+    /*
+    * The XSLT version as specified by the stylesheet's root element.
+    */
+    int isInclude;
+    int hasForwardsCompat; /* whether forwards-compatible mode was used
+                            in a parsing episode */
+    int maxNodeInfos; /* TEMP TODO: just for the interest */
+    int maxLREs;  /* TEMP TODO: just for the interest */
+    /* 
+    * In order to keep the old behaviour, applying strict rules of
+    * the spec can be turned off. This has effect only on special
+    * mechanisms like whitespace-stripping in the stylesheet.
+    */
+    int strict;
+    xsltPrincipalStylesheetDataPtr psData;
+#ifdef XSLT_REFACTORED_XPATHCOMP
+    xmlXPathContextPtr xpathCtxt;
+#endif
+    xsltStyleItemUknownPtr unknownItem;
+    int hasNsAliases; /* Indicator if there was an xsl:namespace-alias. */
+    xsltNsAliasPtr nsAliases;
+    xsltVarInfoPtr ivars; /* Storage of local in-scope variables/params. */
+    xsltVarInfoPtr ivar; /* topmost local variable/param. */
+};   
+
+#else /* XSLT_REFACTORED */
+/*
+* The old structures before refactoring.
+*/
+
+/**
+ * _xsltStylePreComp:
+ *
+ * The in-memory structure corresponding to XSLT stylesheet constructs
+ * precomputed data.
+ */
+struct _xsltStylePreComp {
+    xsltElemPreCompPtr next;   /* chained list */
+    xsltStyleType type;                /* type of the element */
+    xsltTransformFunction func; /* handling function */
+    xmlNodePtr inst;           /* the instruction */
+
+    /*
+     * Pre computed values.
+     */
+
+    const xmlChar *stype;       /* sort */
+    int      has_stype;                /* sort */
+    int      number;           /* sort */
+    const xmlChar *order;      /* sort */
+    int      has_order;                /* sort */
+    int      descending;       /* sort */
+    const xmlChar *lang;       /* sort */
+    int      has_lang;         /* sort */
+    const xmlChar *case_order; /* sort */
+    int      lower_first;      /* sort */
+
+    const xmlChar *use;                /* copy, element */
+    int      has_use;          /* copy, element */
+
+    int      noescape;         /* text */
+
+    const xmlChar *name;       /* element, attribute, pi */
+    int      has_name;         /* element, attribute, pi */
+    const xmlChar *ns;         /* element */
+    int      has_ns;           /* element */
+
+    const xmlChar *mode;       /* apply-templates */
+    const xmlChar *modeURI;    /* apply-templates */
+
+    const xmlChar *test;       /* if */
+
+    xsltTemplatePtr templ;     /* call-template */
+
+    const xmlChar *select;     /* sort, copy-of, value-of, apply-templates */
+
+    int      ver11;            /* document */
+    const xmlChar *filename;   /* document URL */
+    int      has_filename;     /* document */
+
+    xsltNumberData numdata;    /* number */
+
+    xmlXPathCompExprPtr comp;  /* a precompiled XPath expression */
+    xmlNsPtr *nsList;          /* the namespaces in scope */
+    int nsNr;                  /* the number of namespaces in scope */
+};
+
+#endif /* XSLT_REFACTORED */
+
+
+#define XSLT_VAR_GLOBAL 1<<0
+#define XSLT_VAR_IN_SELECT 1<<1
+#define XSLT_TCTXT_VARIABLE(c) ((xsltStackElemPtr) (c)->contextVariable)
+/*
+ * The in-memory structure corresponding to an XSLT Variable
+ * or Param.
+ */
+typedef struct _xsltStackElem xsltStackElem;
+typedef xsltStackElem *xsltStackElemPtr;
+struct _xsltStackElem {
+    struct _xsltStackElem *next;/* chained list */
+    xsltStylePreCompPtr comp;   /* the compiled form */
+    int computed;              /* was the evaluation done */
+    const xmlChar *name;       /* the local part of the name QName */
+    const xmlChar *nameURI;    /* the URI part of the name QName */
+    const xmlChar *select;     /* the eval string */
+    xmlNodePtr tree;           /* the sequence constructor if no eval
+                                   string or the location */
+    xmlXPathObjectPtr value;   /* The value if computed */
+    xmlDocPtr fragment;                /* The Result Tree Fragments (needed for XSLT 1.0)
+                                  which are bound to the variable's lifetime. */
+    int level;                  /* the depth in the tree;
+                                   -1 if persistent (e.g. a given xsl:with-param) */
+    xsltTransformContextPtr context; /* The transformation context; needed to cache
+                                        the variables */
+    int flags;
+};
+
+#ifdef XSLT_REFACTORED
+
+struct _xsltPrincipalStylesheetData {
+    /*
+    * Namespace dictionary for ns-prefixes and ns-names:
+    * TODO: Shared between stylesheets, and XPath mechanisms.
+    *   Not used yet.
+    */
+    xmlDictPtr namespaceDict;
+    /*
+    * Global list of in-scope namespaces.
+    */
+    xsltPointerListPtr inScopeNamespaces;
+    /*
+    * Global list of information for [xsl:]excluded-result-prefixes.
+    */
+    xsltPointerListPtr exclResultNamespaces;
+    /*
+    * Global list of information for [xsl:]extension-element-prefixes.
+    */
+    xsltPointerListPtr extElemNamespaces;
+    xsltEffectiveNsPtr effectiveNs;
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+    /*
+    * Namespace name map to get rid of string comparison of namespace names.
+    */
+    xsltNsMapPtr nsMap;
+#endif
+};
+
+    
+#endif
+/*
+ * Note that we added a @compCtxt field to anchor an stylesheet compilation
+ * context, since, due to historical reasons, various compile-time function
+ * take only the stylesheet as argument and not a compilation context.
+ */
+struct _xsltStylesheet {
+    /*
+     * The stylesheet import relation is kept as a tree.
+     */
+    struct _xsltStylesheet *parent;
+    struct _xsltStylesheet *next;
+    struct _xsltStylesheet *imports;
+
+    xsltDocumentPtr docList;           /* the include document list */
+
+    /*
+     * General data on the style sheet document.
+     */
+    xmlDocPtr doc;             /* the parsed XML stylesheet */
+    xmlHashTablePtr stripSpaces;/* the hash table of the strip-space and
+                                  preserve space elements */
+    int             stripAll;  /* strip-space * (1) preserve-space * (-1) */
+    xmlHashTablePtr cdataSection;/* the hash table of the cdata-section */
+
+    /*
+     * Global variable or parameters.
+     */
+    xsltStackElemPtr variables; /* linked list of param and variables */
+
+    /*
+     * Template descriptions.
+     */
+    xsltTemplatePtr templates; /* the ordered list of templates */
+    void *templatesHash;       /* hash table or wherever compiled templates
+                                  informations are stored */
+    void *rootMatch;           /* template based on / */
+    void *keyMatch;            /* template based on key() */
+    void *elemMatch;           /* template based on * */
+    void *attrMatch;           /* template based on @* */
+    void *parentMatch;         /* template based on .. */
+    void *textMatch;           /* template based on text() */
+    void *piMatch;             /* template based on processing-instruction() */
+    void *commentMatch;                /* template based on comment() */
+    
+    /*
+     * Namespace aliases.
+     * NOTE: Not used in the refactored code.
+     */
+    xmlHashTablePtr nsAliases; /* the namespace alias hash tables */
+
+    /*
+     * Attribute sets.
+     */
+    xmlHashTablePtr attributeSets;/* the attribute sets hash tables */
+
+    /*
+     * Namespaces.
+     * TODO: Eliminate this.
+     */
+    xmlHashTablePtr nsHash;     /* the set of namespaces in use:
+                                   ATTENTION: This is used for
+                                   execution of XPath expressions; unfortunately
+                                   it restricts the stylesheet to have distinct
+                                   prefixes.
+                                  TODO: We need to get rid of this.    
+                                */
+    void           *nsDefs;     /* ATTENTION TODO: This is currently used to store
+                                  xsltExtDefPtr (in extensions.c) and
+                                   *not* xmlNsPtr.
+                                */
+
+    /*
+     * Key definitions.
+     */
+    void *keys;                        /* key definitions */
+
+    /*
+     * Output related stuff.
+     */
+    xmlChar *method;           /* the output method */
+    xmlChar *methodURI;                /* associated namespace if any */
+    xmlChar *version;          /* version string */
+    xmlChar *encoding;         /* encoding string */
+    int omitXmlDeclaration;     /* omit-xml-declaration = "yes" | "no" */
+
+    /* 
+     * Number formatting.
+     */
+    xsltDecimalFormatPtr decimalFormat;
+    int standalone;             /* standalone = "yes" | "no" */
+    xmlChar *doctypePublic;     /* doctype-public string */
+    xmlChar *doctypeSystem;     /* doctype-system string */
+    int indent;                        /* should output being indented */
+    xmlChar *mediaType;                /* media-type string */
+
+    /*
+     * Precomputed blocks.
+     */
+    xsltElemPreCompPtr preComps;/* list of precomputed blocks */
+    int warnings;              /* number of warnings found at compilation */
+    int errors;                        /* number of errors found at compilation */
+
+    xmlChar  *exclPrefix;      /* last excluded prefixes */
+    xmlChar **exclPrefixTab;   /* array of excluded prefixes */
+    int       exclPrefixNr;    /* number of excluded prefixes in scope */
+    int       exclPrefixMax;   /* size of the array */
+
+    void     *_private;                /* user defined data */
+
+    /*
+     * Extensions.
+     */
+    xmlHashTablePtr extInfos;  /* the extension data */
+    int                    extrasNr;   /* the number of extras required */
+
+    /*
+     * For keeping track of nested includes
+     */
+    xsltDocumentPtr includes;  /* points to last nested include */
+
+    /*
+     * dictionary: shared between stylesheet, context and documents.
+     */
+    xmlDictPtr dict;
+    /*
+     * precompiled attribute value templates.
+     */
+    void *attVTs;
+    /*
+     * if namespace-alias has an alias for the default stylesheet prefix
+     * NOTE: Not used in the refactored code.
+     */
+    const xmlChar *defaultAlias;
+    /*
+     * bypass pre-processing (already done) (used in imports)
+     */
+    int nopreproc;
+    /*
+     * all document text strings were internalized
+     */
+    int internalized;
+    /*
+     * Literal Result Element as Stylesheet c.f. section 2.3
+     */
+    int literal_result;
+    /*
+    * The principal stylesheet
+    */
+    xsltStylesheetPtr principal;
+#ifdef XSLT_REFACTORED
+    /*
+    * Compilation context used during compile-time.
+    */
+    xsltCompilerCtxtPtr compCtxt; /* TODO: Change this to (void *). */
+
+    xsltPrincipalStylesheetDataPtr principalData;    
+#endif
+};
+
+typedef struct _xsltTransformCache xsltTransformCache;
+typedef xsltTransformCache *xsltTransformCachePtr;
+struct _xsltTransformCache {
+    xmlDocPtr RVT;
+    int nbRVT;
+    xsltStackElemPtr stackItems;
+    int nbStackItems;
+#ifdef XSLT_DEBUG_PROFILE_CACHE
+    int dbgCachedRVTs;
+    int dbgReusedRVTs;
+    int dbgCachedVars;
+    int dbgReusedVars;
+#endif
+};
+
+/*
+ * The in-memory structure corresponding to an XSLT Transformation.
+ */
+typedef enum {
+    XSLT_OUTPUT_XML = 0,
+    XSLT_OUTPUT_HTML,
+    XSLT_OUTPUT_TEXT
+} xsltOutputType;
+
+typedef enum {
+    XSLT_STATE_OK = 0,
+    XSLT_STATE_ERROR,
+    XSLT_STATE_STOPPED
+} xsltTransformState;
+
+struct _xsltTransformContext {
+    xsltStylesheetPtr style;           /* the stylesheet used */
+    xsltOutputType type;               /* the type of output */
+
+    xsltTemplatePtr  templ;            /* the current template */
+    int              templNr;          /* Nb of templates in the stack */
+    int              templMax;         /* Size of the templtes stack */
+    xsltTemplatePtr *templTab;         /* the template stack */
+
+    xsltStackElemPtr  vars;            /* the current variable list */
+    int               varsNr;          /* Nb of variable list in the stack */
+    int               varsMax;         /* Size of the variable list stack */
+    xsltStackElemPtr *varsTab;         /* the variable list stack */
+    int               varsBase;                /* the var base for current templ */
+
+    /*
+     * Extensions
+     */
+    xmlHashTablePtr   extFunctions;    /* the extension functions */
+    xmlHashTablePtr   extElements;     /* the extension elements */
+    xmlHashTablePtr   extInfos;                /* the extension data */
+
+    const xmlChar *mode;               /* the current mode */
+    const xmlChar *modeURI;            /* the current mode URI */
+
+    xsltDocumentPtr docList;           /* the document list */
+
+    xsltDocumentPtr document;          /* the current source document; can be NULL if an RTF */
+    xmlNodePtr node;                   /* the current node being processed */
+    xmlNodeSetPtr nodeList;            /* the current node list */
+    /* xmlNodePtr current;                     the node */
+
+    xmlDocPtr output;                  /* the resulting document */
+    xmlNodePtr insert;                 /* the insertion node */
+
+    xmlXPathContextPtr xpathCtxt;      /* the XPath context */
+    xsltTransformState state;          /* the current state */
+
+    /*
+     * Global variables
+     */
+    xmlHashTablePtr   globalVars;      /* the global variables and params */
+
+    xmlNodePtr inst;                   /* the instruction in the stylesheet */
+
+    int xinclude;                      /* should XInclude be processed */
+
+    const char *      outputFile;      /* the output URI if known */
+
+    int profile;                        /* is this run profiled */
+    long             prof;             /* the current profiled value */
+    int              profNr;           /* Nb of templates in the stack */
+    int              profMax;          /* Size of the templtaes stack */
+    long            *profTab;          /* the profile template stack */
+
+    void            *_private;         /* user defined data */
+
+    int              extrasNr;         /* the number of extras used */
+    int              extrasMax;                /* the number of extras allocated */
+    xsltRuntimeExtraPtr extras;                /* extra per runtime informations */
+
+    xsltDocumentPtr  styleList;                /* the stylesheet docs list */
+    void                 * sec;                /* the security preferences if any */
+
+    xmlGenericErrorFunc  error;                /* a specific error handler */
+    void              * errctx;                /* context for the error handler */
+
+    xsltSortFunc      sortfunc;                /* a ctxt specific sort routine */
+
+    /*
+     * handling of temporary Result Value Tree
+     * (XSLT 1.0 term: "Result Tree Fragment")
+     */
+    xmlDocPtr       tmpRVT;            /* list of RVT without persistance */
+    xmlDocPtr       persistRVT;                /* list of persistant RVTs */
+    int             ctxtflags;          /* context processing flags */
+
+    /*
+     * Speed optimization when coalescing text nodes
+     */
+    const xmlChar  *lasttext;          /* last text node content */
+    unsigned int    lasttsize;         /* last text node size */
+    unsigned int    lasttuse;          /* last text node use */
+    /*
+     * Per Context Debugging
+     */
+    int debugStatus;                   /* the context level debug status */
+    unsigned long* traceCode;          /* pointer to the variable holding the mask */
+
+    int parserOptions;                 /* parser options xmlParserOption */
+
+    /*
+     * dictionnary: shared between stylesheet, context and documents.
+     */
+    xmlDictPtr dict;
+    /*
+     * The current source doc; one of: the initial source doc, a RTF
+     * or a source doc aquired via the document() function.
+     */
+    xmlDocPtr          tmpDoc;
+    /*
+     * all document text strings are internalized
+     */
+    int internalized;
+    int nbKeys;
+    int hasTemplKeyPatterns;    
+    xsltTemplatePtr currentTemplateRule; /* the Current Template Rule */    
+    xmlNodePtr initialContextNode;
+    xmlDocPtr initialContextDoc;
+    xsltTransformCachePtr cache;
+    void *contextVariable; /* the current variable item */
+    xmlDocPtr localRVT; /* list of local tree fragments; will be freed when
+                          the instruction which created the fragment
+                           exits */
+    xmlDocPtr localRVTBase;    
+};
+
+/**
+ * CHECK_STOPPED:
+ *
+ * Macro to check if the XSLT processing should be stopped.
+ * Will return from the function.
+ */
+#define CHECK_STOPPED if (ctxt->state == XSLT_STATE_STOPPED) return;
+
+/**
+ * CHECK_STOPPEDE:
+ *
+ * Macro to check if the XSLT processing should be stopped.
+ * Will goto the error: label.
+ */
+#define CHECK_STOPPEDE if (ctxt->state == XSLT_STATE_STOPPED) goto error;
+
+/**
+ * CHECK_STOPPED0:
+ *
+ * Macro to check if the XSLT processing should be stopped.
+ * Will return from the function with a 0 value.
+ */
+#define CHECK_STOPPED0 if (ctxt->state == XSLT_STATE_STOPPED) return(0);
+
+/*
+ * The macro XML_CAST_FPTR is a hack to avoid a gcc warning about
+ * possible incompatibilities between function pointers and object
+ * pointers.  It is defined in libxml/hash.h within recent versions
+ * of libxml2, but is put here for compatibility.
+ */
+#ifndef XML_CAST_FPTR
+/**
+ * XML_CAST_FPTR:
+ * @fptr:  pointer to a function
+ *
+ * Macro to do a casting from an object pointer to a
+ * function pointer without encountering a warning from
+ * gcc
+ *
+ * #define XML_CAST_FPTR(fptr) (*(void **)(&fptr))
+ * This macro violated ISO C aliasing rules (gcc4 on s390 broke)
+ * so it is disabled now
+ */
+
+#define XML_CAST_FPTR(fptr) fptr
+#endif
+/*
+ * Functions associated to the internal types
+xsltDecimalFormatPtr   xsltDecimalFormatGetByName(xsltStylesheetPtr sheet,
+                                                  xmlChar *name);
+ */
+XSLTPUBFUN xsltStylesheetPtr XSLTCALL  
+                       xsltNewStylesheet       (void);
+XSLTPUBFUN xsltStylesheetPtr XSLTCALL  
+                       xsltParseStylesheetFile (const xmlChar* filename);
+XSLTPUBFUN void XSLTCALL                       
+                       xsltFreeStylesheet      (xsltStylesheetPtr style);
+XSLTPUBFUN int XSLTCALL                        
+                       xsltIsBlank             (xmlChar *str);
+XSLTPUBFUN void XSLTCALL                       
+                       xsltFreeStackElemList   (xsltStackElemPtr elem);
+XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL       
+                       xsltDecimalFormatGetByName(xsltStylesheetPtr style,
+                                                xmlChar *name);
+
+XSLTPUBFUN xsltStylesheetPtr XSLTCALL  
+                       xsltParseStylesheetProcess(xsltStylesheetPtr ret,
+                                                xmlDocPtr doc);
+XSLTPUBFUN void XSLTCALL                       
+                       xsltParseStylesheetOutput(xsltStylesheetPtr style,
+                                                xmlNodePtr cur);
+XSLTPUBFUN xsltStylesheetPtr XSLTCALL  
+                       xsltParseStylesheetDoc  (xmlDocPtr doc);
+XSLTPUBFUN xsltStylesheetPtr XSLTCALL  
+                       xsltParseStylesheetImportedDoc(xmlDocPtr doc,
+                                               xsltStylesheetPtr style);
+XSLTPUBFUN xsltStylesheetPtr XSLTCALL  
+                       xsltLoadStylesheetPI    (xmlDocPtr doc);
+XSLTPUBFUN void XSLTCALL                       
+                       xsltNumberFormat        (xsltTransformContextPtr ctxt,
+                                                xsltNumberDataPtr data,
+                                                xmlNodePtr node);
+XSLTPUBFUN xmlXPathError XSLTCALL               
+                       xsltFormatNumberConversion(xsltDecimalFormatPtr self,
+                                                xmlChar *format,
+                                                double number,
+                                                xmlChar **result);
+
+XSLTPUBFUN void XSLTCALL                       
+                       xsltParseTemplateContent(xsltStylesheetPtr style,
+                                                xmlNodePtr templ);
+XSLTPUBFUN int XSLTCALL                        
+                       xsltAllocateExtra       (xsltStylesheetPtr style);
+XSLTPUBFUN int XSLTCALL                        
+                       xsltAllocateExtraCtxt   (xsltTransformContextPtr ctxt);
+/*
+ * Extra functions for Result Value Trees
+ */
+XSLTPUBFUN xmlDocPtr XSLTCALL          
+                       xsltCreateRVT           (xsltTransformContextPtr ctxt);
+XSLTPUBFUN int XSLTCALL                        
+                       xsltRegisterTmpRVT      (xsltTransformContextPtr ctxt,
+                                                xmlDocPtr RVT);
+XSLTPUBFUN int XSLTCALL                        
+                       xsltRegisterLocalRVT    (xsltTransformContextPtr ctxt,
+                                                xmlDocPtr RVT);
+XSLTPUBFUN int XSLTCALL                        
+                       xsltRegisterPersistRVT  (xsltTransformContextPtr ctxt,
+                                                xmlDocPtr RVT);
+XSLTPUBFUN int XSLTCALL
+                       xsltExtensionInstructionResultRegister(
+                                                xsltTransformContextPtr ctxt,
+                                                xmlXPathObjectPtr obj);
+XSLTPUBFUN int XSLTCALL
+                       xsltExtensionInstructionResultFinalize(
+                                                xsltTransformContextPtr ctxt);
+XSLTPUBFUN void XSLTCALL
+                       xsltFreeRVTs            (xsltTransformContextPtr ctxt);
+XSLTPUBFUN void XSLTCALL
+                       xsltReleaseRVT          (xsltTransformContextPtr ctxt,
+                                                xmlDocPtr RVT);
+XSLTPUBFUN int XSLTCALL
+                       xsltTransStorageAdd     (xsltTransformContextPtr ctxt,
+                                                void *id,
+                                                void *data);
+XSLTPUBFUN void * XSLTCALL
+                       xsltTransStorageRemove  (xsltTransformContextPtr ctxt,
+                                                void *id);
+
+/*
+ * Extra functions for Attribute Value Templates
+ */
+XSLTPUBFUN void XSLTCALL
+                       xsltCompileAttr         (xsltStylesheetPtr style,
+                                                xmlAttrPtr attr);
+XSLTPUBFUN xmlChar * XSLTCALL
+                       xsltEvalAVT             (xsltTransformContextPtr ctxt,
+                                                void *avt,
+                                                xmlNodePtr node);
+XSLTPUBFUN void XSLTCALL
+                       xsltFreeAVTList         (void *avt);
+
+/*
+ * Extra function for successful xsltCleanupGlobals / xsltInit sequence.
+ */
+
+XSLTPUBFUN void XSLTCALL
+                       xsltUninit              (void);
+
+/************************************************************************
+ *                                                                     *
+ *  Compile-time functions for *internal* use only                      *
+ *                                                                     *
+ ************************************************************************/
+
+#ifdef XSLT_REFACTORED  
+XSLTPUBFUN void XSLTCALL
+                       xsltParseSequenceConstructor(
+                                                xsltCompilerCtxtPtr cctxt,
+                                                xmlNodePtr start);
+XSLTPUBFUN int XSLTCALL
+                       xsltParseAnyXSLTElem    (xsltCompilerCtxtPtr cctxt,
+                                                xmlNodePtr elem);
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+XSLTPUBFUN int XSLTCALL
+                       xsltRestoreDocumentNamespaces(
+                                                xsltNsMapPtr ns,
+                                                xmlDocPtr doc);
+#endif
+#endif /* XSLT_REFACTORED */
+
+/************************************************************************
+ *                                                                     *
+ *  Transformation-time functions for *internal* use only               *
+ *                                                                     *
+ ************************************************************************/
+XSLTPUBFUN int XSLTCALL
+                       xsltInitCtxtKey         (xsltTransformContextPtr ctxt,
+                                                xsltDocumentPtr doc,
+                                                xsltKeyDefPtr keyd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __XML_XSLT_H__ */
+
index 5ac608a..bc27ef6 100644 (file)
-/*\r
- * xsltutils.c: Utilities for the XSL Transformation 1.0 engine\r
- *\r
- * Reference:\r
- *   http://www.w3.org/TR/1999/REC-xslt-19991116\r
- *\r
- * See Copyright for the status of this software.\r
- *\r
- * daniel@veillard.com\r
- */\r
-\r
-#define IN_LIBXSLT\r
-#include "libxslt.h"\r
-\r
-#include <stdio.h>\r
-#include <string.h>\r
-#ifdef HAVE_SYS_TIME_H\r
-#include <sys/time.h>\r
-#endif\r
-#ifdef HAVE_UNISTD_H\r
-#include <unistd.h>\r
-#endif\r
-#ifdef HAVE_STDLIB_H\r
-#include <stdlib.h>\r
-#endif\r
-#include <stdarg.h>\r
-\r
-#include <libxml/xmlmemory.h>\r
-#include <libxml/tree.h>\r
-#include <libxml/HTMLtree.h>\r
-#include <libxml/xmlerror.h>\r
-#include <libxml/xmlIO.h>\r
-#include "xsltutils.h"\r
-#include "templates.h"\r
-#include "xsltInternals.h"\r
-#include "imports.h"\r
-#include "transform.h"\r
-\r
-/* gettimeofday on Windows ??? */\r
-#if defined(WIN32) && !defined(__CYGWIN__)\r
-#ifdef _MSC_VER\r
-#include <winsock2.h>\r
-#pragma comment(lib, "ws2_32.lib")\r
-#define gettimeofday(p1,p2)\r
-#define HAVE_GETTIMEOFDAY\r
-#define XSLT_WIN32_PERFORMANCE_COUNTER\r
-#endif /* _MS_VER */\r
-#endif /* WIN32 */\r
-\r
-#ifdef XSLT_NEED_TRIO\r
-#include "trio.h"\r
-#define vsnprintf trio_vsnprintf\r
-#endif\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                     Convenience function                            *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltGetCNsProp:\r
- * @style: the stylesheet\r
- * @node:  the node\r
- * @name:  the attribute name\r
- * @nameSpace:  the URI of the namespace\r
- *\r
- * Similar to xmlGetNsProp() but with a slightly different semantic\r
- *\r
- * Search and get the value of an attribute associated to a node\r
- * This attribute has to be anchored in the namespace specified,\r
- * or has no namespace and the element is in that namespace.\r
- *\r
- * This does the entity substitution.\r
- * This function looks in DTD attribute declaration for #FIXED or\r
- * default declaration values unless DTD use has been turned off.\r
- *\r
- * Returns the attribute value or NULL if not found. The string is allocated\r
- *         in the stylesheet dictionnary.\r
- */\r
-const xmlChar *\r
-xsltGetCNsProp(xsltStylesheetPtr style, xmlNodePtr node,\r
-              const xmlChar *name, const xmlChar *nameSpace) {\r
-    xmlAttrPtr prop;\r
-    xmlDocPtr doc;\r
-    xmlNsPtr ns;\r
-    xmlChar *tmp;\r
-    const xmlChar *ret;\r
-\r
-    if ((node == NULL) || (style == NULL) || (style->dict == NULL))\r
-       return(NULL);\r
-\r
-    prop = node->properties;\r
-    if (nameSpace == NULL) {\r
-        return xmlGetProp(node, name);\r
-    }\r
-    while (prop != NULL) {\r
-       /*\r
-        * One need to have\r
-        *   - same attribute names\r
-        *   - and the attribute carrying that namespace\r
-        */\r
-        if ((xmlStrEqual(prop->name, name)) &&\r
-           (((prop->ns == NULL) && (node->ns != NULL) &&\r
-             (xmlStrEqual(node->ns->href, nameSpace))) ||\r
-            ((prop->ns != NULL) &&\r
-             (xmlStrEqual(prop->ns->href, nameSpace))))) {\r
-\r
-           tmp = xmlNodeListGetString(node->doc, prop->children, 1);\r
-           if (tmp == NULL)\r
-               ret = xmlDictLookup(style->dict, BAD_CAST "", 0);\r
-           else {\r
-               ret = xmlDictLookup(style->dict, tmp, -1);\r
-               xmlFree(tmp);\r
-           }\r
-           return ret;\r
-        }\r
-       prop = prop->next;\r
-    }\r
-    tmp = NULL;\r
-    /*\r
-     * Check if there is a default declaration in the internal\r
-     * or external subsets\r
-     */\r
-    doc =  node->doc;\r
-    if (doc != NULL) {\r
-        if (doc->intSubset != NULL) {\r
-           xmlAttributePtr attrDecl;\r
-\r
-           attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);\r
-           if ((attrDecl == NULL) && (doc->extSubset != NULL))\r
-               attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);\r
-               \r
-           if ((attrDecl != NULL) && (attrDecl->prefix != NULL)) {\r
-               /*\r
-                * The DTD declaration only allows a prefix search\r
-                */\r
-               ns = xmlSearchNs(doc, node, attrDecl->prefix);\r
-               if ((ns != NULL) && (xmlStrEqual(ns->href, nameSpace)))\r
-                   return(xmlDictLookup(style->dict,\r
-                                        attrDecl->defaultValue, -1));\r
-           }\r
-       }\r
-    }\r
-    return(NULL);\r
-}\r
-/**\r
- * xsltGetNsProp:\r
- * @node:  the node\r
- * @name:  the attribute name\r
- * @nameSpace:  the URI of the namespace\r
- *\r
- * Similar to xmlGetNsProp() but with a slightly different semantic\r
- *\r
- * Search and get the value of an attribute associated to a node\r
- * This attribute has to be anchored in the namespace specified,\r
- * or has no namespace and the element is in that namespace.\r
- *\r
- * This does the entity substitution.\r
- * This function looks in DTD attribute declaration for #FIXED or\r
- * default declaration values unless DTD use has been turned off.\r
- *\r
- * Returns the attribute value or NULL if not found.\r
- *     It's up to the caller to free the memory.\r
- */\r
-xmlChar *\r
-xsltGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace) {\r
-    xmlAttrPtr prop;\r
-    xmlDocPtr doc;\r
-    xmlNsPtr ns;\r
-\r
-    if (node == NULL)\r
-       return(NULL);\r
-\r
-    prop = node->properties;\r
-    /*\r
-    * TODO: Substitute xmlGetProp() for xmlGetNsProp(), since the former\r
-    * is not namespace-aware and will return an attribute with equal\r
-    * name regardless of its namespace.\r
-    * Example:\r
-    *   <xsl:element foo:name="myName"/>\r
-    *   So this would return "myName" even if an attribute @name\r
-    *   in the XSLT was requested.\r
-    */\r
-    if (nameSpace == NULL)\r
-       return(xmlGetProp(node, name));\r
-    while (prop != NULL) {\r
-       /*\r
-        * One need to have\r
-        *   - same attribute names\r
-        *   - and the attribute carrying that namespace\r
-        */\r
-        if ((xmlStrEqual(prop->name, name)) &&\r
-           (((prop->ns == NULL) && (node->ns != NULL) &&\r
-             (xmlStrEqual(node->ns->href, nameSpace))) ||\r
-            ((prop->ns != NULL) &&\r
-             (xmlStrEqual(prop->ns->href, nameSpace))))) {\r
-           xmlChar *ret;\r
-\r
-           ret = xmlNodeListGetString(node->doc, prop->children, 1);\r
-           if (ret == NULL) return(xmlStrdup((xmlChar *)""));\r
-           return(ret);\r
-        }\r
-       prop = prop->next;\r
-    }\r
-\r
-    /*\r
-     * Check if there is a default declaration in the internal\r
-     * or external subsets\r
-     */\r
-    doc =  node->doc;\r
-    if (doc != NULL) {\r
-        if (doc->intSubset != NULL) {\r
-           xmlAttributePtr attrDecl;\r
-\r
-           attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);\r
-           if ((attrDecl == NULL) && (doc->extSubset != NULL))\r
-               attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);\r
-               \r
-           if ((attrDecl != NULL) && (attrDecl->prefix != NULL)) {\r
-               /*\r
-                * The DTD declaration only allows a prefix search\r
-                */\r
-               ns = xmlSearchNs(doc, node, attrDecl->prefix);\r
-               if ((ns != NULL) && (xmlStrEqual(ns->href, nameSpace)))\r
-                   return(xmlStrdup(attrDecl->defaultValue));\r
-           }\r
-       }\r
-    }\r
-    return(NULL);\r
-}\r
-\r
-/**\r
- * xsltGetUTF8Char:\r
- * @utf:  a sequence of UTF-8 encoded bytes\r
- * @len:  a pointer to @bytes len\r
- *\r
- * Read one UTF8 Char from @utf\r
- * Function copied from libxml2 xmlGetUTF8Char() ... to discard ultimately\r
- * and use the original API\r
- *\r
- * Returns the char value or -1 in case of error and update @len with the\r
- *        number of bytes used\r
- */\r
-int\r
-xsltGetUTF8Char(const unsigned char *utf, int *len) {\r
-    unsigned int c;\r
-\r
-    if (utf == NULL)\r
-       goto error;\r
-    if (len == NULL)\r
-       goto error;\r
-    if (*len < 1)\r
-       goto error;\r
-\r
-    c = utf[0];\r
-    if (c & 0x80) {\r
-       if (*len < 2)\r
-           goto error;\r
-       if ((utf[1] & 0xc0) != 0x80)\r
-           goto error;\r
-       if ((c & 0xe0) == 0xe0) {\r
-           if (*len < 3)\r
-               goto error;\r
-           if ((utf[2] & 0xc0) != 0x80)\r
-               goto error;\r
-           if ((c & 0xf0) == 0xf0) {\r
-               if (*len < 4)\r
-                   goto error;\r
-               if ((c & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)\r
-                   goto error;\r
-               *len = 4;\r
-               /* 4-byte code */\r
-               c = (utf[0] & 0x7) << 18;\r
-               c |= (utf[1] & 0x3f) << 12;\r
-               c |= (utf[2] & 0x3f) << 6;\r
-               c |= utf[3] & 0x3f;\r
-           } else {\r
-             /* 3-byte code */\r
-               *len = 3;\r
-               c = (utf[0] & 0xf) << 12;\r
-               c |= (utf[1] & 0x3f) << 6;\r
-               c |= utf[2] & 0x3f;\r
-           }\r
-       } else {\r
-         /* 2-byte code */\r
-           *len = 2;\r
-           c = (utf[0] & 0x1f) << 6;\r
-           c |= utf[1] & 0x3f;\r
-       }\r
-    } else {\r
-       /* 1-byte code */\r
-       *len = 1;\r
-    }\r
-    return(c);\r
-\r
-error:\r
-    if (len != NULL)\r
-       *len = 0;\r
-    return(-1);\r
-}\r
-\r
-#ifdef XSLT_REFACTORED\r
-\r
-/**\r
- * xsltPointerListAddSize:\r
- * @list: the pointer list structure\r
- * @item: the item to be stored\r
- * @initialSize: the initial size of the list\r
- *\r
- * Adds an item to the list.\r
- *\r
- * Returns the position of the added item in the list or\r
- *         -1 in case of an error.\r
- */\r
-int\r
-xsltPointerListAddSize(xsltPointerListPtr list,                       \r
-                      void *item,\r
-                      int initialSize)\r
-{\r
-    if (list->items == NULL) {\r
-       if (initialSize <= 0)\r
-           initialSize = 1;\r
-       list->items = (void **) xmlMalloc(\r
-           initialSize * sizeof(void *));\r
-       if (list->items == NULL) {\r
-           xsltGenericError(xsltGenericErrorContext,\r
-            "xsltPointerListAddSize: memory allocation failure.\n");\r
-           return(-1);\r
-       }\r
-       list->number = 0;\r
-       list->size = initialSize;\r
-    } else if (list->size <= list->number) {\r
-       list->size *= 2;\r
-       list->items = (void **) xmlRealloc(list->items,\r
-           list->size * sizeof(void *));\r
-       if (list->items == NULL) {\r
-           xsltGenericError(xsltGenericErrorContext,\r
-            "xsltPointerListAddSize: memory re-allocation failure.\n");\r
-           list->size = 0;\r
-           return(-1);\r
-       }\r
-    }\r
-    list->items[list->number++] = item;\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xsltPointerListCreate:\r
- *\r
- * Creates an xsltPointerList structure.\r
- *\r
- * Returns a xsltPointerList structure or NULL in case of an error.\r
- */\r
-xsltPointerListPtr\r
-xsltPointerListCreate(int initialSize)\r
-{\r
-    xsltPointerListPtr ret;\r
-\r
-    ret = xmlMalloc(sizeof(xsltPointerList));\r
-    if (ret == NULL) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-            "xsltPointerListCreate: memory allocation failure.\n");\r
-       return (NULL);\r
-    }\r
-    memset(ret, 0, sizeof(xsltPointerList));\r
-    if (initialSize > 0) {\r
-       xsltPointerListAddSize(ret, NULL, initialSize);\r
-       ret->number = 0;\r
-    }\r
-    return (ret);\r
-}\r
-\r
-/**\r
- * xsltPointerListFree:\r
- *\r
- * Frees the xsltPointerList structure. This does not free\r
- * the content of the list.\r
- */\r
-void\r
-xsltPointerListFree(xsltPointerListPtr list)\r
-{\r
-    if (list == NULL)\r
-       return;\r
-    if (list->items != NULL)\r
-       xmlFree(list->items);\r
-    xmlFree(list);\r
-}\r
-\r
-/**\r
- * xsltPointerListFree:\r
- *\r
- * Resets the list, but does not free the allocated array\r
- * and does not free the content of the list.\r
- */\r
-void\r
-xsltPointerListClear(xsltPointerListPtr list)\r
-{\r
-    if (list->items != NULL) {\r
-       xmlFree(list->items);\r
-       list->items = NULL;\r
-    }\r
-    list->number = 0;\r
-    list->size = 0;\r
-}\r
-\r
-#endif /* XSLT_REFACTORED */\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Handling of XSLT stylesheets messages                   *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltMessage:\r
- * @ctxt:  an XSLT processing context\r
- * @node:  The current node\r
- * @inst:  The node containing the message instruction\r
- *\r
- * Process and xsl:message construct\r
- */\r
-void\r
-xsltMessage(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst) {\r
-    xmlChar *prop, *message;\r
-    int terminate = 0;\r
-\r
-    if ((ctxt == NULL) || (inst == NULL))\r
-       return;\r
-\r
-    prop = xmlGetNsProp(inst, (const xmlChar *)"terminate", NULL);\r
-    if (prop != NULL) {\r
-       if (xmlStrEqual(prop, (const xmlChar *)"yes")) {\r
-           terminate = 1;\r
-       } else if (xmlStrEqual(prop, (const xmlChar *)"no")) {\r
-           terminate = 0;\r
-       } else {\r
-           xsltGenericError(xsltGenericErrorContext,\r
-               "xsl:message : terminate expecting 'yes' or 'no'\n");\r
-           ctxt->state = XSLT_STATE_ERROR;\r
-       }\r
-       xmlFree(prop);\r
-    }\r
-    message = xsltEvalTemplateString(ctxt, node, inst);\r
-    if (message != NULL) {\r
-       int len = xmlStrlen(message);\r
-\r
-       xsltGenericError(xsltGenericErrorContext, "%s",\r
-                        (const char *)message);\r
-       if ((len > 0) && (message[len - 1] != '\n'))\r
-           xsltGenericError(xsltGenericErrorContext, "\n");\r
-       xmlFree(message);\r
-    }\r
-    if (terminate)\r
-       ctxt->state = XSLT_STATE_STOPPED;\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Handling of out of context errors                       *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-#define XSLT_GET_VAR_STR(msg, str) {                           \\r
-    int       size;                                            \\r
-    int       chars;                                           \\r
-    char      *larger;                                         \\r
-    va_list   ap;                                              \\r
-                                                               \\r
-    str = (char *) xmlMalloc(150);                             \\r
-    if (str == NULL)                                           \\r
-       return;                                                 \\r
-                                                               \\r
-    size = 150;                                                        \\r
-                                                               \\r
-    while (1) {                                                        \\r
-       va_start(ap, msg);                                      \\r
-       chars = vsnprintf(str, size, msg, ap);                  \\r
-       va_end(ap);                                             \\r
-       if ((chars > -1) && (chars < size))                     \\r
-           break;                                              \\r
-       if (chars > -1)                                         \\r
-           size += chars + 1;                                  \\r
-       else                                                    \\r
-           size += 100;                                        \\r
-       if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\\r
-           xmlFree(str);                                       \\r
-           return;                                             \\r
-       }                                                       \\r
-       str = larger;                                           \\r
-    }                                                          \\r
-}\r
-/**\r
- * xsltGenericErrorDefaultFunc:\r
- * @ctx:  an error context\r
- * @msg:  the message to display/transmit\r
- * @...:  extra parameters for the message display\r
- * \r
- * Default handler for out of context error messages.\r
- */\r
-static void\r
-xsltGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {\r
-    va_list args;\r
-\r
-    if (xsltGenericErrorContext == NULL)\r
-       xsltGenericErrorContext = (void *) stderr;\r
-\r
-    va_start(args, msg);\r
-    vfprintf((FILE *)xsltGenericErrorContext, msg, args);\r
-    va_end(args);\r
-}\r
-\r
-xmlGenericErrorFunc xsltGenericError = xsltGenericErrorDefaultFunc;\r
-void *xsltGenericErrorContext = NULL;\r
-\r
-\r
-/**\r
- * xsltSetGenericErrorFunc:\r
- * @ctx:  the new error handling context\r
- * @handler:  the new handler function\r
- *\r
- * Function to reset the handler and the error context for out of\r
- * context error messages.\r
- * This simply means that @handler will be called for subsequent\r
- * error messages while not parsing nor validating. And @ctx will\r
- * be passed as first argument to @handler\r
- * One can simply force messages to be emitted to another FILE * than\r
- * stderr by setting @ctx to this file handle and @handler to NULL.\r
- */\r
-void\r
-xsltSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {\r
-    xsltGenericErrorContext = ctx;\r
-    if (handler != NULL)\r
-       xsltGenericError = handler;\r
-    else\r
-       xsltGenericError = xsltGenericErrorDefaultFunc;\r
-}\r
-\r
-/**\r
- * xsltGenericDebugDefaultFunc:\r
- * @ctx:  an error context\r
- * @msg:  the message to display/transmit\r
- * @...:  extra parameters for the message display\r
- * \r
- * Default handler for out of context error messages.\r
- */\r
-static void\r
-xsltGenericDebugDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {\r
-    va_list args;\r
-\r
-    if (xsltGenericDebugContext == NULL)\r
-       return;\r
-\r
-    va_start(args, msg);\r
-    vfprintf((FILE *)xsltGenericDebugContext, msg, args);\r
-    va_end(args);\r
-}\r
-\r
-xmlGenericErrorFunc xsltGenericDebug = xsltGenericDebugDefaultFunc;\r
-void *xsltGenericDebugContext = NULL;\r
-\r
-\r
-/**\r
- * xsltSetGenericDebugFunc:\r
- * @ctx:  the new error handling context\r
- * @handler:  the new handler function\r
- *\r
- * Function to reset the handler and the error context for out of\r
- * context error messages.\r
- * This simply means that @handler will be called for subsequent\r
- * error messages while not parsing or validating. And @ctx will\r
- * be passed as first argument to @handler\r
- * One can simply force messages to be emitted to another FILE * than\r
- * stderr by setting @ctx to this file handle and @handler to NULL.\r
- */\r
-void\r
-xsltSetGenericDebugFunc(void *ctx, xmlGenericErrorFunc handler) {\r
-    xsltGenericDebugContext = ctx;\r
-    if (handler != NULL)\r
-       xsltGenericDebug = handler;\r
-    else\r
-       xsltGenericDebug = xsltGenericDebugDefaultFunc;\r
-}\r
-\r
-/**\r
- * xsltPrintErrorContext:\r
- * @ctxt:  the transformation context\r
- * @style:  the stylesheet\r
- * @node:  the current node being processed\r
- *\r
- * Display the context of an error.\r
- */\r
-void\r
-xsltPrintErrorContext(xsltTransformContextPtr ctxt,\r
-                     xsltStylesheetPtr style, xmlNodePtr node) {\r
-    int line = 0;\r
-    const xmlChar *file = NULL;\r
-    const xmlChar *name = NULL;\r
-    const char *type = "error";\r
-    xmlGenericErrorFunc error = xsltGenericError;\r
-    void *errctx = xsltGenericErrorContext;\r
-\r
-    if (ctxt != NULL) {\r
-       ctxt->state = XSLT_STATE_ERROR;\r
-       if (ctxt->error != NULL) {\r
-           error = ctxt->error;\r
-           errctx = ctxt->errctx;\r
-       }\r
-    }\r
-    if ((node == NULL) && (ctxt != NULL))\r
-       node = ctxt->inst;\r
-\r
-    if (node != NULL)  {\r
-       if ((node->type == XML_DOCUMENT_NODE) ||\r
-           (node->type == XML_HTML_DOCUMENT_NODE)) {\r
-           xmlDocPtr doc = (xmlDocPtr) node;\r
-\r
-           file = doc->URL;\r
-       } else {\r
-           line = xmlGetLineNo(node);\r
-           if ((node->doc != NULL) && (node->doc->URL != NULL))\r
-               file = node->doc->URL;\r
-           if (node->name != NULL)\r
-               name = node->name;\r
-       }\r
-    } \r
-    \r
-    if (ctxt != NULL)\r
-       type = "runtime error";\r
-    else if (style != NULL) {\r
-#ifdef XSLT_REFACTORED\r
-       if (XSLT_CCTXT(style)->errSeverity == XSLT_ERROR_SEVERITY_WARNING)\r
-           type = "compilation warning";\r
-       else\r
-           type = "compilation error";\r
-#else\r
-       type = "compilation error";\r
-#endif\r
-    }\r
-\r
-    if ((file != NULL) && (line != 0) && (name != NULL))\r
-       error(errctx, "%s: file %s line %d element %s\n",\r
-             type, file, line, name);\r
-    else if ((file != NULL) && (name != NULL))\r
-       error(errctx, "%s: file %s element %s\n", type, file, name);\r
-    else if ((file != NULL) && (line != 0))\r
-       error(errctx, "%s: file %s line %d\n", type, file, line);\r
-    else if (file != NULL)\r
-       error(errctx, "%s: file %s\n", type, file);\r
-    else if (name != NULL)\r
-       error(errctx, "%s: element %s\n", type, name);\r
-    else\r
-       error(errctx, "%s\n", type);\r
-}\r
-\r
-/**\r
- * xsltSetTransformErrorFunc:\r
- * @ctxt:  the XSLT transformation context\r
- * @ctx:  the new error handling context\r
- * @handler:  the new handler function\r
- *\r
- * Function to reset the handler and the error context for out of\r
- * context error messages specific to a given XSLT transromation.\r
- *\r
- * This simply means that @handler will be called for subsequent\r
- * error messages while running the transformation.\r
- */\r
-void\r
-xsltSetTransformErrorFunc(xsltTransformContextPtr ctxt,\r
-                          void *ctx, xmlGenericErrorFunc handler)\r
-{\r
-    ctxt->error = handler;\r
-    ctxt->errctx = ctx;\r
-}\r
-\r
-/**\r
- * xsltTransformError:\r
- * @ctxt:  an XSLT transformation context\r
- * @style:  the XSLT stylesheet used\r
- * @node:  the current node in the stylesheet\r
- * @msg:  the message to display/transmit\r
- * @...:  extra parameters for the message display\r
- *\r
- * Display and format an error messages, gives file, line, position and\r
- * extra parameters, will use the specific transformation context if available\r
- */\r
-void\r
-xsltTransformError(xsltTransformContextPtr ctxt,\r
-                  xsltStylesheetPtr style,\r
-                  xmlNodePtr node,\r
-                  const char *msg, ...) {\r
-    xmlGenericErrorFunc error = xsltGenericError;\r
-    void *errctx = xsltGenericErrorContext;\r
-    char * str;\r
-\r
-    if (ctxt != NULL) {\r
-       ctxt->state = XSLT_STATE_ERROR;\r
-       if (ctxt->error != NULL) {\r
-           error = ctxt->error;\r
-           errctx = ctxt->errctx;\r
-       }\r
-    }\r
-    if ((node == NULL) && (ctxt != NULL))\r
-       node = ctxt->inst;\r
-    xsltPrintErrorContext(ctxt, style, node);\r
-    XSLT_GET_VAR_STR(msg, str);\r
-    error(errctx, "%s", str);\r
-    if (str != NULL)\r
-       xmlFree(str);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                             QNames                                  *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltSplitQName:\r
- * @dict: a dictionnary\r
- * @name:  the full QName\r
- * @prefix: the return value\r
- *\r
- * Split QNames into prefix and local names, both allocated from a dictionnary.\r
- *\r
- * Returns: the localname or NULL in case of error.\r
- */\r
-const xmlChar *\r
-xsltSplitQName(xmlDictPtr dict, const xmlChar *name, const xmlChar **prefix) {\r
-    int len = 0;\r
-    const xmlChar *ret = NULL;\r
-\r
-    *prefix = NULL;\r
-    if ((name == NULL) || (dict == NULL)) return(NULL);\r
-    if (name[0] == ':')\r
-        return(xmlDictLookup(dict, name, -1));\r
-    while ((name[len] != 0) && (name[len] != ':')) len++;\r
-    if (name[len] == 0) return(xmlDictLookup(dict, name, -1));\r
-    *prefix = xmlDictLookup(dict, name, len);\r
-    ret = xmlDictLookup(dict, &name[len + 1], -1);\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltGetQNameURI:\r
- * @node:  the node holding the QName\r
- * @name:  pointer to the initial QName value\r
- *\r
- * This function analyzes @name, if the name contains a prefix,\r
- * the function seaches the associated namespace in scope for it.\r
- * It will also replace @name value with the NCName, the old value being\r
- * freed.\r
- * Errors in the prefix lookup are signalled by setting @name to NULL.\r
- *\r
- * NOTE: the namespace returned is a pointer to the place where it is\r
- *       defined and hence has the same lifespan as the document holding it.\r
- *\r
- * Returns the namespace URI if there is a prefix, or NULL if @name is\r
- *         not prefixed.\r
- */\r
-const xmlChar *\r
-xsltGetQNameURI(xmlNodePtr node, xmlChar ** name)\r
-{\r
-    int len = 0;\r
-    xmlChar *qname;\r
-    xmlNsPtr ns;\r
-\r
-    if (name == NULL)\r
-       return(NULL);\r
-    qname = *name;\r
-    if ((qname == NULL) || (*qname == 0))\r
-       return(NULL);\r
-    if (node == NULL) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-                        "QName: no element for namespace lookup %s\n",\r
-                        qname);\r
-       xmlFree(qname);\r
-       *name = NULL;\r
-       return(NULL);\r
-    }\r
-\r
-    /* nasty but valid */\r
-    if (qname[0] == ':')\r
-       return(NULL);\r
-\r
-    /*\r
-     * we are not trying to validate but just to cut, and yes it will\r
-     * work even if this is a set of UTF-8 encoded chars\r
-     */\r
-    while ((qname[len] != 0) && (qname[len] != ':')) \r
-       len++;\r
-    \r
-    if (qname[len] == 0)\r
-       return(NULL);\r
-\r
-    /*\r
-     * handle xml: separately, this one is magical\r
-     */\r
-    if ((qname[0] == 'x') && (qname[1] == 'm') &&\r
-        (qname[2] == 'l') && (qname[3] == ':')) {\r
-       if (qname[4] == 0)\r
-           return(NULL);\r
-        *name = xmlStrdup(&qname[4]);\r
-       xmlFree(qname);\r
-       return(XML_XML_NAMESPACE);\r
-    }\r
-\r
-    qname[len] = 0;\r
-    ns = xmlSearchNs(node->doc, node, qname);\r
-    if (ns == NULL) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-               "%s:%s : no namespace bound to prefix %s\n",\r
-                        qname, &qname[len + 1], qname);\r
-       *name = NULL;\r
-       xmlFree(qname);\r
-       return(NULL);\r
-    }\r
-    *name = xmlStrdup(&qname[len + 1]);\r
-    xmlFree(qname);\r
-    return(ns->href);\r
-}\r
-\r
-/**\r
- * xsltGetQNameURI2:\r
- * @style:  stylesheet pointer\r
- * @node:   the node holding the QName\r
- * @name:   pointer to the initial QName value\r
- *\r
- * This function is similar to xsltGetQNameURI, but is used when\r
- * @name is a dictionary entry.\r
- *\r
- * Returns the namespace URI if there is a prefix, or NULL if @name is\r
- * not prefixed.\r
- */\r
-const xmlChar *\r
-xsltGetQNameURI2(xsltStylesheetPtr style, xmlNodePtr node,\r
-                const xmlChar **name) {\r
-    int len = 0;\r
-    xmlChar *qname;\r
-    xmlNsPtr ns;\r
-\r
-    if (name == NULL)\r
-        return(NULL);\r
-    qname = (xmlChar *)*name;\r
-    if ((qname == NULL) || (*qname == 0))\r
-        return(NULL);\r
-    if (node == NULL) {\r
-        xsltGenericError(xsltGenericErrorContext,\r
-                         "QName: no element for namespace lookup %s\n",\r
-                          qname);\r
-       *name = NULL;\r
-       return(NULL);\r
-    }\r
-\r
-    /*\r
-     * we are not trying to validate but just to cut, and yes it will\r
-     * work even if this is a set of UTF-8 encoded chars\r
-     */\r
-    while ((qname[len] != 0) && (qname[len] != ':'))\r
-        len++;\r
-\r
-    if (qname[len] == 0)\r
-        return(NULL);\r
-\r
-    /*\r
-     * handle xml: separately, this one is magical\r
-     */\r
-    if ((qname[0] == 'x') && (qname[1] == 'm') &&\r
-        (qname[2] == 'l') && (qname[3] == ':')) {\r
-        if (qname[4] == 0)\r
-            return(NULL);\r
-        *name = xmlDictLookup(style->dict, &qname[4], -1);\r
-        return(XML_XML_NAMESPACE);\r
-    }\r
-\r
-    qname = xmlStrndup(*name, len);\r
-    ns = xmlSearchNs(node->doc, node, qname);\r
-    if (ns == NULL) {\r
-       if (style) {\r
-           xsltTransformError(NULL, style, node,\r
-               "No namespace bound to prefix '%s'.\n",\r
-               qname);\r
-           style->errors++;\r
-       } else {\r
-           xsltGenericError(xsltGenericErrorContext,\r
-                "%s : no namespace bound to prefix %s\n",\r
-               *name, qname);\r
-       }\r
-        *name = NULL;\r
-        xmlFree(qname);\r
-        return(NULL);\r
-    }\r
-    *name = xmlDictLookup(style->dict, (*name)+len+1, -1);\r
-    xmlFree(qname);\r
-    return(ns->href);\r
-}\r
-                                                                                     \r
-/************************************************************************\r
- *                                                                     *\r
- *                             Sorting                                 *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltDocumentSortFunction:\r
- * @list:  the node set\r
- *\r
- * reorder the current node list @list accordingly to the document order\r
- * This function is slow, obsolete and should not be used anymore.\r
- */\r
-void\r
-xsltDocumentSortFunction(xmlNodeSetPtr list) {\r
-    int i, j;\r
-    int len, tst;\r
-    xmlNodePtr node;\r
-\r
-    if (list == NULL)\r
-       return;\r
-    len = list->nodeNr;\r
-    if (len <= 1)\r
-       return;\r
-    /* TODO: sort is really not optimized, does it needs to ? */\r
-    for (i = 0;i < len -1;i++) {\r
-       for (j = i + 1; j < len; j++) {\r
-           tst = xmlXPathCmpNodes(list->nodeTab[i], list->nodeTab[j]);\r
-           if (tst == -1) {\r
-               node = list->nodeTab[i];\r
-               list->nodeTab[i] = list->nodeTab[j];\r
-               list->nodeTab[j] = node;\r
-           }\r
-       }\r
-    }\r
-}\r
-\r
-/**\r
- * xsltComputeSortResult:\r
- * @ctxt:  a XSLT process context\r
- * @sort:  node list\r
- *\r
- * reorder the current node list accordingly to the set of sorting\r
- * requirement provided by the array of nodes.\r
- *\r
- * Returns a ordered XPath nodeset or NULL in case of error.\r
- */\r
-xmlXPathObjectPtr *\r
-xsltComputeSortResult(xsltTransformContextPtr ctxt, xmlNodePtr sort) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemSortPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    xmlXPathObjectPtr *results = NULL;\r
-    xmlNodeSetPtr list = NULL;\r
-    xmlXPathObjectPtr res;\r
-    int len = 0;\r
-    int i;    \r
-    xmlNodePtr oldNode;\r
-    xmlNodePtr oldInst;\r
-    int        oldPos, oldSize ;\r
-    int oldNsNr;\r
-    xmlNsPtr *oldNamespaces;\r
-\r
-    comp = sort->psvi;\r
-    if (comp == NULL) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-            "xsl:sort : compilation failed\n");\r
-       return(NULL);\r
-    }\r
-\r
-    if ((comp->select == NULL) || (comp->comp == NULL))\r
-       return(NULL);\r
-\r
-    list = ctxt->nodeList;\r
-    if ((list == NULL) || (list->nodeNr <= 1))\r
-       return(NULL);\r
-\r
-    len = list->nodeNr;\r
-\r
-    /* TODO: xsl:sort lang attribute */\r
-    /* TODO: xsl:sort case-order attribute */\r
-\r
-\r
-    results = xmlMalloc(len * sizeof(xmlXPathObjectPtr));\r
-    if (results == NULL) {\r
-       xsltGenericError(xsltGenericErrorContext,\r
-            "xsltComputeSortResult: memory allocation failure\n");\r
-       return(NULL);\r
-    }\r
-\r
-    oldNode = ctxt->node;\r
-    oldInst = ctxt->inst;\r
-    oldPos = ctxt->xpathCtxt->proximityPosition;\r
-    oldSize = ctxt->xpathCtxt->contextSize;\r
-    oldNsNr = ctxt->xpathCtxt->nsNr;\r
-    oldNamespaces = ctxt->xpathCtxt->namespaces;\r
-    for (i = 0;i < len;i++) {\r
-       ctxt->inst = sort;\r
-       ctxt->xpathCtxt->contextSize = len;\r
-       ctxt->xpathCtxt->proximityPosition = i + 1;\r
-       ctxt->node = list->nodeTab[i];\r
-       ctxt->xpathCtxt->node = ctxt->node;\r
-#ifdef XSLT_REFACTORED\r
-       if (comp->inScopeNs != NULL) {\r
-           ctxt->xpathCtxt->namespaces = comp->inScopeNs->list;\r
-           ctxt->xpathCtxt->nsNr = comp->inScopeNs->xpathNumber;\r
-       } else {\r
-           ctxt->xpathCtxt->namespaces = NULL;\r
-           ctxt->xpathCtxt->nsNr = 0;\r
-       }\r
-#else\r
-       ctxt->xpathCtxt->namespaces = comp->nsList;\r
-       ctxt->xpathCtxt->nsNr = comp->nsNr;\r
-#endif\r
-       res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt);\r
-       if (res != NULL) {\r
-           if (res->type != XPATH_STRING)\r
-               res = xmlXPathConvertString(res);\r
-           if (comp->number)\r
-               res = xmlXPathConvertNumber(res);\r
-           res->index = i;     /* Save original pos for dupl resolv */\r
-           if (comp->number) {\r
-               if (res->type == XPATH_NUMBER) {\r
-                   results[i] = res;\r
-               } else {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                   xsltGenericDebug(xsltGenericDebugContext,\r
-                       "xsltComputeSortResult: select didn't evaluate to a number\n");\r
-#endif\r
-                   results[i] = NULL;\r
-               }\r
-           } else {\r
-               if (res->type == XPATH_STRING) {\r
-                   results[i] = res;\r
-               } else {\r
-#ifdef WITH_XSLT_DEBUG_PROCESS\r
-                   xsltGenericDebug(xsltGenericDebugContext,\r
-                       "xsltComputeSortResult: select didn't evaluate to a string\n");\r
-#endif\r
-                   results[i] = NULL;\r
-               }\r
-           }\r
-       } else {\r
-           ctxt->state = XSLT_STATE_STOPPED;\r
-           results[i] = NULL;\r
-       }\r
-    }\r
-    ctxt->node = oldNode;\r
-    ctxt->inst = oldInst;\r
-    ctxt->xpathCtxt->contextSize = oldSize;\r
-    ctxt->xpathCtxt->proximityPosition = oldPos;\r
-    ctxt->xpathCtxt->nsNr = oldNsNr;\r
-    ctxt->xpathCtxt->namespaces = oldNamespaces;\r
-\r
-    return(results);\r
-}\r
-\r
-/**\r
- * xsltDefaultSortFunction:\r
- * @ctxt:  a XSLT process context\r
- * @sorts:  array of sort nodes\r
- * @nbsorts:  the number of sorts in the array\r
- *\r
- * reorder the current node list accordingly to the set of sorting\r
- * requirement provided by the arry of nodes.\r
- */\r
-void   \r
-xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,\r
-                  int nbsorts) {\r
-#ifdef XSLT_REFACTORED\r
-    xsltStyleItemSortPtr comp;\r
-#else\r
-    xsltStylePreCompPtr comp;\r
-#endif\r
-    xmlXPathObjectPtr *resultsTab[XSLT_MAX_SORT];\r
-    xmlXPathObjectPtr *results = NULL, *res;\r
-    xmlNodeSetPtr list = NULL;\r
-    int descending, number, desc, numb;\r
-    int len = 0;\r
-    int i, j, incr;\r
-    int tst;\r
-    int depth;\r
-    xmlNodePtr node;\r
-    xmlXPathObjectPtr tmp;    \r
-    int tempstype[XSLT_MAX_SORT], temporder[XSLT_MAX_SORT];\r
-\r
-    if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) ||\r
-       (nbsorts >= XSLT_MAX_SORT))\r
-       return;\r
-    if (sorts[0] == NULL)\r
-       return;\r
-    comp = sorts[0]->psvi;\r
-    if (comp == NULL)\r
-       return;\r
-\r
-    list = ctxt->nodeList;\r
-    if ((list == NULL) || (list->nodeNr <= 1))\r
-       return; /* nothing to do */\r
-\r
-    for (j = 0; j < nbsorts; j++) {\r
-       comp = sorts[j]->psvi;\r
-       tempstype[j] = 0;\r
-       if ((comp->stype == NULL) && (comp->has_stype != 0)) {\r
-           comp->stype =\r
-               xsltEvalAttrValueTemplate(ctxt, sorts[j],\r
-                                         (const xmlChar *) "data-type",\r
-                                         XSLT_NAMESPACE);\r
-           if (comp->stype != NULL) {\r
-               tempstype[j] = 1;\r
-               if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))\r
-                   comp->number = 0;\r
-               else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))\r
-                   comp->number = 1;\r
-               else {\r
-                   xsltTransformError(ctxt, NULL, sorts[j],\r
-                         "xsltDoSortFunction: no support for data-type = %s\n",\r
-                                    comp->stype);\r
-                   comp->number = 0; /* use default */\r
-               }\r
-           }\r
-       }\r
-       temporder[j] = 0;\r
-       if ((comp->order == NULL) && (comp->has_order != 0)) {\r
-           comp->order = xsltEvalAttrValueTemplate(ctxt, sorts[j],\r
-                                                   (const xmlChar *) "order",\r
-                                                   XSLT_NAMESPACE);\r
-           if (comp->order != NULL) {\r
-               temporder[j] = 1;\r
-               if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))\r
-                   comp->descending = 0;\r
-               else if (xmlStrEqual(comp->order,\r
-                                    (const xmlChar *) "descending"))\r
-                   comp->descending = 1;\r
-               else {\r
-                   xsltTransformError(ctxt, NULL, sorts[j],\r
-                            "xsltDoSortFunction: invalid value %s for order\n",\r
-                                    comp->order);\r
-                   comp->descending = 0; /* use default */\r
-               }\r
-           }\r
-       }\r
-    }\r
-\r
-    len = list->nodeNr;\r
-\r
-    resultsTab[0] = xsltComputeSortResult(ctxt, sorts[0]);\r
-    for (i = 1;i < XSLT_MAX_SORT;i++)\r
-       resultsTab[i] = NULL;\r
-\r
-    results = resultsTab[0];\r
-\r
-    comp = sorts[0]->psvi;\r
-    descending = comp->descending;\r
-    number = comp->number;\r
-    if (results == NULL)\r
-       return;\r
-\r
-    /* Shell's sort of node-set */\r
-    for (incr = len / 2; incr > 0; incr /= 2) {\r
-       for (i = incr; i < len; i++) {\r
-           j = i - incr;\r
-           if (results[i] == NULL)\r
-               continue;\r
-           \r
-           while (j >= 0) {\r
-               if (results[j] == NULL)\r
-                   tst = 1;\r
-               else {\r
-                   if (number) {\r
-                       /* We make NaN smaller than number in accordance\r
-                          with XSLT spec */\r
-                       if (xmlXPathIsNaN(results[j]->floatval)) {\r
-                           if (xmlXPathIsNaN(results[j + incr]->floatval))\r
-                               tst = 0;\r
-                           else\r
-                               tst = -1;\r
-                       } else if (xmlXPathIsNaN(results[j + incr]->floatval))\r
-                           tst = 1;\r
-                       else if (results[j]->floatval ==\r
-                               results[j + incr]->floatval)\r
-                           tst = 0;\r
-                       else if (results[j]->floatval > \r
-                               results[j + incr]->floatval)\r
-                           tst = 1;\r
-                       else tst = -1;\r
-                   } else {\r
-                       tst = xmlStrcmp(results[j]->stringval,\r
-                                    results[j + incr]->stringval); \r
-                   }\r
-                   if (descending)\r
-                       tst = -tst;\r
-               }\r
-               if (tst == 0) {\r
-                   /*\r
-                    * Okay we need to use multi level sorts\r
-                    */\r
-                   depth = 1;\r
-                   while (depth < nbsorts) {\r
-                       if (sorts[depth] == NULL)\r
-                           break;\r
-                       comp = sorts[depth]->psvi;\r
-                       if (comp == NULL)\r
-                           break;\r
-                       desc = comp->descending;\r
-                       numb = comp->number;\r
-\r
-                       /*\r
-                        * Compute the result of the next level for the\r
-                        * full set, this might be optimized ... or not\r
-                        */\r
-                       if (resultsTab[depth] == NULL) \r
-                           resultsTab[depth] = xsltComputeSortResult(ctxt,\r
-                                                       sorts[depth]);\r
-                       res = resultsTab[depth];\r
-                       if (res == NULL) \r
-                           break;\r
-                       if (res[j] == NULL) {\r
-                           if (res[j+incr] != NULL)\r
-                               tst = 1;\r
-                       } else {\r
-                           if (numb) {\r
-                               /* We make NaN smaller than number in\r
-                                  accordance with XSLT spec */\r
-                               if (xmlXPathIsNaN(res[j]->floatval)) {\r
-                                   if (xmlXPathIsNaN(res[j +\r
-                                               incr]->floatval))\r
-                                       tst = 0;\r
-                                   else\r
-                                       tst = -1;\r
-                               } else if (xmlXPathIsNaN(res[j + incr]->\r
-                                               floatval))\r
-                                   tst = 1;\r
-                               else if (res[j]->floatval == res[j + incr]->\r
-                                               floatval)\r
-                                   tst = 0;\r
-                               else if (res[j]->floatval > \r
-                                       res[j + incr]->floatval)\r
-                                   tst = 1;\r
-                               else tst = -1;\r
-                           } else {\r
-                               tst = xmlStrcmp(res[j]->stringval,\r
-                                            res[j + incr]->stringval); \r
-                           }\r
-                           if (desc)\r
-                               tst = -tst;\r
-                       }\r
-\r
-                       /*\r
-                        * if we still can't differenciate at this level\r
-                        * try one level deeper.\r
-                        */\r
-                       if (tst != 0)\r
-                           break;\r
-                       depth++;\r
-                   }\r
-               }\r
-               if (tst == 0) {\r
-                   tst = results[j]->index > results[j + incr]->index;\r
-               }\r
-               if (tst > 0) {\r
-                   tmp = results[j];\r
-                   results[j] = results[j + incr];\r
-                   results[j + incr] = tmp;\r
-                   node = list->nodeTab[j];\r
-                   list->nodeTab[j] = list->nodeTab[j + incr];\r
-                   list->nodeTab[j + incr] = node;\r
-                   depth = 1;\r
-                   while (depth < nbsorts) {\r
-                       if (sorts[depth] == NULL)\r
-                           break;\r
-                       if (resultsTab[depth] == NULL)\r
-                           break;\r
-                       res = resultsTab[depth];\r
-                       tmp = res[j];\r
-                       res[j] = res[j + incr];\r
-                       res[j + incr] = tmp;\r
-                       depth++;\r
-                   }\r
-                   j -= incr;\r
-               } else\r
-                   break;\r
-           }\r
-       }\r
-    }\r
-\r
-    for (j = 0; j < nbsorts; j++) {\r
-       comp = sorts[j]->psvi;\r
-       if (tempstype[j] == 1) {\r
-           /* The data-type needs to be recomputed each time */\r
-           xmlFree((void *)(comp->stype));\r
-           comp->stype = NULL;\r
-       }\r
-       if (temporder[j] == 1) {\r
-           /* The order needs to be recomputed each time */\r
-           xmlFree((void *)(comp->order));\r
-           comp->order = NULL;\r
-       }\r
-       if (resultsTab[j] != NULL) {\r
-           for (i = 0;i < len;i++)\r
-               xmlXPathFreeObject(resultsTab[j][i]);\r
-           xmlFree(resultsTab[j]);\r
-       }\r
-    }\r
-}\r
-\r
-\r
-static xsltSortFunc xsltSortFunction = xsltDefaultSortFunction;\r
-\r
-/**\r
- * xsltDoSortFunction:\r
- * @ctxt:  a XSLT process context\r
- * @sorts:  array of sort nodes\r
- * @nbsorts:  the number of sorts in the array\r
- *\r
- * reorder the current node list accordingly to the set of sorting\r
- * requirement provided by the arry of nodes.\r
- * This is a wrapper function, the actual function used is specified\r
- * using xsltSetCtxtSortFunc() to set the context specific sort function,\r
- * or xsltSetSortFunc() to set the global sort function.\r
- * If a sort function is set on the context, this will get called.\r
- * Otherwise the global sort function is called.\r
- */\r
-void\r
-xsltDoSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr * sorts,\r
-                   int nbsorts)\r
-{\r
-    if (ctxt->sortfunc != NULL)\r
-       (ctxt->sortfunc)(ctxt, sorts, nbsorts);\r
-    else if (xsltSortFunction != NULL)\r
-        xsltSortFunction(ctxt, sorts, nbsorts);\r
-}\r
-\r
-/**\r
- * xsltSetSortFunc:\r
- * @handler:  the new handler function\r
- *\r
- * Function to reset the global handler for XSLT sorting.\r
- * If the handler is NULL, the default sort function will be used.\r
- */\r
-void\r
-xsltSetSortFunc(xsltSortFunc handler) {\r
-    if (handler != NULL)\r
-       xsltSortFunction = handler;\r
-    else\r
-       xsltSortFunction = xsltDefaultSortFunction;\r
-}\r
-\r
-/**\r
- * xsltSetCtxtSortFunc:\r
- * @ctxt:  a XSLT process context\r
- * @handler:  the new handler function\r
- *\r
- * Function to set the handler for XSLT sorting\r
- * for the specified context. \r
- * If the handler is NULL, then the global\r
- * sort function will be called\r
- */\r
-void \r
-xsltSetCtxtSortFunc(xsltTransformContextPtr ctxt, xsltSortFunc handler) {\r
-    ctxt->sortfunc = handler;\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                             Parsing options                         *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltSetCtxtParseOptions:\r
- * @ctxt:  a XSLT process context\r
- * @options:  a combination of libxml2 xmlParserOption\r
- * \r
- * Change the default parser option passed by the XSLT engine to the \r
- * parser when using document() loading.\r
- *\r
- * Returns the previous options or -1 in case of error\r
- */\r
-int \r
-xsltSetCtxtParseOptions(xsltTransformContextPtr ctxt, int options)\r
-{\r
-    int oldopts;\r
-\r
-    if (ctxt == NULL)\r
-        return(-1);\r
-    oldopts = ctxt->parserOptions;\r
-    ctxt->parserOptions = options;\r
-    return(oldopts);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *                             Output                                  *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltSaveResultTo:\r
- * @buf:  an output buffer\r
- * @result:  the result xmlDocPtr\r
- * @style:  the stylesheet\r
- *\r
- * Save the result @result obtained by applying the @style stylesheet\r
- * to an I/O output channel @buf\r
- *\r
- * Returns the number of byte written or -1 in case of failure.\r
- */\r
-int\r
-xsltSaveResultTo(xmlOutputBufferPtr buf, xmlDocPtr result,\r
-              xsltStylesheetPtr style) {\r
-    const xmlChar *encoding;\r
-    int base;\r
-    const xmlChar *method;\r
-    int indent;\r
-\r
-    if ((buf == NULL) || (result == NULL) || (style == NULL))\r
-       return(-1);\r
-    if ((result->children == NULL) ||\r
-       ((result->children->type == XML_DTD_NODE) &&\r
-        (result->children->next == NULL)))\r
-       return(0);\r
-\r
-    if ((style->methodURI != NULL) &&\r
-       ((style->method == NULL) ||\r
-        (!xmlStrEqual(style->method, (const xmlChar *) "xhtml")))) {\r
-        xsltGenericError(xsltGenericErrorContext,\r
-               "xsltSaveResultTo : unknown ouput method\n");\r
-        return(-1);\r
-    }\r
-\r
-    base = buf->written;\r
-\r
-    XSLT_GET_IMPORT_PTR(method, style, method)\r
-    XSLT_GET_IMPORT_PTR(encoding, style, encoding)\r
-    XSLT_GET_IMPORT_INT(indent, style, indent);\r
-\r
-    if ((method == NULL) && (result->type == XML_HTML_DOCUMENT_NODE))\r
-       method = (const xmlChar *) "html";\r
-\r
-    if ((method != NULL) &&\r
-       (xmlStrEqual(method, (const xmlChar *) "html"))) {\r
-       if (encoding != NULL) {\r
-           htmlSetMetaEncoding(result, (const xmlChar *) encoding);\r
-       } else {\r
-           htmlSetMetaEncoding(result, (const xmlChar *) "UTF-8");\r
-       }\r
-       if (indent == -1)\r
-           indent = 1;\r
-       htmlDocContentDumpFormatOutput(buf, result, (const char *) encoding,\r
-                                      indent);\r
-       xmlOutputBufferFlush(buf);\r
-    } else if ((method != NULL) &&\r
-       (xmlStrEqual(method, (const xmlChar *) "xhtml"))) {\r
-       if (encoding != NULL) {\r
-           htmlSetMetaEncoding(result, (const xmlChar *) encoding);\r
-       } else {\r
-           htmlSetMetaEncoding(result, (const xmlChar *) "UTF-8");\r
-       }\r
-       htmlDocContentDumpOutput(buf, result, (const char *) encoding);\r
-       xmlOutputBufferFlush(buf);\r
-    } else if ((method != NULL) &&\r
-              (xmlStrEqual(method, (const xmlChar *) "text"))) {\r
-       xmlNodePtr cur;\r
-\r
-       cur = result->children;\r
-       while (cur != NULL) {\r
-           if (cur->type == XML_TEXT_NODE)\r
-               xmlOutputBufferWriteString(buf, (const char *) cur->content);\r
-\r
-           /*\r
-            * Skip to next node\r
-            */\r
-           if (cur->children != NULL) {\r
-               if ((cur->children->type != XML_ENTITY_DECL) &&\r
-                   (cur->children->type != XML_ENTITY_REF_NODE) &&\r
-                   (cur->children->type != XML_ENTITY_NODE)) {\r
-                   cur = cur->children;\r
-                   continue;\r
-               }\r
-           }\r
-           if (cur->next != NULL) {\r
-               cur = cur->next;\r
-               continue;\r
-           }\r
-           \r
-           do {\r
-               cur = cur->parent;\r
-               if (cur == NULL)\r
-                   break;\r
-               if (cur == (xmlNodePtr) style->doc) {\r
-                   cur = NULL;\r
-                   break;\r
-               }\r
-               if (cur->next != NULL) {\r
-                   cur = cur->next;\r
-                   break;\r
-               }\r
-           } while (cur != NULL);\r
-       }\r
-       xmlOutputBufferFlush(buf);\r
-    } else {\r
-       int omitXmlDecl;\r
-       int standalone;\r
-\r
-       XSLT_GET_IMPORT_INT(omitXmlDecl, style, omitXmlDeclaration);\r
-       XSLT_GET_IMPORT_INT(standalone, style, standalone);\r
-\r
-       if (omitXmlDecl != 1) {\r
-           xmlOutputBufferWriteString(buf, "<?xml version=");\r
-           if (result->version != NULL) \r
-               xmlBufferWriteQuotedString(buf->buffer, result->version);\r
-           else\r
-               xmlOutputBufferWriteString(buf, "\"1.0\"");\r
-           if (encoding == NULL) {\r
-               if (result->encoding != NULL)\r
-                   encoding = result->encoding;\r
-               else if (result->charset != XML_CHAR_ENCODING_UTF8)\r
-                   encoding = (const xmlChar *)\r
-                              xmlGetCharEncodingName((xmlCharEncoding)\r
-                                                     result->charset);\r
-           }\r
-           if (encoding != NULL) {\r
-               xmlOutputBufferWriteString(buf, " encoding=");\r
-               xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);\r
-           }\r
-           switch (standalone) {\r
-               case 0:\r
-                   xmlOutputBufferWriteString(buf, " standalone=\"no\"");\r
-                   break;\r
-               case 1:\r
-                   xmlOutputBufferWriteString(buf, " standalone=\"yes\"");\r
-                   break;\r
-               default:\r
-                   break;\r
-           }\r
-           xmlOutputBufferWriteString(buf, "?>\n");\r
-       }\r
-       if (result->children != NULL) {\r
-           xmlNodePtr child = result->children;\r
-\r
-           while (child != NULL) {\r
-               xmlNodeDumpOutput(buf, result, child, 0, (indent == 1),\r
-                                 (const char *) encoding);\r
-               if ((child->type == XML_DTD_NODE) ||\r
-                   ((child->type == XML_COMMENT_NODE) &&\r
-                    (child->next != NULL)))\r
-                   xmlOutputBufferWriteString(buf, "\n");\r
-               child = child->next;\r
-           }\r
-           xmlOutputBufferWriteString(buf, "\n");\r
-       }\r
-       xmlOutputBufferFlush(buf);\r
-    }\r
-    return(buf->written - base);\r
-}\r
-\r
-/**\r
- * xsltSaveResultToFilename:\r
- * @URL:  a filename or URL\r
- * @result:  the result xmlDocPtr\r
- * @style:  the stylesheet\r
- * @compression:  the compression factor (0 - 9 included)\r
- *\r
- * Save the result @result obtained by applying the @style stylesheet\r
- * to a file or @URL\r
- *\r
- * Returns the number of byte written or -1 in case of failure.\r
- */\r
-int\r
-xsltSaveResultToFilename(const char *URL, xmlDocPtr result,\r
-                        xsltStylesheetPtr style, int compression) {\r
-    xmlOutputBufferPtr buf;\r
-    const xmlChar *encoding;\r
-    int ret;\r
-\r
-    if ((URL == NULL) || (result == NULL) || (style == NULL))\r
-       return(-1);\r
-    if (result->children == NULL)\r
-       return(0);\r
-\r
-    XSLT_GET_IMPORT_PTR(encoding, style, encoding)\r
-    if (encoding != NULL) {\r
-       xmlCharEncodingHandlerPtr encoder;\r
-\r
-       encoder = xmlFindCharEncodingHandler((char *)encoding);\r
-       if ((encoder != NULL) &&\r
-           (xmlStrEqual((const xmlChar *)encoder->name,\r
-                        (const xmlChar *) "UTF-8")))\r
-           encoder = NULL;\r
-       buf = xmlOutputBufferCreateFilename(URL, encoder, compression);\r
-    } else {\r
-       buf = xmlOutputBufferCreateFilename(URL, NULL, compression);\r
-    }\r
-    if (buf == NULL)\r
-       return(-1);\r
-    xsltSaveResultTo(buf, result, style);\r
-    ret = xmlOutputBufferClose(buf);\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltSaveResultToFile:\r
- * @file:  a FILE * I/O\r
- * @result:  the result xmlDocPtr\r
- * @style:  the stylesheet\r
- *\r
- * Save the result @result obtained by applying the @style stylesheet\r
- * to an open FILE * I/O.\r
- * This does not close the FILE @file\r
- *\r
- * Returns the number of bytes written or -1 in case of failure.\r
- */\r
-int\r
-xsltSaveResultToFile(FILE *file, xmlDocPtr result, xsltStylesheetPtr style) {\r
-    xmlOutputBufferPtr buf;\r
-    const xmlChar *encoding;\r
-    int ret;\r
-\r
-    if ((file == NULL) || (result == NULL) || (style == NULL))\r
-       return(-1);\r
-    if (result->children == NULL)\r
-       return(0);\r
-\r
-    XSLT_GET_IMPORT_PTR(encoding, style, encoding)\r
-    if (encoding != NULL) {\r
-       xmlCharEncodingHandlerPtr encoder;\r
-\r
-       encoder = xmlFindCharEncodingHandler((char *)encoding);\r
-       if ((encoder != NULL) &&\r
-           (xmlStrEqual((const xmlChar *)encoder->name,\r
-                        (const xmlChar *) "UTF-8")))\r
-           encoder = NULL;\r
-       buf = xmlOutputBufferCreateFile(file, encoder);\r
-    } else {\r
-       buf = xmlOutputBufferCreateFile(file, NULL);\r
-    }\r
-\r
-    if (buf == NULL)\r
-       return(-1);\r
-    xsltSaveResultTo(buf, result, style);\r
-    ret = xmlOutputBufferClose(buf);\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltSaveResultToFd:\r
- * @fd:  a file descriptor\r
- * @result:  the result xmlDocPtr\r
- * @style:  the stylesheet\r
- *\r
- * Save the result @result obtained by applying the @style stylesheet\r
- * to an open file descriptor\r
- * This does not close the descriptor.\r
- *\r
- * Returns the number of bytes written or -1 in case of failure.\r
- */\r
-int\r
-xsltSaveResultToFd(int fd, xmlDocPtr result, xsltStylesheetPtr style) {\r
-    xmlOutputBufferPtr buf;\r
-    const xmlChar *encoding;\r
-    int ret;\r
-\r
-    if ((fd < 0) || (result == NULL) || (style == NULL))\r
-       return(-1);\r
-    if (result->children == NULL)\r
-       return(0);\r
-\r
-    XSLT_GET_IMPORT_PTR(encoding, style, encoding)\r
-    if (encoding != NULL) {\r
-       xmlCharEncodingHandlerPtr encoder;\r
-\r
-       encoder = xmlFindCharEncodingHandler((char *)encoding);\r
-       if ((encoder != NULL) &&\r
-           (xmlStrEqual((const xmlChar *)encoder->name,\r
-                        (const xmlChar *) "UTF-8")))\r
-           encoder = NULL;\r
-       buf = xmlOutputBufferCreateFd(fd, encoder);\r
-    } else {\r
-       buf = xmlOutputBufferCreateFd(fd, NULL);\r
-    }\r
-    if (buf == NULL)\r
-       return(-1);\r
-    xsltSaveResultTo(buf, result, style);\r
-    ret = xmlOutputBufferClose(buf);\r
-    return(ret);\r
-}\r
-\r
-/**\r
- * xsltSaveResultToString:\r
- * @doc_txt_ptr:  Memory pointer for allocated XML text\r
- * @doc_txt_len:  Length of the generated XML text\r
- * @result:  the result xmlDocPtr\r
- * @style:  the stylesheet\r
- *\r
- * Save the result @result obtained by applying the @style stylesheet\r
- * to a new allocated string.\r
- *\r
- * Returns 0 in case of success and -1 in case of error\r
- */\r
-int\r
-xsltSaveResultToString(xmlChar **doc_txt_ptr, int * doc_txt_len, \r
-                      xmlDocPtr result, xsltStylesheetPtr style) {\r
-    xmlOutputBufferPtr buf;\r
-    const xmlChar *encoding;\r
-\r
-    *doc_txt_ptr = NULL;\r
-    *doc_txt_len = 0;\r
-    if (result->children == NULL)\r
-       return(0);\r
-\r
-    XSLT_GET_IMPORT_PTR(encoding, style, encoding)\r
-    if (encoding != NULL) {\r
-       xmlCharEncodingHandlerPtr encoder;\r
-\r
-       encoder = xmlFindCharEncodingHandler((char *)encoding);\r
-       if ((encoder != NULL) &&\r
-           (xmlStrEqual((const xmlChar *)encoder->name,\r
-                        (const xmlChar *) "UTF-8")))\r
-           encoder = NULL;\r
-       buf = xmlAllocOutputBuffer(encoder);\r
-    } else {\r
-       buf = xmlAllocOutputBuffer(NULL);\r
-    }\r
-    if (buf == NULL)\r
-       return(-1);\r
-    xsltSaveResultTo(buf, result, style);\r
-    if (buf->conv != NULL) {\r
-       *doc_txt_len = buf->conv->use;\r
-       *doc_txt_ptr = xmlStrndup(buf->conv->content, *doc_txt_len);\r
-    } else {\r
-       *doc_txt_len = buf->buffer->use;\r
-       *doc_txt_ptr = xmlStrndup(buf->buffer->content, *doc_txt_len);\r
-    }\r
-    (void)xmlOutputBufferClose(buf);\r
-    return 0;\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Generating profiling informations                       *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-static long calibration = -1;\r
-\r
-/**\r
- * xsltCalibrateTimestamps:\r
- *\r
- * Used for to calibrate the xsltTimestamp() function\r
- * Should work if launched at startup and we don't loose our quantum :-)\r
- *\r
- * Returns the number of milliseconds used by xsltTimestamp()\r
- */\r
-static long\r
-xsltCalibrateTimestamps(void) {\r
-    register int i;\r
-\r
-    for (i = 0;i < 999;i++)\r
-       xsltTimestamp();\r
-    return(xsltTimestamp() / 1000);\r
-}\r
-\r
-/**\r
- * xsltCalibrateAdjust:\r
- * @delta:  a negative dealy value found\r
- *\r
- * Used for to correct the calibration for xsltTimestamp()\r
- */\r
-void\r
-xsltCalibrateAdjust(long delta) {\r
-    calibration += delta;\r
-}\r
-\r
-/**\r
- * xsltTimestamp:\r
- *\r
- * Used for gathering profiling data\r
- *\r
- * Returns the number of tenth of milliseconds since the beginning of the\r
- * profiling\r
- */\r
-long\r
-xsltTimestamp(void)\r
-{\r
-#ifdef XSLT_WIN32_PERFORMANCE_COUNTER\r
-    BOOL ok;\r
-    LARGE_INTEGER performanceCount;\r
-    LARGE_INTEGER performanceFrequency;\r
-    LONGLONG quadCount;\r
-    double seconds;\r
-    static LONGLONG startupQuadCount = 0;\r
-    static LONGLONG startupQuadFreq = 0;\r
-\r
-    ok = QueryPerformanceCounter(&performanceCount);\r
-    if (!ok)\r
-        return 0;\r
-    quadCount = performanceCount.QuadPart;\r
-    if (calibration < 0) {\r
-        calibration = 0;\r
-        ok = QueryPerformanceFrequency(&performanceFrequency);\r
-        if (!ok)\r
-            return 0;\r
-        startupQuadFreq = performanceFrequency.QuadPart;\r
-        startupQuadCount = quadCount;\r
-        return (0);\r
-    }\r
-    if (startupQuadFreq == 0)\r
-        return 0;\r
-    seconds = (quadCount - startupQuadCount) / (double) startupQuadFreq;\r
-    return (long) (seconds * XSLT_TIMESTAMP_TICS_PER_SEC);\r
-\r
-#else /* XSLT_WIN32_PERFORMANCE_COUNTER */\r
-#ifdef HAVE_GETTIMEOFDAY\r
-    static struct timeval startup;\r
-    struct timeval cur;\r
-    long tics;\r
-\r
-    if (calibration < 0) {\r
-        gettimeofday(&startup, NULL);\r
-        calibration = 0;\r
-        calibration = xsltCalibrateTimestamps();\r
-        gettimeofday(&startup, NULL);\r
-        return (0);\r
-    }\r
-\r
-    gettimeofday(&cur, NULL);\r
-    tics = (cur.tv_sec - startup.tv_sec) * XSLT_TIMESTAMP_TICS_PER_SEC;\r
-    tics += (cur.tv_usec - startup.tv_usec) /\r
-                          (1000000l / XSLT_TIMESTAMP_TICS_PER_SEC);\r
-    \r
-    tics -= calibration;\r
-    return(tics);\r
-#else\r
-\r
-    /* Neither gettimeofday() nor Win32 performance counter available */\r
-\r
-    return (0);\r
-\r
-#endif /* HAVE_GETTIMEOFDAY */\r
-#endif /* XSLT_WIN32_PERFORMANCE_COUNTER */\r
-}\r
-\r
-#define MAX_TEMPLATES 10000\r
-\r
-/**\r
- * xsltSaveProfiling:\r
- * @ctxt:  an XSLT context\r
- * @output:  a FILE * for saving the informations\r
- *\r
- * Save the profiling informations on @output\r
- */\r
-void\r
-xsltSaveProfiling(xsltTransformContextPtr ctxt, FILE *output) {\r
-    int nb, i,j;\r
-    int max;\r
-    int total;\r
-    long totalt;\r
-    xsltTemplatePtr *templates;\r
-    xsltStylesheetPtr style;\r
-    xsltTemplatePtr template;\r
-\r
-    if ((output == NULL) || (ctxt == NULL))\r
-       return;\r
-    if (ctxt->profile == 0)\r
-       return;\r
-\r
-    nb = 0;\r
-    max = MAX_TEMPLATES;\r
-    templates = xmlMalloc(max * sizeof(xsltTemplatePtr));\r
-    if (templates == NULL)\r
-       return;\r
-\r
-    style = ctxt->style;\r
-    while (style != NULL) {\r
-       template = style->templates;\r
-       while (template != NULL) {\r
-           if (nb >= max)\r
-               break;\r
-\r
-           if (template->nbCalls > 0)\r
-               templates[nb++] = template;\r
-           template = template->next;\r
-       }\r
-\r
-       style = xsltNextImport(style);\r
-    }\r
-\r
-    for (i = 0;i < nb -1;i++) {\r
-       for (j = i + 1; j < nb; j++) {\r
-           if ((templates[i]->time <= templates[j]->time) ||\r
-               ((templates[i]->time == templates[j]->time) &&\r
-                (templates[i]->nbCalls <= templates[j]->nbCalls))) {\r
-               template = templates[j];\r
-               templates[j] = templates[i];\r
-               templates[i] = template;\r
-           }\r
-       }\r
-    }\r
-\r
-    fprintf(output, "%6s%20s%20s%10s  Calls Tot 100us Avg\n\n",\r
-           "number", "match", "name", "mode");\r
-    total = 0;\r
-    totalt = 0;\r
-    for (i = 0;i < nb;i++) {\r
-       fprintf(output, "%5d ", i);\r
-       if (templates[i]->match != NULL) {\r
-           if (xmlStrlen(templates[i]->match) > 20)\r
-               fprintf(output, "%s\n%26s", templates[i]->match, "");\r
-           else\r
-               fprintf(output, "%20s", templates[i]->match);\r
-       } else {\r
-           fprintf(output, "%20s", "");\r
-       }\r
-       if (templates[i]->name != NULL) {\r
-           if (xmlStrlen(templates[i]->name) > 20)\r
-               fprintf(output, "%s\n%46s", templates[i]->name, "");\r
-           else\r
-               fprintf(output, "%20s", templates[i]->name);\r
-       } else {\r
-           fprintf(output, "%20s", "");\r
-       }\r
-       if (templates[i]->mode != NULL) {\r
-           if (xmlStrlen(templates[i]->mode) > 10)\r
-               fprintf(output, "%s\n%56s", templates[i]->mode, "");\r
-           else\r
-               fprintf(output, "%10s", templates[i]->mode);\r
-       } else {\r
-           fprintf(output, "%10s", "");\r
-       }\r
-       fprintf(output, " %6d", templates[i]->nbCalls);\r
-       fprintf(output, " %6ld %6ld\n", templates[i]->time,\r
-               templates[i]->time / templates[i]->nbCalls);\r
-       total += templates[i]->nbCalls;\r
-       totalt += templates[i]->time;\r
-    }\r
-    fprintf(output, "\n%30s%26s %6d %6ld\n", "Total", "", total, totalt);\r
-\r
-    xmlFree(templates);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Fetching profiling informations                         *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltGetProfileInformation:\r
- * @ctxt:  a transformation context\r
- *\r
- * This function should be called after the transformation completed\r
- * to extract template processing profiling informations if availble.\r
- * The informations are returned as an XML document tree like\r
- * <?xml version="1.0"?>\r
- * <profile>\r
- * <template rank="1" match="*" name=""\r
- *         mode="" calls="6" time="48" average="8"/>\r
- * <template rank="2" match="item2|item3" name=""\r
- *         mode="" calls="10" time="30" average="3"/>\r
- * <template rank="3" match="item1" name=""\r
- *         mode="" calls="5" time="17" average="3"/>\r
- * </profile>\r
- * The caller will need to free up the returned tree with xmlFreeDoc()\r
- *\r
- * Returns the xmlDocPtr corresponding to the result or NULL if not available.\r
- */\r
-\r
-xmlDocPtr\r
-xsltGetProfileInformation(xsltTransformContextPtr ctxt)\r
-{\r
-    xmlDocPtr ret = NULL;\r
-    xmlNodePtr root, child;\r
-    char buf[100];\r
-\r
-    xsltStylesheetPtr style;\r
-    xsltTemplatePtr *templates;\r
-    xsltTemplatePtr templ;\r
-    int nb = 0, max = 0, i, j;\r
-\r
-    if (!ctxt)\r
-        return NULL;\r
-\r
-    if (!ctxt->profile)\r
-        return NULL;\r
-\r
-    nb = 0;\r
-    max = 10000;\r
-    templates =\r
-        (xsltTemplatePtr *) xmlMalloc(max * sizeof(xsltTemplatePtr));\r
-    if (templates == NULL)\r
-        return NULL;\r
-\r
-    /*\r
-     * collect all the templates in an array\r
-     */\r
-    style = ctxt->style;\r
-    while (style != NULL) {\r
-        templ = style->templates;\r
-        while (templ != NULL) {\r
-            if (nb >= max)\r
-                break;\r
-\r
-            if (templ->nbCalls > 0)\r
-                templates[nb++] = templ;\r
-            templ = templ->next;\r
-        }\r
-\r
-        style = (xsltStylesheetPtr) xsltNextImport(style);\r
-    }\r
-\r
-    /*\r
-     * Sort the array by time spent\r
-     */\r
-    for (i = 0; i < nb - 1; i++) {\r
-        for (j = i + 1; j < nb; j++) {\r
-            if ((templates[i]->time <= templates[j]->time) ||\r
-                ((templates[i]->time == templates[j]->time) &&\r
-                 (templates[i]->nbCalls <= templates[j]->nbCalls))) {\r
-                templ = templates[j];\r
-                templates[j] = templates[i];\r
-                templates[i] = templ;\r
-            }\r
-        }\r
-    }\r
-\r
-    /*\r
-     * Generate a document corresponding to the results.\r
-     */\r
-    ret = xmlNewDoc(BAD_CAST "1.0");\r
-    root = xmlNewDocNode(ret, NULL, BAD_CAST "profile", NULL);\r
-    xmlDocSetRootElement(ret, root);\r
-\r
-    for (i = 0; i < nb; i++) {\r
-        child = xmlNewChild(root, NULL, BAD_CAST "template", NULL);\r
-        sprintf(buf, "%d", i + 1);\r
-        xmlSetProp(child, BAD_CAST "rank", BAD_CAST buf);\r
-        xmlSetProp(child, BAD_CAST "match", BAD_CAST templates[i]->match);\r
-        xmlSetProp(child, BAD_CAST "name", BAD_CAST templates[i]->name);\r
-        xmlSetProp(child, BAD_CAST "mode", BAD_CAST templates[i]->mode);\r
-\r
-        sprintf(buf, "%d", templates[i]->nbCalls);\r
-        xmlSetProp(child, BAD_CAST "calls", BAD_CAST buf);\r
-\r
-        sprintf(buf, "%ld", templates[i]->time);\r
-        xmlSetProp(child, BAD_CAST "time", BAD_CAST buf);\r
-\r
-        sprintf(buf, "%ld", templates[i]->time / templates[i]->nbCalls);\r
-        xmlSetProp(child, BAD_CAST "average", BAD_CAST buf);\r
-    };\r
-\r
-    xmlFree(templates);\r
-\r
-    return ret;\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Hooks for libxml2 XPath                                 *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/**\r
- * xsltXPathCompile:\r
- * @style: the stylesheet\r
- * @str:  the XPath expression\r
- *\r
- * Compile an XPath expression\r
- *\r
- * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.\r
- *         the caller has to free the object.\r
- */\r
-xmlXPathCompExprPtr\r
-xsltXPathCompile(xsltStylesheetPtr style, const xmlChar *str) {\r
-    xmlXPathContextPtr xpathCtxt;\r
-    xmlXPathCompExprPtr ret;\r
-\r
-    if (style != NULL) {\r
-#ifdef XSLT_REFACTORED_XPATHCOMP\r
-       if (XSLT_CCTXT(style)) {\r
-           /*\r
-           * Proposed by Jerome Pesenti\r
-           * --------------------------\r
-           * For better efficiency we'll reuse the compilation\r
-           * context's XPath context. For the common stylesheet using\r
-           * XPath expressions this will reduce compilation time to\r
-           * about 50%.\r
-           *\r
-           * See http://mail.gnome.org/archives/xslt/2006-April/msg00037.html\r
-           */\r
-           xpathCtxt = XSLT_CCTXT(style)->xpathCtxt;\r
-           xpathCtxt->doc = style->doc;\r
-       } else\r
-           xpathCtxt = xmlXPathNewContext(style->doc); \r
-#else\r
-       xpathCtxt = xmlXPathNewContext(style->doc);\r
-#endif\r
-       xpathCtxt->dict = style->dict;\r
-    } else {\r
-       xpathCtxt = xmlXPathNewContext(NULL);\r
-    }\r
-    /*\r
-    * Compile the expression.\r
-    */\r
-    ret = xmlXPathCtxtCompile(xpathCtxt, str);\r
-\r
-#ifdef XSLT_REFACTORED_XPATHCOMP\r
-    if ((style == NULL) || (! XSLT_CCTXT(style))) {\r
-       xmlXPathFreeContext(xpathCtxt);\r
-    }\r
-#else\r
-    xmlXPathFreeContext(xpathCtxt);\r
-#endif\r
-    /*\r
-     * TODO: there is a lot of optimizations which should be possible\r
-     *       like variable slot precomputations, function precomputations, etc.\r
-     */\r
-\r
-    return(ret);\r
-}\r
-\r
-/************************************************************************\r
- *                                                                     *\r
- *             Hooks for the debugger                                  *\r
- *                                                                     *\r
- ************************************************************************/\r
-\r
-/*\r
- * There is currently only 3 debugging callback defined\r
- * Debugger callbacks are disabled by default\r
- */\r
-#define XSLT_CALLBACK_NUMBER 3\r
-\r
-typedef struct _xsltDebuggerCallbacks xsltDebuggerCallbacks;\r
-typedef xsltDebuggerCallbacks *xsltDebuggerCallbacksPtr;\r
-struct _xsltDebuggerCallbacks {\r
-    xsltHandleDebuggerCallback handler;\r
-    xsltAddCallCallback add;\r
-    xsltDropCallCallback drop;\r
-};\r
-\r
-static xsltDebuggerCallbacks xsltDebuggerCurrentCallbacks = {\r
-    NULL, /* handler */\r
-    NULL, /* add */\r
-    NULL  /* drop */\r
-};\r
-\r
-int xslDebugStatus;\r
-\r
-/**\r
- * xsltSetDebuggerStatus:\r
- * @value : the value to be set\r
- * \r
- * This function sets the value of xslDebugStatus.\r
- */\r
-void\r
-xsltSetDebuggerStatus(int value)\r
-{\r
-    xslDebugStatus = value;    \r
-}\r
-\r
-/**\r
- * xsltGetDebuggerStatus: \r
- * \r
- * Get xslDebugStatus.\r
- *\r
- * Returns the value of xslDebugStatus.\r
- */\r
-int\r
-xsltGetDebuggerStatus(void)\r
-{\r
-    return(xslDebugStatus);    \r
-}\r
-\r
-/**\r
- * xsltSetDebuggerCallbacks:\r
- * @no : number of callbacks\r
- * @block : the block of callbacks\r
- * \r
- * This function allow to plug a debugger into the XSLT library\r
- * @block points to a block of memory containing the address of @no \r
- * callback routines.\r
- *\r
- * Returns 0 in case of success and -1 in case of error\r
- */\r
-int\r
-xsltSetDebuggerCallbacks(int no, void *block)\r
-{\r
-    xsltDebuggerCallbacksPtr callbacks;\r
-\r
-    if ((block == NULL) || (no != XSLT_CALLBACK_NUMBER))\r
-       return(-1);\r
-\r
-    callbacks = (xsltDebuggerCallbacksPtr) block;\r
-    xsltDebuggerCurrentCallbacks.handler = callbacks->handler;\r
-    xsltDebuggerCurrentCallbacks.add  = callbacks->add;\r
-    xsltDebuggerCurrentCallbacks.drop  = callbacks->drop;\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xslHandleDebugger:\r
- * @cur : source node being executed\r
- * @node : data node being processed\r
- * @templ : temlate that applies to node\r
- * @ctxt : the xslt transform context \r
- * \r
- * If either cur or node are a breakpoint, or xslDebugStatus in state \r
- *   where debugging must occcur at this time then transfer control\r
- *   to the xslDebugBreak function\r
- */\r
-void\r
-xslHandleDebugger(xmlNodePtr cur, xmlNodePtr node, xsltTemplatePtr templ,\r
-                 xsltTransformContextPtr ctxt)\r
-{\r
-    if (xsltDebuggerCurrentCallbacks.handler != NULL)\r
-       xsltDebuggerCurrentCallbacks.handler(cur, node, templ, ctxt);\r
-}\r
-\r
-/**\r
- * xslAddCall:\r
- * @templ : current template being applied\r
- * @source : the source node being processed\r
- *\r
- * Add template "call" to call stack\r
- * Returns : 1 on sucess 0 otherwise an error may be printed if \r
- *            WITH_XSLT_DEBUG_BREAKPOINTS is defined\r
- */\r
-int\r
-xslAddCall(xsltTemplatePtr templ, xmlNodePtr source)\r
-{\r
-    if (xsltDebuggerCurrentCallbacks.add != NULL)\r
-       return(xsltDebuggerCurrentCallbacks.add(templ, source));\r
-    return(0);\r
-}\r
-\r
-/**\r
- * xslDropCall:\r
- *\r
- * Drop the topmost item off the call stack\r
- */\r
-void\r
-xslDropCall(void)\r
-{\r
-    if (xsltDebuggerCurrentCallbacks.drop != NULL)\r
-       xsltDebuggerCurrentCallbacks.drop();\r
-}\r
-\r
+/*
+ * xsltutils.c: Utilities for the XSL Transformation 1.0 engine
+ *
+ * Reference:
+ *   http://www.w3.org/TR/1999/REC-xslt-19991116
+ *
+ * See Copyright for the status of this software.
+ *
+ * daniel@veillard.com
+ */
+
+#define IN_LIBXSLT
+#include "libxslt.h"
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <stdarg.h>
+
+#include <libxml/xmlmemory.h>
+#include <libxml/tree.h>
+#include <libxml/HTMLtree.h>
+#include <libxml/xmlerror.h>
+#include <libxml/xmlIO.h>
+#include "xsltutils.h"
+#include "templates.h"
+#include "xsltInternals.h"
+#include "imports.h"
+#include "transform.h"
+
+/* gettimeofday on Windows ??? */
+#if defined(WIN32) && !defined(__CYGWIN__)
+#ifdef _MSC_VER
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+#define gettimeofday(p1,p2)
+#define HAVE_GETTIMEOFDAY
+#define XSLT_WIN32_PERFORMANCE_COUNTER
+#endif /* _MS_VER */
+#endif /* WIN32 */
+
+#ifdef XSLT_NEED_TRIO
+#include "trio.h"
+#define vsnprintf trio_vsnprintf
+#endif
+
+/************************************************************************
+ *                                                                     *
+ *                     Convenience function                            *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltGetCNsProp:
+ * @style: the stylesheet
+ * @node:  the node
+ * @name:  the attribute name
+ * @nameSpace:  the URI of the namespace
+ *
+ * Similar to xmlGetNsProp() but with a slightly different semantic
+ *
+ * Search and get the value of an attribute associated to a node
+ * This attribute has to be anchored in the namespace specified,
+ * or has no namespace and the element is in that namespace.
+ *
+ * This does the entity substitution.
+ * This function looks in DTD attribute declaration for #FIXED or
+ * default declaration values unless DTD use has been turned off.
+ *
+ * Returns the attribute value or NULL if not found. The string is allocated
+ *         in the stylesheet dictionnary.
+ */
+const xmlChar *
+xsltGetCNsProp(xsltStylesheetPtr style, xmlNodePtr node,
+              const xmlChar *name, const xmlChar *nameSpace) {
+    xmlAttrPtr prop;
+    xmlDocPtr doc;
+    xmlNsPtr ns;
+    xmlChar *tmp;
+    const xmlChar *ret;
+
+    if ((node == NULL) || (style == NULL) || (style->dict == NULL))
+       return(NULL);
+
+    prop = node->properties;
+    if (nameSpace == NULL) {
+        return xmlGetProp(node, name);
+    }
+    while (prop != NULL) {
+       /*
+        * One need to have
+        *   - same attribute names
+        *   - and the attribute carrying that namespace
+        */
+        if ((xmlStrEqual(prop->name, name)) &&
+           (((prop->ns == NULL) && (node->ns != NULL) &&
+             (xmlStrEqual(node->ns->href, nameSpace))) ||
+            ((prop->ns != NULL) &&
+             (xmlStrEqual(prop->ns->href, nameSpace))))) {
+
+           tmp = xmlNodeListGetString(node->doc, prop->children, 1);
+           if (tmp == NULL)
+               ret = xmlDictLookup(style->dict, BAD_CAST "", 0);
+           else {
+               ret = xmlDictLookup(style->dict, tmp, -1);
+               xmlFree(tmp);
+           }
+           return ret;
+        }
+       prop = prop->next;
+    }
+    tmp = NULL;
+    /*
+     * Check if there is a default declaration in the internal
+     * or external subsets
+     */
+    doc =  node->doc;
+    if (doc != NULL) {
+        if (doc->intSubset != NULL) {
+           xmlAttributePtr attrDecl;
+
+           attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
+           if ((attrDecl == NULL) && (doc->extSubset != NULL))
+               attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
+               
+           if ((attrDecl != NULL) && (attrDecl->prefix != NULL)) {
+               /*
+                * The DTD declaration only allows a prefix search
+                */
+               ns = xmlSearchNs(doc, node, attrDecl->prefix);
+               if ((ns != NULL) && (xmlStrEqual(ns->href, nameSpace)))
+                   return(xmlDictLookup(style->dict,
+                                        attrDecl->defaultValue, -1));
+           }
+       }
+    }
+    return(NULL);
+}
+/**
+ * xsltGetNsProp:
+ * @node:  the node
+ * @name:  the attribute name
+ * @nameSpace:  the URI of the namespace
+ *
+ * Similar to xmlGetNsProp() but with a slightly different semantic
+ *
+ * Search and get the value of an attribute associated to a node
+ * This attribute has to be anchored in the namespace specified,
+ * or has no namespace and the element is in that namespace.
+ *
+ * This does the entity substitution.
+ * This function looks in DTD attribute declaration for #FIXED or
+ * default declaration values unless DTD use has been turned off.
+ *
+ * Returns the attribute value or NULL if not found.
+ *     It's up to the caller to free the memory.
+ */
+xmlChar *
+xsltGetNsProp(xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace) {
+    xmlAttrPtr prop;
+    xmlDocPtr doc;
+    xmlNsPtr ns;
+
+    if (node == NULL)
+       return(NULL);
+
+    prop = node->properties;
+    /*
+    * TODO: Substitute xmlGetProp() for xmlGetNsProp(), since the former
+    * is not namespace-aware and will return an attribute with equal
+    * name regardless of its namespace.
+    * Example:
+    *   <xsl:element foo:name="myName"/>
+    *   So this would return "myName" even if an attribute @name
+    *   in the XSLT was requested.
+    */
+    if (nameSpace == NULL)
+       return(xmlGetProp(node, name));
+    while (prop != NULL) {
+       /*
+        * One need to have
+        *   - same attribute names
+        *   - and the attribute carrying that namespace
+        */
+        if ((xmlStrEqual(prop->name, name)) &&
+           (((prop->ns == NULL) && (node->ns != NULL) &&
+             (xmlStrEqual(node->ns->href, nameSpace))) ||
+            ((prop->ns != NULL) &&
+             (xmlStrEqual(prop->ns->href, nameSpace))))) {
+           xmlChar *ret;
+
+           ret = xmlNodeListGetString(node->doc, prop->children, 1);
+           if (ret == NULL) return(xmlStrdup((xmlChar *)""));
+           return(ret);
+        }
+       prop = prop->next;
+    }
+
+    /*
+     * Check if there is a default declaration in the internal
+     * or external subsets
+     */
+    doc =  node->doc;
+    if (doc != NULL) {
+        if (doc->intSubset != NULL) {
+           xmlAttributePtr attrDecl;
+
+           attrDecl = xmlGetDtdAttrDesc(doc->intSubset, node->name, name);
+           if ((attrDecl == NULL) && (doc->extSubset != NULL))
+               attrDecl = xmlGetDtdAttrDesc(doc->extSubset, node->name, name);
+               
+           if ((attrDecl != NULL) && (attrDecl->prefix != NULL)) {
+               /*
+                * The DTD declaration only allows a prefix search
+                */
+               ns = xmlSearchNs(doc, node, attrDecl->prefix);
+               if ((ns != NULL) && (xmlStrEqual(ns->href, nameSpace)))
+                   return(xmlStrdup(attrDecl->defaultValue));
+           }
+       }
+    }
+    return(NULL);
+}
+
+/**
+ * xsltGetUTF8Char:
+ * @utf:  a sequence of UTF-8 encoded bytes
+ * @len:  a pointer to @bytes len
+ *
+ * Read one UTF8 Char from @utf
+ * Function copied from libxml2 xmlGetUTF8Char() ... to discard ultimately
+ * and use the original API
+ *
+ * Returns the char value or -1 in case of error and update @len with the
+ *        number of bytes used
+ */
+int
+xsltGetUTF8Char(const unsigned char *utf, int *len) {
+    unsigned int c;
+
+    if (utf == NULL)
+       goto error;
+    if (len == NULL)
+       goto error;
+    if (*len < 1)
+       goto error;
+
+    c = utf[0];
+    if (c & 0x80) {
+       if (*len < 2)
+           goto error;
+       if ((utf[1] & 0xc0) != 0x80)
+           goto error;
+       if ((c & 0xe0) == 0xe0) {
+           if (*len < 3)
+               goto error;
+           if ((utf[2] & 0xc0) != 0x80)
+               goto error;
+           if ((c & 0xf0) == 0xf0) {
+               if (*len < 4)
+                   goto error;
+               if ((c & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
+                   goto error;
+               *len = 4;
+               /* 4-byte code */
+               c = (utf[0] & 0x7) << 18;
+               c |= (utf[1] & 0x3f) << 12;
+               c |= (utf[2] & 0x3f) << 6;
+               c |= utf[3] & 0x3f;
+           } else {
+             /* 3-byte code */
+               *len = 3;
+               c = (utf[0] & 0xf) << 12;
+               c |= (utf[1] & 0x3f) << 6;
+               c |= utf[2] & 0x3f;
+           }
+       } else {
+         /* 2-byte code */
+           *len = 2;
+           c = (utf[0] & 0x1f) << 6;
+           c |= utf[1] & 0x3f;
+       }
+    } else {
+       /* 1-byte code */
+       *len = 1;
+    }
+    return(c);
+
+error:
+    if (len != NULL)
+       *len = 0;
+    return(-1);
+}
+
+#ifdef XSLT_REFACTORED
+
+/**
+ * xsltPointerListAddSize:
+ * @list: the pointer list structure
+ * @item: the item to be stored
+ * @initialSize: the initial size of the list
+ *
+ * Adds an item to the list.
+ *
+ * Returns the position of the added item in the list or
+ *         -1 in case of an error.
+ */
+int
+xsltPointerListAddSize(xsltPointerListPtr list,                       
+                      void *item,
+                      int initialSize)
+{
+    if (list->items == NULL) {
+       if (initialSize <= 0)
+           initialSize = 1;
+       list->items = (void **) xmlMalloc(
+           initialSize * sizeof(void *));
+       if (list->items == NULL) {
+           xsltGenericError(xsltGenericErrorContext,
+            "xsltPointerListAddSize: memory allocation failure.\n");
+           return(-1);
+       }
+       list->number = 0;
+       list->size = initialSize;
+    } else if (list->size <= list->number) {
+       list->size *= 2;
+       list->items = (void **) xmlRealloc(list->items,
+           list->size * sizeof(void *));
+       if (list->items == NULL) {
+           xsltGenericError(xsltGenericErrorContext,
+            "xsltPointerListAddSize: memory re-allocation failure.\n");
+           list->size = 0;
+           return(-1);
+       }
+    }
+    list->items[list->number++] = item;
+    return(0);
+}
+
+/**
+ * xsltPointerListCreate:
+ *
+ * Creates an xsltPointerList structure.
+ *
+ * Returns a xsltPointerList structure or NULL in case of an error.
+ */
+xsltPointerListPtr
+xsltPointerListCreate(int initialSize)
+{
+    xsltPointerListPtr ret;
+
+    ret = xmlMalloc(sizeof(xsltPointerList));
+    if (ret == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+            "xsltPointerListCreate: memory allocation failure.\n");
+       return (NULL);
+    }
+    memset(ret, 0, sizeof(xsltPointerList));
+    if (initialSize > 0) {
+       xsltPointerListAddSize(ret, NULL, initialSize);
+       ret->number = 0;
+    }
+    return (ret);
+}
+
+/**
+ * xsltPointerListFree:
+ *
+ * Frees the xsltPointerList structure. This does not free
+ * the content of the list.
+ */
+void
+xsltPointerListFree(xsltPointerListPtr list)
+{
+    if (list == NULL)
+       return;
+    if (list->items != NULL)
+       xmlFree(list->items);
+    xmlFree(list);
+}
+
+/**
+ * xsltPointerListFree:
+ *
+ * Resets the list, but does not free the allocated array
+ * and does not free the content of the list.
+ */
+void
+xsltPointerListClear(xsltPointerListPtr list)
+{
+    if (list->items != NULL) {
+       xmlFree(list->items);
+       list->items = NULL;
+    }
+    list->number = 0;
+    list->size = 0;
+}
+
+#endif /* XSLT_REFACTORED */
+
+/************************************************************************
+ *                                                                     *
+ *             Handling of XSLT stylesheets messages                   *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltMessage:
+ * @ctxt:  an XSLT processing context
+ * @node:  The current node
+ * @inst:  The node containing the message instruction
+ *
+ * Process and xsl:message construct
+ */
+void
+xsltMessage(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst) {
+    xmlChar *prop, *message;
+    int terminate = 0;
+
+    if ((ctxt == NULL) || (inst == NULL))
+       return;
+
+    prop = xmlGetNsProp(inst, (const xmlChar *)"terminate", NULL);
+    if (prop != NULL) {
+       if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
+           terminate = 1;
+       } else if (xmlStrEqual(prop, (const xmlChar *)"no")) {
+           terminate = 0;
+       } else {
+           xsltGenericError(xsltGenericErrorContext,
+               "xsl:message : terminate expecting 'yes' or 'no'\n");
+           ctxt->state = XSLT_STATE_ERROR;
+       }
+       xmlFree(prop);
+    }
+    message = xsltEvalTemplateString(ctxt, node, inst);
+    if (message != NULL) {
+       int len = xmlStrlen(message);
+
+       xsltGenericError(xsltGenericErrorContext, "%s",
+                        (const char *)message);
+       if ((len > 0) && (message[len - 1] != '\n'))
+           xsltGenericError(xsltGenericErrorContext, "\n");
+       xmlFree(message);
+    }
+    if (terminate)
+       ctxt->state = XSLT_STATE_STOPPED;
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Handling of out of context errors                       *
+ *                                                                     *
+ ************************************************************************/
+
+#define XSLT_GET_VAR_STR(msg, str) {                           \
+    int       size;                                            \
+    int       chars;                                           \
+    char      *larger;                                         \
+    va_list   ap;                                              \
+                                                               \
+    str = (char *) xmlMalloc(150);                             \
+    if (str == NULL)                                           \
+       return;                                                 \
+                                                               \
+    size = 150;                                                        \
+                                                               \
+    while (1) {                                                        \
+       va_start(ap, msg);                                      \
+       chars = vsnprintf(str, size, msg, ap);                  \
+       va_end(ap);                                             \
+       if ((chars > -1) && (chars < size))                     \
+           break;                                              \
+       if (chars > -1)                                         \
+           size += chars + 1;                                  \
+       else                                                    \
+           size += 100;                                        \
+       if ((larger = (char *) xmlRealloc(str, size)) == NULL) {\
+           xmlFree(str);                                       \
+           return;                                             \
+       }                                                       \
+       str = larger;                                           \
+    }                                                          \
+}
+/**
+ * xsltGenericErrorDefaultFunc:
+ * @ctx:  an error context
+ * @msg:  the message to display/transmit
+ * @...:  extra parameters for the message display
+ * 
+ * Default handler for out of context error messages.
+ */
+static void
+xsltGenericErrorDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
+    va_list args;
+
+    if (xsltGenericErrorContext == NULL)
+       xsltGenericErrorContext = (void *) stderr;
+
+    va_start(args, msg);
+    vfprintf((FILE *)xsltGenericErrorContext, msg, args);
+    va_end(args);
+}
+
+xmlGenericErrorFunc xsltGenericError = xsltGenericErrorDefaultFunc;
+void *xsltGenericErrorContext = NULL;
+
+
+/**
+ * xsltSetGenericErrorFunc:
+ * @ctx:  the new error handling context
+ * @handler:  the new handler function
+ *
+ * Function to reset the handler and the error context for out of
+ * context error messages.
+ * This simply means that @handler will be called for subsequent
+ * error messages while not parsing nor validating. And @ctx will
+ * be passed as first argument to @handler
+ * One can simply force messages to be emitted to another FILE * than
+ * stderr by setting @ctx to this file handle and @handler to NULL.
+ */
+void
+xsltSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler) {
+    xsltGenericErrorContext = ctx;
+    if (handler != NULL)
+       xsltGenericError = handler;
+    else
+       xsltGenericError = xsltGenericErrorDefaultFunc;
+}
+
+/**
+ * xsltGenericDebugDefaultFunc:
+ * @ctx:  an error context
+ * @msg:  the message to display/transmit
+ * @...:  extra parameters for the message display
+ * 
+ * Default handler for out of context error messages.
+ */
+static void
+xsltGenericDebugDefaultFunc(void *ctx ATTRIBUTE_UNUSED, const char *msg, ...) {
+    va_list args;
+
+    if (xsltGenericDebugContext == NULL)
+       return;
+
+    va_start(args, msg);
+    vfprintf((FILE *)xsltGenericDebugContext, msg, args);
+    va_end(args);
+}
+
+xmlGenericErrorFunc xsltGenericDebug = xsltGenericDebugDefaultFunc;
+void *xsltGenericDebugContext = NULL;
+
+
+/**
+ * xsltSetGenericDebugFunc:
+ * @ctx:  the new error handling context
+ * @handler:  the new handler function
+ *
+ * Function to reset the handler and the error context for out of
+ * context error messages.
+ * This simply means that @handler will be called for subsequent
+ * error messages while not parsing or validating. And @ctx will
+ * be passed as first argument to @handler
+ * One can simply force messages to be emitted to another FILE * than
+ * stderr by setting @ctx to this file handle and @handler to NULL.
+ */
+void
+xsltSetGenericDebugFunc(void *ctx, xmlGenericErrorFunc handler) {
+    xsltGenericDebugContext = ctx;
+    if (handler != NULL)
+       xsltGenericDebug = handler;
+    else
+       xsltGenericDebug = xsltGenericDebugDefaultFunc;
+}
+
+/**
+ * xsltPrintErrorContext:
+ * @ctxt:  the transformation context
+ * @style:  the stylesheet
+ * @node:  the current node being processed
+ *
+ * Display the context of an error.
+ */
+void
+xsltPrintErrorContext(xsltTransformContextPtr ctxt,
+                     xsltStylesheetPtr style, xmlNodePtr node) {
+    int line = 0;
+    const xmlChar *file = NULL;
+    const xmlChar *name = NULL;
+    const char *type = "error";
+    xmlGenericErrorFunc error = xsltGenericError;
+    void *errctx = xsltGenericErrorContext;
+
+    if (ctxt != NULL) {
+       ctxt->state = XSLT_STATE_ERROR;
+       if (ctxt->error != NULL) {
+           error = ctxt->error;
+           errctx = ctxt->errctx;
+       }
+    }
+    if ((node == NULL) && (ctxt != NULL))
+       node = ctxt->inst;
+
+    if (node != NULL)  {
+       if ((node->type == XML_DOCUMENT_NODE) ||
+           (node->type == XML_HTML_DOCUMENT_NODE)) {
+           xmlDocPtr doc = (xmlDocPtr) node;
+
+           file = doc->URL;
+       } else {
+           line = xmlGetLineNo(node);
+           if ((node->doc != NULL) && (node->doc->URL != NULL))
+               file = node->doc->URL;
+           if (node->name != NULL)
+               name = node->name;
+       }
+    } 
+    
+    if (ctxt != NULL)
+       type = "runtime error";
+    else if (style != NULL) {
+#ifdef XSLT_REFACTORED
+       if (XSLT_CCTXT(style)->errSeverity == XSLT_ERROR_SEVERITY_WARNING)
+           type = "compilation warning";
+       else
+           type = "compilation error";
+#else
+       type = "compilation error";
+#endif
+    }
+
+    if ((file != NULL) && (line != 0) && (name != NULL))
+       error(errctx, "%s: file %s line %d element %s\n",
+             type, file, line, name);
+    else if ((file != NULL) && (name != NULL))
+       error(errctx, "%s: file %s element %s\n", type, file, name);
+    else if ((file != NULL) && (line != 0))
+       error(errctx, "%s: file %s line %d\n", type, file, line);
+    else if (file != NULL)
+       error(errctx, "%s: file %s\n", type, file);
+    else if (name != NULL)
+       error(errctx, "%s: element %s\n", type, name);
+    else
+       error(errctx, "%s\n", type);
+}
+
+/**
+ * xsltSetTransformErrorFunc:
+ * @ctxt:  the XSLT transformation context
+ * @ctx:  the new error handling context
+ * @handler:  the new handler function
+ *
+ * Function to reset the handler and the error context for out of
+ * context error messages specific to a given XSLT transromation.
+ *
+ * This simply means that @handler will be called for subsequent
+ * error messages while running the transformation.
+ */
+void
+xsltSetTransformErrorFunc(xsltTransformContextPtr ctxt,
+                          void *ctx, xmlGenericErrorFunc handler)
+{
+    ctxt->error = handler;
+    ctxt->errctx = ctx;
+}
+
+/**
+ * xsltTransformError:
+ * @ctxt:  an XSLT transformation context
+ * @style:  the XSLT stylesheet used
+ * @node:  the current node in the stylesheet
+ * @msg:  the message to display/transmit
+ * @...:  extra parameters for the message display
+ *
+ * Display and format an error messages, gives file, line, position and
+ * extra parameters, will use the specific transformation context if available
+ */
+void
+xsltTransformError(xsltTransformContextPtr ctxt,
+                  xsltStylesheetPtr style,
+                  xmlNodePtr node,
+                  const char *msg, ...) {
+    xmlGenericErrorFunc error = xsltGenericError;
+    void *errctx = xsltGenericErrorContext;
+    char * str;
+
+    if (ctxt != NULL) {
+       ctxt->state = XSLT_STATE_ERROR;
+       if (ctxt->error != NULL) {
+           error = ctxt->error;
+           errctx = ctxt->errctx;
+       }
+    }
+    if ((node == NULL) && (ctxt != NULL))
+       node = ctxt->inst;
+    xsltPrintErrorContext(ctxt, style, node);
+    XSLT_GET_VAR_STR(msg, str);
+    error(errctx, "%s", str);
+    if (str != NULL)
+       xmlFree(str);
+}
+
+/************************************************************************
+ *                                                                     *
+ *                             QNames                                  *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltSplitQName:
+ * @dict: a dictionnary
+ * @name:  the full QName
+ * @prefix: the return value
+ *
+ * Split QNames into prefix and local names, both allocated from a dictionnary.
+ *
+ * Returns: the localname or NULL in case of error.
+ */
+const xmlChar *
+xsltSplitQName(xmlDictPtr dict, const xmlChar *name, const xmlChar **prefix) {
+    int len = 0;
+    const xmlChar *ret = NULL;
+
+    *prefix = NULL;
+    if ((name == NULL) || (dict == NULL)) return(NULL);
+    if (name[0] == ':')
+        return(xmlDictLookup(dict, name, -1));
+    while ((name[len] != 0) && (name[len] != ':')) len++;
+    if (name[len] == 0) return(xmlDictLookup(dict, name, -1));
+    *prefix = xmlDictLookup(dict, name, len);
+    ret = xmlDictLookup(dict, &name[len + 1], -1);
+    return(ret);
+}
+
+/**
+ * xsltGetQNameURI:
+ * @node:  the node holding the QName
+ * @name:  pointer to the initial QName value
+ *
+ * This function analyzes @name, if the name contains a prefix,
+ * the function seaches the associated namespace in scope for it.
+ * It will also replace @name value with the NCName, the old value being
+ * freed.
+ * Errors in the prefix lookup are signalled by setting @name to NULL.
+ *
+ * NOTE: the namespace returned is a pointer to the place where it is
+ *       defined and hence has the same lifespan as the document holding it.
+ *
+ * Returns the namespace URI if there is a prefix, or NULL if @name is
+ *         not prefixed.
+ */
+const xmlChar *
+xsltGetQNameURI(xmlNodePtr node, xmlChar ** name)
+{
+    int len = 0;
+    xmlChar *qname;
+    xmlNsPtr ns;
+
+    if (name == NULL)
+       return(NULL);
+    qname = *name;
+    if ((qname == NULL) || (*qname == 0))
+       return(NULL);
+    if (node == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+                        "QName: no element for namespace lookup %s\n",
+                        qname);
+       xmlFree(qname);
+       *name = NULL;
+       return(NULL);
+    }
+
+    /* nasty but valid */
+    if (qname[0] == ':')
+       return(NULL);
+
+    /*
+     * we are not trying to validate but just to cut, and yes it will
+     * work even if this is a set of UTF-8 encoded chars
+     */
+    while ((qname[len] != 0) && (qname[len] != ':')) 
+       len++;
+    
+    if (qname[len] == 0)
+       return(NULL);
+
+    /*
+     * handle xml: separately, this one is magical
+     */
+    if ((qname[0] == 'x') && (qname[1] == 'm') &&
+        (qname[2] == 'l') && (qname[3] == ':')) {
+       if (qname[4] == 0)
+           return(NULL);
+        *name = xmlStrdup(&qname[4]);
+       xmlFree(qname);
+       return(XML_XML_NAMESPACE);
+    }
+
+    qname[len] = 0;
+    ns = xmlSearchNs(node->doc, node, qname);
+    if (ns == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+               "%s:%s : no namespace bound to prefix %s\n",
+                        qname, &qname[len + 1], qname);
+       *name = NULL;
+       xmlFree(qname);
+       return(NULL);
+    }
+    *name = xmlStrdup(&qname[len + 1]);
+    xmlFree(qname);
+    return(ns->href);
+}
+
+/**
+ * xsltGetQNameURI2:
+ * @style:  stylesheet pointer
+ * @node:   the node holding the QName
+ * @name:   pointer to the initial QName value
+ *
+ * This function is similar to xsltGetQNameURI, but is used when
+ * @name is a dictionary entry.
+ *
+ * Returns the namespace URI if there is a prefix, or NULL if @name is
+ * not prefixed.
+ */
+const xmlChar *
+xsltGetQNameURI2(xsltStylesheetPtr style, xmlNodePtr node,
+                const xmlChar **name) {
+    int len = 0;
+    xmlChar *qname;
+    xmlNsPtr ns;
+
+    if (name == NULL)
+        return(NULL);
+    qname = (xmlChar *)*name;
+    if ((qname == NULL) || (*qname == 0))
+        return(NULL);
+    if (node == NULL) {
+        xsltGenericError(xsltGenericErrorContext,
+                         "QName: no element for namespace lookup %s\n",
+                          qname);
+       *name = NULL;
+       return(NULL);
+    }
+
+    /*
+     * we are not trying to validate but just to cut, and yes it will
+     * work even if this is a set of UTF-8 encoded chars
+     */
+    while ((qname[len] != 0) && (qname[len] != ':'))
+        len++;
+
+    if (qname[len] == 0)
+        return(NULL);
+
+    /*
+     * handle xml: separately, this one is magical
+     */
+    if ((qname[0] == 'x') && (qname[1] == 'm') &&
+        (qname[2] == 'l') && (qname[3] == ':')) {
+        if (qname[4] == 0)
+            return(NULL);
+        *name = xmlDictLookup(style->dict, &qname[4], -1);
+        return(XML_XML_NAMESPACE);
+    }
+
+    qname = xmlStrndup(*name, len);
+    ns = xmlSearchNs(node->doc, node, qname);
+    if (ns == NULL) {
+       if (style) {
+           xsltTransformError(NULL, style, node,
+               "No namespace bound to prefix '%s'.\n",
+               qname);
+           style->errors++;
+       } else {
+           xsltGenericError(xsltGenericErrorContext,
+                "%s : no namespace bound to prefix %s\n",
+               *name, qname);
+       }
+        *name = NULL;
+        xmlFree(qname);
+        return(NULL);
+    }
+    *name = xmlDictLookup(style->dict, (*name)+len+1, -1);
+    xmlFree(qname);
+    return(ns->href);
+}
+                                                                                     
+/************************************************************************
+ *                                                                     *
+ *                             Sorting                                 *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltDocumentSortFunction:
+ * @list:  the node set
+ *
+ * reorder the current node list @list accordingly to the document order
+ * This function is slow, obsolete and should not be used anymore.
+ */
+void
+xsltDocumentSortFunction(xmlNodeSetPtr list) {
+    int i, j;
+    int len, tst;
+    xmlNodePtr node;
+
+    if (list == NULL)
+       return;
+    len = list->nodeNr;
+    if (len <= 1)
+       return;
+    /* TODO: sort is really not optimized, does it needs to ? */
+    for (i = 0;i < len -1;i++) {
+       for (j = i + 1; j < len; j++) {
+           tst = xmlXPathCmpNodes(list->nodeTab[i], list->nodeTab[j]);
+           if (tst == -1) {
+               node = list->nodeTab[i];
+               list->nodeTab[i] = list->nodeTab[j];
+               list->nodeTab[j] = node;
+           }
+       }
+    }
+}
+
+/**
+ * xsltComputeSortResult:
+ * @ctxt:  a XSLT process context
+ * @sort:  node list
+ *
+ * reorder the current node list accordingly to the set of sorting
+ * requirement provided by the array of nodes.
+ *
+ * Returns a ordered XPath nodeset or NULL in case of error.
+ */
+xmlXPathObjectPtr *
+xsltComputeSortResult(xsltTransformContextPtr ctxt, xmlNodePtr sort) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemSortPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    xmlXPathObjectPtr *results = NULL;
+    xmlNodeSetPtr list = NULL;
+    xmlXPathObjectPtr res;
+    int len = 0;
+    int i;    
+    xmlNodePtr oldNode;
+    xmlNodePtr oldInst;
+    int        oldPos, oldSize ;
+    int oldNsNr;
+    xmlNsPtr *oldNamespaces;
+
+    comp = sort->psvi;
+    if (comp == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+            "xsl:sort : compilation failed\n");
+       return(NULL);
+    }
+
+    if ((comp->select == NULL) || (comp->comp == NULL))
+       return(NULL);
+
+    list = ctxt->nodeList;
+    if ((list == NULL) || (list->nodeNr <= 1))
+       return(NULL);
+
+    len = list->nodeNr;
+
+    /* TODO: xsl:sort lang attribute */
+    /* TODO: xsl:sort case-order attribute */
+
+
+    results = xmlMalloc(len * sizeof(xmlXPathObjectPtr));
+    if (results == NULL) {
+       xsltGenericError(xsltGenericErrorContext,
+            "xsltComputeSortResult: memory allocation failure\n");
+       return(NULL);
+    }
+
+    oldNode = ctxt->node;
+    oldInst = ctxt->inst;
+    oldPos = ctxt->xpathCtxt->proximityPosition;
+    oldSize = ctxt->xpathCtxt->contextSize;
+    oldNsNr = ctxt->xpathCtxt->nsNr;
+    oldNamespaces = ctxt->xpathCtxt->namespaces;
+    for (i = 0;i < len;i++) {
+       ctxt->inst = sort;
+       ctxt->xpathCtxt->contextSize = len;
+       ctxt->xpathCtxt->proximityPosition = i + 1;
+       ctxt->node = list->nodeTab[i];
+       ctxt->xpathCtxt->node = ctxt->node;
+#ifdef XSLT_REFACTORED
+       if (comp->inScopeNs != NULL) {
+           ctxt->xpathCtxt->namespaces = comp->inScopeNs->list;
+           ctxt->xpathCtxt->nsNr = comp->inScopeNs->xpathNumber;
+       } else {
+           ctxt->xpathCtxt->namespaces = NULL;
+           ctxt->xpathCtxt->nsNr = 0;
+       }
+#else
+       ctxt->xpathCtxt->namespaces = comp->nsList;
+       ctxt->xpathCtxt->nsNr = comp->nsNr;
+#endif
+       res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt);
+       if (res != NULL) {
+           if (res->type != XPATH_STRING)
+               res = xmlXPathConvertString(res);
+           if (comp->number)
+               res = xmlXPathConvertNumber(res);
+           res->index = i;     /* Save original pos for dupl resolv */
+           if (comp->number) {
+               if (res->type == XPATH_NUMBER) {
+                   results[i] = res;
+               } else {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   xsltGenericDebug(xsltGenericDebugContext,
+                       "xsltComputeSortResult: select didn't evaluate to a number\n");
+#endif
+                   results[i] = NULL;
+               }
+           } else {
+               if (res->type == XPATH_STRING) {
+                   results[i] = res;
+               } else {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   xsltGenericDebug(xsltGenericDebugContext,
+                       "xsltComputeSortResult: select didn't evaluate to a string\n");
+#endif
+                   results[i] = NULL;
+               }
+           }
+       } else {
+           ctxt->state = XSLT_STATE_STOPPED;
+           results[i] = NULL;
+       }
+    }
+    ctxt->node = oldNode;
+    ctxt->inst = oldInst;
+    ctxt->xpathCtxt->contextSize = oldSize;
+    ctxt->xpathCtxt->proximityPosition = oldPos;
+    ctxt->xpathCtxt->nsNr = oldNsNr;
+    ctxt->xpathCtxt->namespaces = oldNamespaces;
+
+    return(results);
+}
+
+/**
+ * xsltDefaultSortFunction:
+ * @ctxt:  a XSLT process context
+ * @sorts:  array of sort nodes
+ * @nbsorts:  the number of sorts in the array
+ *
+ * reorder the current node list accordingly to the set of sorting
+ * requirement provided by the arry of nodes.
+ */
+void   
+xsltDefaultSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts,
+                  int nbsorts) {
+#ifdef XSLT_REFACTORED
+    xsltStyleItemSortPtr comp;
+#else
+    xsltStylePreCompPtr comp;
+#endif
+    xmlXPathObjectPtr *resultsTab[XSLT_MAX_SORT];
+    xmlXPathObjectPtr *results = NULL, *res;
+    xmlNodeSetPtr list = NULL;
+    int descending, number, desc, numb;
+    int len = 0;
+    int i, j, incr;
+    int tst;
+    int depth;
+    xmlNodePtr node;
+    xmlXPathObjectPtr tmp;    
+    int tempstype[XSLT_MAX_SORT], temporder[XSLT_MAX_SORT];
+
+    if ((ctxt == NULL) || (sorts == NULL) || (nbsorts <= 0) ||
+       (nbsorts >= XSLT_MAX_SORT))
+       return;
+    if (sorts[0] == NULL)
+       return;
+    comp = sorts[0]->psvi;
+    if (comp == NULL)
+       return;
+
+    list = ctxt->nodeList;
+    if ((list == NULL) || (list->nodeNr <= 1))
+       return; /* nothing to do */
+
+    for (j = 0; j < nbsorts; j++) {
+       comp = sorts[j]->psvi;
+       tempstype[j] = 0;
+       if ((comp->stype == NULL) && (comp->has_stype != 0)) {
+           comp->stype =
+               xsltEvalAttrValueTemplate(ctxt, sorts[j],
+                                         (const xmlChar *) "data-type",
+                                         XSLT_NAMESPACE);
+           if (comp->stype != NULL) {
+               tempstype[j] = 1;
+               if (xmlStrEqual(comp->stype, (const xmlChar *) "text"))
+                   comp->number = 0;
+               else if (xmlStrEqual(comp->stype, (const xmlChar *) "number"))
+                   comp->number = 1;
+               else {
+                   xsltTransformError(ctxt, NULL, sorts[j],
+                         "xsltDoSortFunction: no support for data-type = %s\n",
+                                    comp->stype);
+                   comp->number = 0; /* use default */
+               }
+           }
+       }
+       temporder[j] = 0;
+       if ((comp->order == NULL) && (comp->has_order != 0)) {
+           comp->order = xsltEvalAttrValueTemplate(ctxt, sorts[j],
+                                                   (const xmlChar *) "order",
+                                                   XSLT_NAMESPACE);
+           if (comp->order != NULL) {
+               temporder[j] = 1;
+               if (xmlStrEqual(comp->order, (const xmlChar *) "ascending"))
+                   comp->descending = 0;
+               else if (xmlStrEqual(comp->order,
+                                    (const xmlChar *) "descending"))
+                   comp->descending = 1;
+               else {
+                   xsltTransformError(ctxt, NULL, sorts[j],
+                            "xsltDoSortFunction: invalid value %s for order\n",
+                                    comp->order);
+                   comp->descending = 0; /* use default */
+               }
+           }
+       }
+    }
+
+    len = list->nodeNr;
+
+    resultsTab[0] = xsltComputeSortResult(ctxt, sorts[0]);
+    for (i = 1;i < XSLT_MAX_SORT;i++)
+       resultsTab[i] = NULL;
+
+    results = resultsTab[0];
+
+    comp = sorts[0]->psvi;
+    descending = comp->descending;
+    number = comp->number;
+    if (results == NULL)
+       return;
+
+    /* Shell's sort of node-set */
+    for (incr = len / 2; incr > 0; incr /= 2) {
+       for (i = incr; i < len; i++) {
+           j = i - incr;
+           if (results[i] == NULL)
+               continue;
+           
+           while (j >= 0) {
+               if (results[j] == NULL)
+                   tst = 1;
+               else {
+                   if (number) {
+                       /* We make NaN smaller than number in accordance
+                          with XSLT spec */
+                       if (xmlXPathIsNaN(results[j]->floatval)) {
+                           if (xmlXPathIsNaN(results[j + incr]->floatval))
+                               tst = 0;
+                           else
+                               tst = -1;
+                       } else if (xmlXPathIsNaN(results[j + incr]->floatval))
+                           tst = 1;
+                       else if (results[j]->floatval ==
+                               results[j + incr]->floatval)
+                           tst = 0;
+                       else if (results[j]->floatval > 
+                               results[j + incr]->floatval)
+                           tst = 1;
+                       else tst = -1;
+                   } else {
+                       tst = xmlStrcmp(results[j]->stringval,
+                                    results[j + incr]->stringval); 
+                   }
+                   if (descending)
+                       tst = -tst;
+               }
+               if (tst == 0) {
+                   /*
+                    * Okay we need to use multi level sorts
+                    */
+                   depth = 1;
+                   while (depth < nbsorts) {
+                       if (sorts[depth] == NULL)
+                           break;
+                       comp = sorts[depth]->psvi;
+                       if (comp == NULL)
+                           break;
+                       desc = comp->descending;
+                       numb = comp->number;
+
+                       /*
+                        * Compute the result of the next level for the
+                        * full set, this might be optimized ... or not
+                        */
+                       if (resultsTab[depth] == NULL) 
+                           resultsTab[depth] = xsltComputeSortResult(ctxt,
+                                                       sorts[depth]);
+                       res = resultsTab[depth];
+                       if (res == NULL) 
+                           break;
+                       if (res[j] == NULL) {
+                           if (res[j+incr] != NULL)
+                               tst = 1;
+                       } else {
+                           if (numb) {
+                               /* We make NaN smaller than number in
+                                  accordance with XSLT spec */
+                               if (xmlXPathIsNaN(res[j]->floatval)) {
+                                   if (xmlXPathIsNaN(res[j +
+                                               incr]->floatval))
+                                       tst = 0;
+                                   else
+                                       tst = -1;
+                               } else if (xmlXPathIsNaN(res[j + incr]->
+                                               floatval))
+                                   tst = 1;
+                               else if (res[j]->floatval == res[j + incr]->
+                                               floatval)
+                                   tst = 0;
+                               else if (res[j]->floatval > 
+                                       res[j + incr]->floatval)
+                                   tst = 1;
+                               else tst = -1;
+                           } else {
+                               tst = xmlStrcmp(res[j]->stringval,
+                                            res[j + incr]->stringval); 
+                           }
+                           if (desc)
+                               tst = -tst;
+                       }
+
+                       /*
+                        * if we still can't differenciate at this level
+                        * try one level deeper.
+                        */
+                       if (tst != 0)
+                           break;
+                       depth++;
+                   }
+               }
+               if (tst == 0) {
+                   tst = results[j]->index > results[j + incr]->index;
+               }
+               if (tst > 0) {
+                   tmp = results[j];
+                   results[j] = results[j + incr];
+                   results[j + incr] = tmp;
+                   node = list->nodeTab[j];
+                   list->nodeTab[j] = list->nodeTab[j + incr];
+                   list->nodeTab[j + incr] = node;
+                   depth = 1;
+                   while (depth < nbsorts) {
+                       if (sorts[depth] == NULL)
+                           break;
+                       if (resultsTab[depth] == NULL)
+                           break;
+                       res = resultsTab[depth];
+                       tmp = res[j];
+                       res[j] = res[j + incr];
+                       res[j + incr] = tmp;
+                       depth++;
+                   }
+                   j -= incr;
+               } else
+                   break;
+           }
+       }
+    }
+
+    for (j = 0; j < nbsorts; j++) {
+       comp = sorts[j]->psvi;
+       if (tempstype[j] == 1) {
+           /* The data-type needs to be recomputed each time */
+           xmlFree((void *)(comp->stype));
+           comp->stype = NULL;
+       }
+       if (temporder[j] == 1) {
+           /* The order needs to be recomputed each time */
+           xmlFree((void *)(comp->order));
+           comp->order = NULL;
+       }
+       if (resultsTab[j] != NULL) {
+           for (i = 0;i < len;i++)
+               xmlXPathFreeObject(resultsTab[j][i]);
+           xmlFree(resultsTab[j]);
+       }
+    }
+}
+
+
+static xsltSortFunc xsltSortFunction = xsltDefaultSortFunction;
+
+/**
+ * xsltDoSortFunction:
+ * @ctxt:  a XSLT process context
+ * @sorts:  array of sort nodes
+ * @nbsorts:  the number of sorts in the array
+ *
+ * reorder the current node list accordingly to the set of sorting
+ * requirement provided by the arry of nodes.
+ * This is a wrapper function, the actual function used is specified
+ * using xsltSetCtxtSortFunc() to set the context specific sort function,
+ * or xsltSetSortFunc() to set the global sort function.
+ * If a sort function is set on the context, this will get called.
+ * Otherwise the global sort function is called.
+ */
+void
+xsltDoSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr * sorts,
+                   int nbsorts)
+{
+    if (ctxt->sortfunc != NULL)
+       (ctxt->sortfunc)(ctxt, sorts, nbsorts);
+    else if (xsltSortFunction != NULL)
+        xsltSortFunction(ctxt, sorts, nbsorts);
+}
+
+/**
+ * xsltSetSortFunc:
+ * @handler:  the new handler function
+ *
+ * Function to reset the global handler for XSLT sorting.
+ * If the handler is NULL, the default sort function will be used.
+ */
+void
+xsltSetSortFunc(xsltSortFunc handler) {
+    if (handler != NULL)
+       xsltSortFunction = handler;
+    else
+       xsltSortFunction = xsltDefaultSortFunction;
+}
+
+/**
+ * xsltSetCtxtSortFunc:
+ * @ctxt:  a XSLT process context
+ * @handler:  the new handler function
+ *
+ * Function to set the handler for XSLT sorting
+ * for the specified context. 
+ * If the handler is NULL, then the global
+ * sort function will be called
+ */
+void 
+xsltSetCtxtSortFunc(xsltTransformContextPtr ctxt, xsltSortFunc handler) {
+    ctxt->sortfunc = handler;
+}
+
+/************************************************************************
+ *                                                                     *
+ *                             Parsing options                         *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltSetCtxtParseOptions:
+ * @ctxt:  a XSLT process context
+ * @options:  a combination of libxml2 xmlParserOption
+ * 
+ * Change the default parser option passed by the XSLT engine to the 
+ * parser when using document() loading.
+ *
+ * Returns the previous options or -1 in case of error
+ */
+int 
+xsltSetCtxtParseOptions(xsltTransformContextPtr ctxt, int options)
+{
+    int oldopts;
+
+    if (ctxt == NULL)
+        return(-1);
+    oldopts = ctxt->parserOptions;
+    ctxt->parserOptions = options;
+    return(oldopts);
+}
+
+/************************************************************************
+ *                                                                     *
+ *                             Output                                  *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltSaveResultTo:
+ * @buf:  an output buffer
+ * @result:  the result xmlDocPtr
+ * @style:  the stylesheet
+ *
+ * Save the result @result obtained by applying the @style stylesheet
+ * to an I/O output channel @buf
+ *
+ * Returns the number of byte written or -1 in case of failure.
+ */
+int
+xsltSaveResultTo(xmlOutputBufferPtr buf, xmlDocPtr result,
+              xsltStylesheetPtr style) {
+    const xmlChar *encoding;
+    int base;
+    const xmlChar *method;
+    int indent;
+
+    if ((buf == NULL) || (result == NULL) || (style == NULL))
+       return(-1);
+    if ((result->children == NULL) ||
+       ((result->children->type == XML_DTD_NODE) &&
+        (result->children->next == NULL)))
+       return(0);
+
+    if ((style->methodURI != NULL) &&
+       ((style->method == NULL) ||
+        (!xmlStrEqual(style->method, (const xmlChar *) "xhtml")))) {
+        xsltGenericError(xsltGenericErrorContext,
+               "xsltSaveResultTo : unknown ouput method\n");
+        return(-1);
+    }
+
+    base = buf->written;
+
+    XSLT_GET_IMPORT_PTR(method, style, method)
+    XSLT_GET_IMPORT_PTR(encoding, style, encoding)
+    XSLT_GET_IMPORT_INT(indent, style, indent);
+
+    if ((method == NULL) && (result->type == XML_HTML_DOCUMENT_NODE))
+       method = (const xmlChar *) "html";
+
+    if ((method != NULL) &&
+       (xmlStrEqual(method, (const xmlChar *) "html"))) {
+       if (encoding != NULL) {
+           htmlSetMetaEncoding(result, (const xmlChar *) encoding);
+       } else {
+           htmlSetMetaEncoding(result, (const xmlChar *) "UTF-8");
+       }
+       if (indent == -1)
+           indent = 1;
+       htmlDocContentDumpFormatOutput(buf, result, (const char *) encoding,
+                                      indent);
+       xmlOutputBufferFlush(buf);
+    } else if ((method != NULL) &&
+       (xmlStrEqual(method, (const xmlChar *) "xhtml"))) {
+       if (encoding != NULL) {
+           htmlSetMetaEncoding(result, (const xmlChar *) encoding);
+       } else {
+           htmlSetMetaEncoding(result, (const xmlChar *) "UTF-8");
+       }
+       htmlDocContentDumpOutput(buf, result, (const char *) encoding);
+       xmlOutputBufferFlush(buf);
+    } else if ((method != NULL) &&
+              (xmlStrEqual(method, (const xmlChar *) "text"))) {
+       xmlNodePtr cur;
+
+       cur = result->children;
+       while (cur != NULL) {
+           if (cur->type == XML_TEXT_NODE)
+               xmlOutputBufferWriteString(buf, (const char *) cur->content);
+
+           /*
+            * Skip to next node
+            */
+           if (cur->children != NULL) {
+               if ((cur->children->type != XML_ENTITY_DECL) &&
+                   (cur->children->type != XML_ENTITY_REF_NODE) &&
+                   (cur->children->type != XML_ENTITY_NODE)) {
+                   cur = cur->children;
+                   continue;
+               }
+           }
+           if (cur->next != NULL) {
+               cur = cur->next;
+               continue;
+           }
+           
+           do {
+               cur = cur->parent;
+               if (cur == NULL)
+                   break;
+               if (cur == (xmlNodePtr) style->doc) {
+                   cur = NULL;
+                   break;
+               }
+               if (cur->next != NULL) {
+                   cur = cur->next;
+                   break;
+               }
+           } while (cur != NULL);
+       }
+       xmlOutputBufferFlush(buf);
+    } else {
+       int omitXmlDecl;
+       int standalone;
+
+       XSLT_GET_IMPORT_INT(omitXmlDecl, style, omitXmlDeclaration);
+       XSLT_GET_IMPORT_INT(standalone, style, standalone);
+
+       if (omitXmlDecl != 1) {
+           xmlOutputBufferWriteString(buf, "<?xml version=");
+           if (result->version != NULL) 
+               xmlBufferWriteQuotedString(buf->buffer, result->version);
+           else
+               xmlOutputBufferWriteString(buf, "\"1.0\"");
+           if (encoding == NULL) {
+               if (result->encoding != NULL)
+                   encoding = result->encoding;
+               else if (result->charset != XML_CHAR_ENCODING_UTF8)
+                   encoding = (const xmlChar *)
+                              xmlGetCharEncodingName((xmlCharEncoding)
+                                                     result->charset);
+           }
+           if (encoding != NULL) {
+               xmlOutputBufferWriteString(buf, " encoding=");
+               xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
+           }
+           switch (standalone) {
+               case 0:
+                   xmlOutputBufferWriteString(buf, " standalone=\"no\"");
+                   break;
+               case 1:
+                   xmlOutputBufferWriteString(buf, " standalone=\"yes\"");
+                   break;
+               default:
+                   break;
+           }
+           xmlOutputBufferWriteString(buf, "?>\n");
+       }
+       if (result->children != NULL) {
+           xmlNodePtr child = result->children;
+
+           while (child != NULL) {
+               xmlNodeDumpOutput(buf, result, child, 0, (indent == 1),
+                                 (const char *) encoding);
+               if ((child->type == XML_DTD_NODE) ||
+                   ((child->type == XML_COMMENT_NODE) &&
+                    (child->next != NULL)))
+                   xmlOutputBufferWriteString(buf, "\n");
+               child = child->next;
+           }
+           xmlOutputBufferWriteString(buf, "\n");
+       }
+       xmlOutputBufferFlush(buf);
+    }
+    return(buf->written - base);
+}
+
+/**
+ * xsltSaveResultToFilename:
+ * @URL:  a filename or URL
+ * @result:  the result xmlDocPtr
+ * @style:  the stylesheet
+ * @compression:  the compression factor (0 - 9 included)
+ *
+ * Save the result @result obtained by applying the @style stylesheet
+ * to a file or @URL
+ *
+ * Returns the number of byte written or -1 in case of failure.
+ */
+int
+xsltSaveResultToFilename(const char *URL, xmlDocPtr result,
+                        xsltStylesheetPtr style, int compression) {
+    xmlOutputBufferPtr buf;
+    const xmlChar *encoding;
+    int ret;
+
+    if ((URL == NULL) || (result == NULL) || (style == NULL))
+       return(-1);
+    if (result->children == NULL)
+       return(0);
+
+    XSLT_GET_IMPORT_PTR(encoding, style, encoding)
+    if (encoding != NULL) {
+       xmlCharEncodingHandlerPtr encoder;
+
+       encoder = xmlFindCharEncodingHandler((char *)encoding);
+       if ((encoder != NULL) &&
+           (xmlStrEqual((const xmlChar *)encoder->name,
+                        (const xmlChar *) "UTF-8")))
+           encoder = NULL;
+       buf = xmlOutputBufferCreateFilename(URL, encoder, compression);
+    } else {
+       buf = xmlOutputBufferCreateFilename(URL, NULL, compression);
+    }
+    if (buf == NULL)
+       return(-1);
+    xsltSaveResultTo(buf, result, style);
+    ret = xmlOutputBufferClose(buf);
+    return(ret);
+}
+
+/**
+ * xsltSaveResultToFile:
+ * @file:  a FILE * I/O
+ * @result:  the result xmlDocPtr
+ * @style:  the stylesheet
+ *
+ * Save the result @result obtained by applying the @style stylesheet
+ * to an open FILE * I/O.
+ * This does not close the FILE @file
+ *
+ * Returns the number of bytes written or -1 in case of failure.
+ */
+int
+xsltSaveResultToFile(FILE *file, xmlDocPtr result, xsltStylesheetPtr style) {
+    xmlOutputBufferPtr buf;
+    const xmlChar *encoding;
+    int ret;
+
+    if ((file == NULL) || (result == NULL) || (style == NULL))
+       return(-1);
+    if (result->children == NULL)
+       return(0);
+
+    XSLT_GET_IMPORT_PTR(encoding, style, encoding)
+    if (encoding != NULL) {
+       xmlCharEncodingHandlerPtr encoder;
+
+       encoder = xmlFindCharEncodingHandler((char *)encoding);
+       if ((encoder != NULL) &&
+           (xmlStrEqual((const xmlChar *)encoder->name,
+                        (const xmlChar *) "UTF-8")))
+           encoder = NULL;
+       buf = xmlOutputBufferCreateFile(file, encoder);
+    } else {
+       buf = xmlOutputBufferCreateFile(file, NULL);
+    }
+
+    if (buf == NULL)
+       return(-1);
+    xsltSaveResultTo(buf, result, style);
+    ret = xmlOutputBufferClose(buf);
+    return(ret);
+}
+
+/**
+ * xsltSaveResultToFd:
+ * @fd:  a file descriptor
+ * @result:  the result xmlDocPtr
+ * @style:  the stylesheet
+ *
+ * Save the result @result obtained by applying the @style stylesheet
+ * to an open file descriptor
+ * This does not close the descriptor.
+ *
+ * Returns the number of bytes written or -1 in case of failure.
+ */
+int
+xsltSaveResultToFd(int fd, xmlDocPtr result, xsltStylesheetPtr style) {
+    xmlOutputBufferPtr buf;
+    const xmlChar *encoding;
+    int ret;
+
+    if ((fd < 0) || (result == NULL) || (style == NULL))
+       return(-1);
+    if (result->children == NULL)
+       return(0);
+
+    XSLT_GET_IMPORT_PTR(encoding, style, encoding)
+    if (encoding != NULL) {
+       xmlCharEncodingHandlerPtr encoder;
+
+       encoder = xmlFindCharEncodingHandler((char *)encoding);
+       if ((encoder != NULL) &&
+           (xmlStrEqual((const xmlChar *)encoder->name,
+                        (const xmlChar *) "UTF-8")))
+           encoder = NULL;
+       buf = xmlOutputBufferCreateFd(fd, encoder);
+    } else {
+       buf = xmlOutputBufferCreateFd(fd, NULL);
+    }
+    if (buf == NULL)
+       return(-1);
+    xsltSaveResultTo(buf, result, style);
+    ret = xmlOutputBufferClose(buf);
+    return(ret);
+}
+
+/**
+ * xsltSaveResultToString:
+ * @doc_txt_ptr:  Memory pointer for allocated XML text
+ * @doc_txt_len:  Length of the generated XML text
+ * @result:  the result xmlDocPtr
+ * @style:  the stylesheet
+ *
+ * Save the result @result obtained by applying the @style stylesheet
+ * to a new allocated string.
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+int
+xsltSaveResultToString(xmlChar **doc_txt_ptr, int * doc_txt_len, 
+                      xmlDocPtr result, xsltStylesheetPtr style) {
+    xmlOutputBufferPtr buf;
+    const xmlChar *encoding;
+
+    *doc_txt_ptr = NULL;
+    *doc_txt_len = 0;
+    if (result->children == NULL)
+       return(0);
+
+    XSLT_GET_IMPORT_PTR(encoding, style, encoding)
+    if (encoding != NULL) {
+       xmlCharEncodingHandlerPtr encoder;
+
+       encoder = xmlFindCharEncodingHandler((char *)encoding);
+       if ((encoder != NULL) &&
+           (xmlStrEqual((const xmlChar *)encoder->name,
+                        (const xmlChar *) "UTF-8")))
+           encoder = NULL;
+       buf = xmlAllocOutputBuffer(encoder);
+    } else {
+       buf = xmlAllocOutputBuffer(NULL);
+    }
+    if (buf == NULL)
+       return(-1);
+    xsltSaveResultTo(buf, result, style);
+    if (buf->conv != NULL) {
+       *doc_txt_len = buf->conv->use;
+       *doc_txt_ptr = xmlStrndup(buf->conv->content, *doc_txt_len);
+    } else {
+       *doc_txt_len = buf->buffer->use;
+       *doc_txt_ptr = xmlStrndup(buf->buffer->content, *doc_txt_len);
+    }
+    (void)xmlOutputBufferClose(buf);
+    return 0;
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Generating profiling informations                       *
+ *                                                                     *
+ ************************************************************************/
+
+static long calibration = -1;
+
+/**
+ * xsltCalibrateTimestamps:
+ *
+ * Used for to calibrate the xsltTimestamp() function
+ * Should work if launched at startup and we don't loose our quantum :-)
+ *
+ * Returns the number of milliseconds used by xsltTimestamp()
+ */
+static long
+xsltCalibrateTimestamps(void) {
+    register int i;
+
+    for (i = 0;i < 999;i++)
+       xsltTimestamp();
+    return(xsltTimestamp() / 1000);
+}
+
+/**
+ * xsltCalibrateAdjust:
+ * @delta:  a negative dealy value found
+ *
+ * Used for to correct the calibration for xsltTimestamp()
+ */
+void
+xsltCalibrateAdjust(long delta) {
+    calibration += delta;
+}
+
+/**
+ * xsltTimestamp:
+ *
+ * Used for gathering profiling data
+ *
+ * Returns the number of tenth of milliseconds since the beginning of the
+ * profiling
+ */
+long
+xsltTimestamp(void)
+{
+#ifdef XSLT_WIN32_PERFORMANCE_COUNTER
+    BOOL ok;
+    LARGE_INTEGER performanceCount;
+    LARGE_INTEGER performanceFrequency;
+    LONGLONG quadCount;
+    double seconds;
+    static LONGLONG startupQuadCount = 0;
+    static LONGLONG startupQuadFreq = 0;
+
+    ok = QueryPerformanceCounter(&performanceCount);
+    if (!ok)
+        return 0;
+    quadCount = performanceCount.QuadPart;
+    if (calibration < 0) {
+        calibration = 0;
+        ok = QueryPerformanceFrequency(&performanceFrequency);
+        if (!ok)
+            return 0;
+        startupQuadFreq = performanceFrequency.QuadPart;
+        startupQuadCount = quadCount;
+        return (0);
+    }
+    if (startupQuadFreq == 0)
+        return 0;
+    seconds = (quadCount - startupQuadCount) / (double) startupQuadFreq;
+    return (long) (seconds * XSLT_TIMESTAMP_TICS_PER_SEC);
+
+#else /* XSLT_WIN32_PERFORMANCE_COUNTER */
+#ifdef HAVE_GETTIMEOFDAY
+    static struct timeval startup;
+    struct timeval cur;
+    long tics;
+
+    if (calibration < 0) {
+        gettimeofday(&startup, NULL);
+        calibration = 0;
+        calibration = xsltCalibrateTimestamps();
+        gettimeofday(&startup, NULL);
+        return (0);
+    }
+
+    gettimeofday(&cur, NULL);
+    tics = (cur.tv_sec - startup.tv_sec) * XSLT_TIMESTAMP_TICS_PER_SEC;
+    tics += (cur.tv_usec - startup.tv_usec) /
+                          (1000000l / XSLT_TIMESTAMP_TICS_PER_SEC);
+    
+    tics -= calibration;
+    return(tics);
+#else
+
+    /* Neither gettimeofday() nor Win32 performance counter available */
+
+    return (0);
+
+#endif /* HAVE_GETTIMEOFDAY */
+#endif /* XSLT_WIN32_PERFORMANCE_COUNTER */
+}
+
+#define MAX_TEMPLATES 10000
+
+/**
+ * xsltSaveProfiling:
+ * @ctxt:  an XSLT context
+ * @output:  a FILE * for saving the informations
+ *
+ * Save the profiling informations on @output
+ */
+void
+xsltSaveProfiling(xsltTransformContextPtr ctxt, FILE *output) {
+    int nb, i,j;
+    int max;
+    int total;
+    long totalt;
+    xsltTemplatePtr *templates;
+    xsltStylesheetPtr style;
+    xsltTemplatePtr template;
+
+    if ((output == NULL) || (ctxt == NULL))
+       return;
+    if (ctxt->profile == 0)
+       return;
+
+    nb = 0;
+    max = MAX_TEMPLATES;
+    templates = xmlMalloc(max * sizeof(xsltTemplatePtr));
+    if (templates == NULL)
+       return;
+
+    style = ctxt->style;
+    while (style != NULL) {
+       template = style->templates;
+       while (template != NULL) {
+           if (nb >= max)
+               break;
+
+           if (template->nbCalls > 0)
+               templates[nb++] = template;
+           template = template->next;
+       }
+
+       style = xsltNextImport(style);
+    }
+
+    for (i = 0;i < nb -1;i++) {
+       for (j = i + 1; j < nb; j++) {
+           if ((templates[i]->time <= templates[j]->time) ||
+               ((templates[i]->time == templates[j]->time) &&
+                (templates[i]->nbCalls <= templates[j]->nbCalls))) {
+               template = templates[j];
+               templates[j] = templates[i];
+               templates[i] = template;
+           }
+       }
+    }
+
+    fprintf(output, "%6s%20s%20s%10s  Calls Tot 100us Avg\n\n",
+           "number", "match", "name", "mode");
+    total = 0;
+    totalt = 0;
+    for (i = 0;i < nb;i++) {
+       fprintf(output, "%5d ", i);
+       if (templates[i]->match != NULL) {
+           if (xmlStrlen(templates[i]->match) > 20)
+               fprintf(output, "%s\n%26s", templates[i]->match, "");
+           else
+               fprintf(output, "%20s", templates[i]->match);
+       } else {
+           fprintf(output, "%20s", "");
+       }
+       if (templates[i]->name != NULL) {
+           if (xmlStrlen(templates[i]->name) > 20)
+               fprintf(output, "%s\n%46s", templates[i]->name, "");
+           else
+               fprintf(output, "%20s", templates[i]->name);
+       } else {
+           fprintf(output, "%20s", "");
+       }
+       if (templates[i]->mode != NULL) {
+           if (xmlStrlen(templates[i]->mode) > 10)
+               fprintf(output, "%s\n%56s", templates[i]->mode, "");
+           else
+               fprintf(output, "%10s", templates[i]->mode);
+       } else {
+           fprintf(output, "%10s", "");
+       }
+       fprintf(output, " %6d", templates[i]->nbCalls);
+       fprintf(output, " %6ld %6ld\n", templates[i]->time,
+               templates[i]->time / templates[i]->nbCalls);
+       total += templates[i]->nbCalls;
+       totalt += templates[i]->time;
+    }
+    fprintf(output, "\n%30s%26s %6d %6ld\n", "Total", "", total, totalt);
+
+    xmlFree(templates);
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Fetching profiling informations                         *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltGetProfileInformation:
+ * @ctxt:  a transformation context
+ *
+ * This function should be called after the transformation completed
+ * to extract template processing profiling informations if availble.
+ * The informations are returned as an XML document tree like
+ * <?xml version="1.0"?>
+ * <profile>
+ * <template rank="1" match="*" name=""
+ *         mode="" calls="6" time="48" average="8"/>
+ * <template rank="2" match="item2|item3" name=""
+ *         mode="" calls="10" time="30" average="3"/>
+ * <template rank="3" match="item1" name=""
+ *         mode="" calls="5" time="17" average="3"/>
+ * </profile>
+ * The caller will need to free up the returned tree with xmlFreeDoc()
+ *
+ * Returns the xmlDocPtr corresponding to the result or NULL if not available.
+ */
+
+xmlDocPtr
+xsltGetProfileInformation(xsltTransformContextPtr ctxt)
+{
+    xmlDocPtr ret = NULL;
+    xmlNodePtr root, child;
+    char buf[100];
+
+    xsltStylesheetPtr style;
+    xsltTemplatePtr *templates;
+    xsltTemplatePtr templ;
+    int nb = 0, max = 0, i, j;
+
+    if (!ctxt)
+        return NULL;
+
+    if (!ctxt->profile)
+        return NULL;
+
+    nb = 0;
+    max = 10000;
+    templates =
+        (xsltTemplatePtr *) xmlMalloc(max * sizeof(xsltTemplatePtr));
+    if (templates == NULL)
+        return NULL;
+
+    /*
+     * collect all the templates in an array
+     */
+    style = ctxt->style;
+    while (style != NULL) {
+        templ = style->templates;
+        while (templ != NULL) {
+            if (nb >= max)
+                break;
+
+            if (templ->nbCalls > 0)
+                templates[nb++] = templ;
+            templ = templ->next;
+        }
+
+        style = (xsltStylesheetPtr) xsltNextImport(style);
+    }
+
+    /*
+     * Sort the array by time spent
+     */
+    for (i = 0; i < nb - 1; i++) {
+        for (j = i + 1; j < nb; j++) {
+            if ((templates[i]->time <= templates[j]->time) ||
+                ((templates[i]->time == templates[j]->time) &&
+                 (templates[i]->nbCalls <= templates[j]->nbCalls))) {
+                templ = templates[j];
+                templates[j] = templates[i];
+                templates[i] = templ;
+            }
+        }
+    }
+
+    /*
+     * Generate a document corresponding to the results.
+     */
+    ret = xmlNewDoc(BAD_CAST "1.0");
+    root = xmlNewDocNode(ret, NULL, BAD_CAST "profile", NULL);
+    xmlDocSetRootElement(ret, root);
+
+    for (i = 0; i < nb; i++) {
+        child = xmlNewChild(root, NULL, BAD_CAST "template", NULL);
+        sprintf(buf, "%d", i + 1);
+        xmlSetProp(child, BAD_CAST "rank", BAD_CAST buf);
+        xmlSetProp(child, BAD_CAST "match", BAD_CAST templates[i]->match);
+        xmlSetProp(child, BAD_CAST "name", BAD_CAST templates[i]->name);
+        xmlSetProp(child, BAD_CAST "mode", BAD_CAST templates[i]->mode);
+
+        sprintf(buf, "%d", templates[i]->nbCalls);
+        xmlSetProp(child, BAD_CAST "calls", BAD_CAST buf);
+
+        sprintf(buf, "%ld", templates[i]->time);
+        xmlSetProp(child, BAD_CAST "time", BAD_CAST buf);
+
+        sprintf(buf, "%ld", templates[i]->time / templates[i]->nbCalls);
+        xmlSetProp(child, BAD_CAST "average", BAD_CAST buf);
+    };
+
+    xmlFree(templates);
+
+    return ret;
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Hooks for libxml2 XPath                                 *
+ *                                                                     *
+ ************************************************************************/
+
+/**
+ * xsltXPathCompile:
+ * @style: the stylesheet
+ * @str:  the XPath expression
+ *
+ * Compile an XPath expression
+ *
+ * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
+ *         the caller has to free the object.
+ */
+xmlXPathCompExprPtr
+xsltXPathCompile(xsltStylesheetPtr style, const xmlChar *str) {
+    xmlXPathContextPtr xpathCtxt;
+    xmlXPathCompExprPtr ret;
+
+    if (style != NULL) {
+#ifdef XSLT_REFACTORED_XPATHCOMP
+       if (XSLT_CCTXT(style)) {
+           /*
+           * Proposed by Jerome Pesenti
+           * --------------------------
+           * For better efficiency we'll reuse the compilation
+           * context's XPath context. For the common stylesheet using
+           * XPath expressions this will reduce compilation time to
+           * about 50%.
+           *
+           * See http://mail.gnome.org/archives/xslt/2006-April/msg00037.html
+           */
+           xpathCtxt = XSLT_CCTXT(style)->xpathCtxt;
+           xpathCtxt->doc = style->doc;
+       } else
+           xpathCtxt = xmlXPathNewContext(style->doc); 
+#else
+       xpathCtxt = xmlXPathNewContext(style->doc);
+#endif
+       xpathCtxt->dict = style->dict;
+    } else {
+       xpathCtxt = xmlXPathNewContext(NULL);
+    }
+    /*
+    * Compile the expression.
+    */
+    ret = xmlXPathCtxtCompile(xpathCtxt, str);
+
+#ifdef XSLT_REFACTORED_XPATHCOMP
+    if ((style == NULL) || (! XSLT_CCTXT(style))) {
+       xmlXPathFreeContext(xpathCtxt);
+    }
+#else
+    xmlXPathFreeContext(xpathCtxt);
+#endif
+    /*
+     * TODO: there is a lot of optimizations which should be possible
+     *       like variable slot precomputations, function precomputations, etc.
+     */
+
+    return(ret);
+}
+
+/************************************************************************
+ *                                                                     *
+ *             Hooks for the debugger                                  *
+ *                                                                     *
+ ************************************************************************/
+
+/*
+ * There is currently only 3 debugging callback defined
+ * Debugger callbacks are disabled by default
+ */
+#define XSLT_CALLBACK_NUMBER 3
+
+typedef struct _xsltDebuggerCallbacks xsltDebuggerCallbacks;
+typedef xsltDebuggerCallbacks *xsltDebuggerCallbacksPtr;
+struct _xsltDebuggerCallbacks {
+    xsltHandleDebuggerCallback handler;
+    xsltAddCallCallback add;
+    xsltDropCallCallback drop;
+};
+
+static xsltDebuggerCallbacks xsltDebuggerCurrentCallbacks = {
+    NULL, /* handler */
+    NULL, /* add */
+    NULL  /* drop */
+};
+
+int xslDebugStatus;
+
+/**
+ * xsltSetDebuggerStatus:
+ * @value : the value to be set
+ * 
+ * This function sets the value of xslDebugStatus.
+ */
+void
+xsltSetDebuggerStatus(int value)
+{
+    xslDebugStatus = value;    
+}
+
+/**
+ * xsltGetDebuggerStatus: 
+ * 
+ * Get xslDebugStatus.
+ *
+ * Returns the value of xslDebugStatus.
+ */
+int
+xsltGetDebuggerStatus(void)
+{
+    return(xslDebugStatus);    
+}
+
+/**
+ * xsltSetDebuggerCallbacks:
+ * @no : number of callbacks
+ * @block : the block of callbacks
+ * 
+ * This function allow to plug a debugger into the XSLT library
+ * @block points to a block of memory containing the address of @no 
+ * callback routines.
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+int
+xsltSetDebuggerCallbacks(int no, void *block)
+{
+    xsltDebuggerCallbacksPtr callbacks;
+
+    if ((block == NULL) || (no != XSLT_CALLBACK_NUMBER))
+       return(-1);
+
+    callbacks = (xsltDebuggerCallbacksPtr) block;
+    xsltDebuggerCurrentCallbacks.handler = callbacks->handler;
+    xsltDebuggerCurrentCallbacks.add  = callbacks->add;
+    xsltDebuggerCurrentCallbacks.drop  = callbacks->drop;
+    return(0);
+}
+
+/**
+ * xslHandleDebugger:
+ * @cur : source node being executed
+ * @node : data node being processed
+ * @templ : temlate that applies to node
+ * @ctxt : the xslt transform context 
+ * 
+ * If either cur or node are a breakpoint, or xslDebugStatus in state 
+ *   where debugging must occcur at this time then transfer control
+ *   to the xslDebugBreak function
+ */
+void
+xslHandleDebugger(xmlNodePtr cur, xmlNodePtr node, xsltTemplatePtr templ,
+                 xsltTransformContextPtr ctxt)
+{
+    if (xsltDebuggerCurrentCallbacks.handler != NULL)
+       xsltDebuggerCurrentCallbacks.handler(cur, node, templ, ctxt);
+}
+
+/**
+ * xslAddCall:
+ * @templ : current template being applied
+ * @source : the source node being processed
+ *
+ * Add template "call" to call stack
+ * Returns : 1 on sucess 0 otherwise an error may be printed if 
+ *            WITH_XSLT_DEBUG_BREAKPOINTS is defined
+ */
+int
+xslAddCall(xsltTemplatePtr templ, xmlNodePtr source)
+{
+    if (xsltDebuggerCurrentCallbacks.add != NULL)
+       return(xsltDebuggerCurrentCallbacks.add(templ, source));
+    return(0);
+}
+
+/**
+ * xslDropCall:
+ *
+ * Drop the topmost item off the call stack
+ */
+void
+xslDropCall(void)
+{
+    if (xsltDebuggerCurrentCallbacks.drop != NULL)
+       xsltDebuggerCurrentCallbacks.drop();
+}
+
index 3595c6a..3886be3 100644 (file)
-/*\r
- * Summary: set of utilities for the XSLT engine\r
- * Description: interfaces for the utilities module of the XSLT engine.\r
- *              things like message handling, profiling, and other\r
- *              generally useful routines.\r
- *\r
- * Copy: See Copyright for the status of this software.\r
- *\r
- * Author: Daniel Veillard\r
- */\r
-\r
-#ifndef __XML_XSLTUTILS_H__\r
-#define __XML_XSLTUTILS_H__\r
-\r
-#include <libxslt/xsltconfig.h>\r
-#ifdef HAVE_STDARG_H\r
-#include <stdarg.h>\r
-#endif\r
-#include <libxml/xpath.h>\r
-#include <libxml/dict.h>\r
-#include <libxml/xmlerror.h>\r
-#include "xsltexports.h"\r
-#include "xsltInternals.h"\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-/**\r
- * XSLT_TODO:\r
- *\r
- * Macro to flag unimplemented blocks.\r
- */\r
-#define XSLT_TODO                                                      \\r
-    xsltGenericError(xsltGenericErrorContext,                          \\r
-           "Unimplemented block at %s:%d\n",                           \\r
-            __FILE__, __LINE__);\r
-\r
-/**\r
- * XSLT_STRANGE:\r
- *\r
- * Macro to flag that a problem was detected internally.\r
- */\r
-#define XSLT_STRANGE                                                   \\r
-    xsltGenericError(xsltGenericErrorContext,                          \\r
-           "Internal error at %s:%d\n",                                \\r
-            __FILE__, __LINE__);\r
-\r
-/**\r
- * IS_XSLT_ELEM:\r
- *\r
- * Checks that the element pertains to XSLT namespace.\r
- */\r
-#define IS_XSLT_ELEM(n)                                                        \\r
-    (((n) != NULL) && ((n)->ns != NULL) &&                             \\r
-     (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE)))\r
-\r
-/**\r
- * IS_XSLT_NAME:\r
- *\r
- * Checks the value of an element in XSLT namespace.\r
- */\r
-#define IS_XSLT_NAME(n, val)                                           \\r
-    (xmlStrEqual((n)->name, (const xmlChar *) (val)))\r
-\r
-/**\r
- * IS_XSLT_REAL_NODE:\r
- *\r
- * Check that a node is a 'real' one: document, element, text or attribute.\r
- */\r
-#define IS_XSLT_REAL_NODE(n)                                           \\r
-    (((n) != NULL) &&                                                  \\r
-     (((n)->type == XML_ELEMENT_NODE) ||                               \\r
-      ((n)->type == XML_TEXT_NODE) ||                                  \\r
-      ((n)->type == XML_CDATA_SECTION_NODE) ||                         \\r
-      ((n)->type == XML_ATTRIBUTE_NODE) ||                             \\r
-      ((n)->type == XML_DOCUMENT_NODE) ||                              \\r
-      ((n)->type == XML_HTML_DOCUMENT_NODE) ||                         \\r
-      ((n)->type == XML_COMMENT_NODE) ||                               \\r
-      ((n)->type == XML_PI_NODE)))      \r
-\r
-/*\r
- * Our own version of namespaced atributes lookup.\r
- */\r
-XSLTPUBFUN xmlChar * XSLTCALL\r
-               xsltGetNsProp   (xmlNodePtr node,\r
-                                const xmlChar *name,\r
-                                const xmlChar *nameSpace);\r
-XSLTPUBFUN const xmlChar * XSLTCALL\r
-               xsltGetCNsProp  (xsltStylesheetPtr style,\r
-                                xmlNodePtr node,\r
-                                const xmlChar *name,\r
-                                const xmlChar *nameSpace);\r
-XSLTPUBFUN int XSLTCALL\r
-               xsltGetUTF8Char (const unsigned char *utf,\r
-                                int *len);\r
-\r
-/*\r
- * XSLT Debug Tracing Tracing Types\r
- */\r
-typedef enum {\r
-       XSLT_TRACE_ALL =                -1,\r
-       XSLT_TRACE_NONE =               0,\r
-       XSLT_TRACE_COPY_TEXT =          1<<0,\r
-       XSLT_TRACE_PROCESS_NODE =       1<<1,\r
-       XSLT_TRACE_APPLY_TEMPLATE =     1<<2,\r
-       XSLT_TRACE_COPY =               1<<3,\r
-       XSLT_TRACE_COMMENT =            1<<4,\r
-       XSLT_TRACE_PI =                 1<<5,\r
-       XSLT_TRACE_COPY_OF =            1<<6,\r
-       XSLT_TRACE_VALUE_OF =           1<<7,\r
-       XSLT_TRACE_CALL_TEMPLATE =      1<<8,\r
-       XSLT_TRACE_APPLY_TEMPLATES =    1<<9,\r
-       XSLT_TRACE_CHOOSE =             1<<10,\r
-       XSLT_TRACE_IF =                 1<<11,\r
-       XSLT_TRACE_FOR_EACH =           1<<12,\r
-       XSLT_TRACE_STRIP_SPACES =       1<<13,\r
-       XSLT_TRACE_TEMPLATES =          1<<14,\r
-       XSLT_TRACE_KEYS =               1<<15,\r
-       XSLT_TRACE_VARIABLES =          1<<16\r
-} xsltDebugTraceCodes;\r
-\r
-/**\r
- * XSLT_TRACE:\r
- *\r
- * Control the type of xsl debugtrace messages emitted.\r
- */\r
-#define XSLT_TRACE(ctxt,code,call)     \\r
-       if (ctxt->traceCode && (*(ctxt->traceCode) & code)) \\r
-           call\r
-\r
-XSLTPUBFUN void XSLTCALL\r
-               xsltDebugSetDefaultTrace(xsltDebugTraceCodes val);\r
-XSLTPUBFUN xsltDebugTraceCodes XSLTCALL\r
-               xsltDebugGetDefaultTrace(void);\r
-\r
-/*\r
- * XSLT specific error and debug reporting functions.\r
- */\r
-XSLTPUBVAR xmlGenericErrorFunc xsltGenericError;\r
-XSLTPUBVAR void *xsltGenericErrorContext;\r
-XSLTPUBVAR xmlGenericErrorFunc xsltGenericDebug;\r
-XSLTPUBVAR void *xsltGenericDebugContext;\r
-\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltPrintErrorContext           (xsltTransformContextPtr ctxt,\r
-                                                xsltStylesheetPtr style,\r
-                                                xmlNodePtr node);\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltMessage                     (xsltTransformContextPtr ctxt,\r
-                                                xmlNodePtr node,\r
-                                                xmlNodePtr inst);\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltSetGenericErrorFunc         (void *ctx,\r
-                                                xmlGenericErrorFunc handler);\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltSetGenericDebugFunc         (void *ctx,\r
-                                                xmlGenericErrorFunc handler);\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltSetTransformErrorFunc       (xsltTransformContextPtr ctxt,\r
-                                                void *ctx,\r
-                                                xmlGenericErrorFunc handler);\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltTransformError              (xsltTransformContextPtr ctxt,\r
-                                                xsltStylesheetPtr style,\r
-                                                xmlNodePtr node,\r
-                                                const char *msg,\r
-                                                ...);\r
-\r
-XSLTPUBFUN int XSLTCALL\r
-               xsltSetCtxtParseOptions         (xsltTransformContextPtr ctxt,\r
-                                                int options);\r
-/*\r
- * Sorting.\r
- */\r
-\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltDocumentSortFunction        (xmlNodeSetPtr list);\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltSetSortFunc                 (xsltSortFunc handler);\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltSetCtxtSortFunc             (xsltTransformContextPtr ctxt,\r
-                                                xsltSortFunc handler);\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltDefaultSortFunction         (xsltTransformContextPtr ctxt,\r
-                                                xmlNodePtr *sorts,\r
-                                                int nbsorts);\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltDoSortFunction              (xsltTransformContextPtr ctxt,\r
-                                                xmlNodePtr * sorts,\r
-                                                int nbsorts);\r
-XSLTPUBFUN xmlXPathObjectPtr * XSLTCALL \r
-               xsltComputeSortResult           (xsltTransformContextPtr ctxt,\r
-                                                xmlNodePtr sort);\r
-\r
-/*\r
- * QNames handling.\r
- */\r
-\r
-XSLTPUBFUN const xmlChar * XSLTCALL\r
-               xsltSplitQName                  (xmlDictPtr dict,\r
-                                                const xmlChar *name,\r
-                                                const xmlChar **prefix);\r
-XSLTPUBFUN const xmlChar * XSLTCALL \r
-               xsltGetQNameURI                 (xmlNodePtr node,\r
-                                                xmlChar **name);\r
-\r
-XSLTPUBFUN const xmlChar * XSLTCALL\r
-               xsltGetQNameURI2                (xsltStylesheetPtr style,\r
-                                                xmlNodePtr node,\r
-                                                const xmlChar **name);\r
-\r
-/*\r
- * Output, reuse libxml I/O buffers.\r
- */\r
-XSLTPUBFUN int XSLTCALL                \r
-               xsltSaveResultTo                (xmlOutputBufferPtr buf,\r
-                                                xmlDocPtr result,\r
-                                                xsltStylesheetPtr style);\r
-XSLTPUBFUN int XSLTCALL                \r
-               xsltSaveResultToFilename        (const char *URI,\r
-                                                xmlDocPtr result,\r
-                                                xsltStylesheetPtr style,\r
-                                                int compression);\r
-XSLTPUBFUN int XSLTCALL                \r
-               xsltSaveResultToFile            (FILE *file,\r
-                                                xmlDocPtr result,\r
-                                                xsltStylesheetPtr style);\r
-XSLTPUBFUN int XSLTCALL                \r
-               xsltSaveResultToFd              (int fd,\r
-                                                xmlDocPtr result,\r
-                                                xsltStylesheetPtr style);\r
-XSLTPUBFUN int XSLTCALL             \r
-               xsltSaveResultToString          (xmlChar **doc_txt_ptr, \r
-                                                 int * doc_txt_len, \r
-                                                 xmlDocPtr result, \r
-                                                 xsltStylesheetPtr style);\r
-\r
-/*\r
- * XPath interface\r
- */\r
-XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL\r
-               xsltXPathCompile                (xsltStylesheetPtr style,\r
-                                                const xmlChar *str);\r
-\r
-/*\r
- * Profiling.\r
- */\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltSaveProfiling               (xsltTransformContextPtr ctxt,\r
-                                                FILE *output);\r
-XSLTPUBFUN xmlDocPtr XSLTCALL  \r
-               xsltGetProfileInformation       (xsltTransformContextPtr ctxt);\r
-\r
-XSLTPUBFUN long XSLTCALL               \r
-               xsltTimestamp                   (void);\r
-XSLTPUBFUN void XSLTCALL               \r
-               xsltCalibrateAdjust             (long delta);\r
-\r
-/**\r
- * XSLT_TIMESTAMP_TICS_PER_SEC:\r
- *\r
- * Sampling precision for profiling\r
- */\r
-#define XSLT_TIMESTAMP_TICS_PER_SEC 100000l\r
-\r
-/*\r
- * Hooks for the debugger.\r
- */\r
-\r
-typedef enum {\r
-    XSLT_DEBUG_NONE = 0, /* no debugging allowed */\r
-    XSLT_DEBUG_INIT,\r
-    XSLT_DEBUG_STEP,\r
-    XSLT_DEBUG_STEPOUT,\r
-    XSLT_DEBUG_NEXT,\r
-    XSLT_DEBUG_STOP,\r
-    XSLT_DEBUG_CONT,\r
-    XSLT_DEBUG_RUN,\r
-    XSLT_DEBUG_RUN_RESTART,\r
-    XSLT_DEBUG_QUIT\r
-} xsltDebugStatusCodes;\r
-\r
-XSLTPUBVAR int xslDebugStatus;\r
-\r
-typedef void (*xsltHandleDebuggerCallback) (xmlNodePtr cur, xmlNodePtr node,\r
-                       xsltTemplatePtr templ, xsltTransformContextPtr ctxt);\r
-typedef int (*xsltAddCallCallback) (xsltTemplatePtr templ, xmlNodePtr source);\r
-typedef void (*xsltDropCallCallback) (void);\r
-\r
-XSLTPUBFUN void XSLTCALL\r
-               xsltSetDebuggerStatus           (int value);\r
-XSLTPUBFUN int XSLTCALL\r
-               xsltGetDebuggerStatus           (void);\r
-XSLTPUBFUN int XSLTCALL                \r
-               xsltSetDebuggerCallbacks        (int no, void *block);\r
-XSLTPUBFUN int XSLTCALL                \r
-               xslAddCall                      (xsltTemplatePtr templ,\r
-                                                xmlNodePtr source);\r
-XSLTPUBFUN void XSLTCALL               \r
-               xslDropCall                     (void);\r
-\r
-#ifdef __cplusplus\r
-}\r
-#endif\r
-\r
-#endif /* __XML_XSLTUTILS_H__ */\r
-\r
-\r
+/*
+ * Summary: set of utilities for the XSLT engine
+ * Description: interfaces for the utilities module of the XSLT engine.
+ *              things like message handling, profiling, and other
+ *              generally useful routines.
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Daniel Veillard
+ */
+
+#ifndef __XML_XSLTUTILS_H__
+#define __XML_XSLTUTILS_H__
+
+#include <libxslt/xsltconfig.h>
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#include <libxml/xpath.h>
+#include <libxml/dict.h>
+#include <libxml/xmlerror.h>
+#include "xsltexports.h"
+#include "xsltInternals.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * XSLT_TODO:
+ *
+ * Macro to flag unimplemented blocks.
+ */
+#define XSLT_TODO                                                      \
+    xsltGenericError(xsltGenericErrorContext,                          \
+           "Unimplemented block at %s:%d\n",                           \
+            __FILE__, __LINE__);
+
+/**
+ * XSLT_STRANGE:
+ *
+ * Macro to flag that a problem was detected internally.
+ */
+#define XSLT_STRANGE                                                   \
+    xsltGenericError(xsltGenericErrorContext,                          \
+           "Internal error at %s:%d\n",                                \
+            __FILE__, __LINE__);
+
+/**
+ * IS_XSLT_ELEM:
+ *
+ * Checks that the element pertains to XSLT namespace.
+ */
+#define IS_XSLT_ELEM(n)                                                        \
+    (((n) != NULL) && ((n)->ns != NULL) &&                             \
+     (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE)))
+
+/**
+ * IS_XSLT_NAME:
+ *
+ * Checks the value of an element in XSLT namespace.
+ */
+#define IS_XSLT_NAME(n, val)                                           \
+    (xmlStrEqual((n)->name, (const xmlChar *) (val)))
+
+/**
+ * IS_XSLT_REAL_NODE:
+ *
+ * Check that a node is a 'real' one: document, element, text or attribute.
+ */
+#define IS_XSLT_REAL_NODE(n)                                           \
+    (((n) != NULL) &&                                                  \
+     (((n)->type == XML_ELEMENT_NODE) ||                               \
+      ((n)->type == XML_TEXT_NODE) ||                                  \
+      ((n)->type == XML_CDATA_SECTION_NODE) ||                         \
+      ((n)->type == XML_ATTRIBUTE_NODE) ||                             \
+      ((n)->type == XML_DOCUMENT_NODE) ||                              \
+      ((n)->type == XML_HTML_DOCUMENT_NODE) ||                         \
+      ((n)->type == XML_COMMENT_NODE) ||                               \
+      ((n)->type == XML_PI_NODE)))      
+
+/*
+ * Our own version of namespaced atributes lookup.
+ */
+XSLTPUBFUN xmlChar * XSLTCALL
+               xsltGetNsProp   (xmlNodePtr node,
+                                const xmlChar *name,
+                                const xmlChar *nameSpace);
+XSLTPUBFUN const xmlChar * XSLTCALL
+               xsltGetCNsProp  (xsltStylesheetPtr style,
+                                xmlNodePtr node,
+                                const xmlChar *name,
+                                const xmlChar *nameSpace);
+XSLTPUBFUN int XSLTCALL
+               xsltGetUTF8Char (const unsigned char *utf,
+                                int *len);
+
+/*
+ * XSLT Debug Tracing Tracing Types
+ */
+typedef enum {
+       XSLT_TRACE_ALL =                -1,
+       XSLT_TRACE_NONE =               0,
+       XSLT_TRACE_COPY_TEXT =          1<<0,
+       XSLT_TRACE_PROCESS_NODE =       1<<1,
+       XSLT_TRACE_APPLY_TEMPLATE =     1<<2,
+       XSLT_TRACE_COPY =               1<<3,
+       XSLT_TRACE_COMMENT =            1<<4,
+       XSLT_TRACE_PI =                 1<<5,
+       XSLT_TRACE_COPY_OF =            1<<6,
+       XSLT_TRACE_VALUE_OF =           1<<7,
+       XSLT_TRACE_CALL_TEMPLATE =      1<<8,
+       XSLT_TRACE_APPLY_TEMPLATES =    1<<9,
+       XSLT_TRACE_CHOOSE =             1<<10,
+       XSLT_TRACE_IF =                 1<<11,
+       XSLT_TRACE_FOR_EACH =           1<<12,
+       XSLT_TRACE_STRIP_SPACES =       1<<13,
+       XSLT_TRACE_TEMPLATES =          1<<14,
+       XSLT_TRACE_KEYS =               1<<15,
+       XSLT_TRACE_VARIABLES =          1<<16
+} xsltDebugTraceCodes;
+
+/**
+ * XSLT_TRACE:
+ *
+ * Control the type of xsl debugtrace messages emitted.
+ */
+#define XSLT_TRACE(ctxt,code,call)     \
+       if (ctxt->traceCode && (*(ctxt->traceCode) & code)) \
+           call
+
+XSLTPUBFUN void XSLTCALL
+               xsltDebugSetDefaultTrace(xsltDebugTraceCodes val);
+XSLTPUBFUN xsltDebugTraceCodes XSLTCALL
+               xsltDebugGetDefaultTrace(void);
+
+/*
+ * XSLT specific error and debug reporting functions.
+ */
+XSLTPUBVAR xmlGenericErrorFunc xsltGenericError;
+XSLTPUBVAR void *xsltGenericErrorContext;
+XSLTPUBVAR xmlGenericErrorFunc xsltGenericDebug;
+XSLTPUBVAR void *xsltGenericDebugContext;
+
+XSLTPUBFUN void XSLTCALL               
+               xsltPrintErrorContext           (xsltTransformContextPtr ctxt,
+                                                xsltStylesheetPtr style,
+                                                xmlNodePtr node);
+XSLTPUBFUN void XSLTCALL               
+               xsltMessage                     (xsltTransformContextPtr ctxt,
+                                                xmlNodePtr node,
+                                                xmlNodePtr inst);
+XSLTPUBFUN void XSLTCALL               
+               xsltSetGenericErrorFunc         (void *ctx,
+                                                xmlGenericErrorFunc handler);
+XSLTPUBFUN void XSLTCALL               
+               xsltSetGenericDebugFunc         (void *ctx,
+                                                xmlGenericErrorFunc handler);
+XSLTPUBFUN void XSLTCALL               
+               xsltSetTransformErrorFunc       (xsltTransformContextPtr ctxt,
+                                                void *ctx,
+                                                xmlGenericErrorFunc handler);
+XSLTPUBFUN void XSLTCALL               
+               xsltTransformError              (xsltTransformContextPtr ctxt,
+                                                xsltStylesheetPtr style,
+                                                xmlNodePtr node,
+                                                const char *msg,
+                                                ...);
+
+XSLTPUBFUN int XSLTCALL
+               xsltSetCtxtParseOptions         (xsltTransformContextPtr ctxt,
+                                                int options);
+/*
+ * Sorting.
+ */
+
+XSLTPUBFUN void XSLTCALL               
+               xsltDocumentSortFunction        (xmlNodeSetPtr list);
+XSLTPUBFUN void XSLTCALL               
+               xsltSetSortFunc                 (xsltSortFunc handler);
+XSLTPUBFUN void XSLTCALL               
+               xsltSetCtxtSortFunc             (xsltTransformContextPtr ctxt,
+                                                xsltSortFunc handler);
+XSLTPUBFUN void XSLTCALL               
+               xsltDefaultSortFunction         (xsltTransformContextPtr ctxt,
+                                                xmlNodePtr *sorts,
+                                                int nbsorts);
+XSLTPUBFUN void XSLTCALL               
+               xsltDoSortFunction              (xsltTransformContextPtr ctxt,
+                                                xmlNodePtr * sorts,
+                                                int nbsorts);
+XSLTPUBFUN xmlXPathObjectPtr * XSLTCALL 
+               xsltComputeSortResult           (xsltTransformContextPtr ctxt,
+                                                xmlNodePtr sort);
+
+/*
+ * QNames handling.
+ */
+
+XSLTPUBFUN const xmlChar * XSLTCALL
+               xsltSplitQName                  (xmlDictPtr dict,
+                                                const xmlChar *name,
+                                                const xmlChar **prefix);
+XSLTPUBFUN const xmlChar * XSLTCALL 
+               xsltGetQNameURI                 (xmlNodePtr node,
+                                                xmlChar **name);
+
+XSLTPUBFUN const xmlChar * XSLTCALL
+               xsltGetQNameURI2                (xsltStylesheetPtr style,
+                                                xmlNodePtr node,
+                                                const xmlChar **name);
+
+/*
+ * Output, reuse libxml I/O buffers.
+ */
+XSLTPUBFUN int XSLTCALL                
+               xsltSaveResultTo                (xmlOutputBufferPtr buf,
+                                                xmlDocPtr result,
+                                                xsltStylesheetPtr style);
+XSLTPUBFUN int XSLTCALL                
+               xsltSaveResultToFilename        (const char *URI,
+                                                xmlDocPtr result,
+                                                xsltStylesheetPtr style,
+                                                int compression);
+XSLTPUBFUN int XSLTCALL                
+               xsltSaveResultToFile            (FILE *file,
+                                                xmlDocPtr result,
+                                                xsltStylesheetPtr style);
+XSLTPUBFUN int XSLTCALL                
+               xsltSaveResultToFd              (int fd,
+                                                xmlDocPtr result,
+                                                xsltStylesheetPtr style);
+XSLTPUBFUN int XSLTCALL             
+               xsltSaveResultToString          (xmlChar **doc_txt_ptr, 
+                                                 int * doc_txt_len, 
+                                                 xmlDocPtr result, 
+                                                 xsltStylesheetPtr style);
+
+/*
+ * XPath interface
+ */
+XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL
+               xsltXPathCompile                (xsltStylesheetPtr style,
+                                                const xmlChar *str);
+
+/*
+ * Profiling.
+ */
+XSLTPUBFUN void XSLTCALL               
+               xsltSaveProfiling               (xsltTransformContextPtr ctxt,
+                                                FILE *output);
+XSLTPUBFUN xmlDocPtr XSLTCALL  
+               xsltGetProfileInformation       (xsltTransformContextPtr ctxt);
+
+XSLTPUBFUN long XSLTCALL               
+               xsltTimestamp                   (void);
+XSLTPUBFUN void XSLTCALL               
+               xsltCalibrateAdjust             (long delta);
+
+/**
+ * XSLT_TIMESTAMP_TICS_PER_SEC:
+ *
+ * Sampling precision for profiling
+ */
+#define XSLT_TIMESTAMP_TICS_PER_SEC 100000l
+
+/*
+ * Hooks for the debugger.
+ */
+
+typedef enum {
+    XSLT_DEBUG_NONE = 0, /* no debugging allowed */
+    XSLT_DEBUG_INIT,
+    XSLT_DEBUG_STEP,
+    XSLT_DEBUG_STEPOUT,
+    XSLT_DEBUG_NEXT,
+    XSLT_DEBUG_STOP,
+    XSLT_DEBUG_CONT,
+    XSLT_DEBUG_RUN,
+    XSLT_DEBUG_RUN_RESTART,
+    XSLT_DEBUG_QUIT
+} xsltDebugStatusCodes;
+
+XSLTPUBVAR int xslDebugStatus;
+
+typedef void (*xsltHandleDebuggerCallback) (xmlNodePtr cur, xmlNodePtr node,
+                       xsltTemplatePtr templ, xsltTransformContextPtr ctxt);
+typedef int (*xsltAddCallCallback) (xsltTemplatePtr templ, xmlNodePtr source);
+typedef void (*xsltDropCallCallback) (void);
+
+XSLTPUBFUN void XSLTCALL
+               xsltSetDebuggerStatus           (int value);
+XSLTPUBFUN int XSLTCALL
+               xsltGetDebuggerStatus           (void);
+XSLTPUBFUN int XSLTCALL                
+               xsltSetDebuggerCallbacks        (int no, void *block);
+XSLTPUBFUN int XSLTCALL                
+               xslAddCall                      (xsltTemplatePtr templ,
+                                                xmlNodePtr source);
+XSLTPUBFUN void XSLTCALL               
+               xslDropCall                     (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __XML_XSLTUTILS_H__ */
+
+