Refactored xsltValueOf(). Changed to use xmlXPathCastToString() directly,
authorKasimier T. Buchcik <kbuchcik@src.gnome.org>
Fri, 14 Jul 2006 16:10:25 +0000 (16:10 +0000)
committerKasimier T. Buchcik <kbuchcik@src.gnome.org>
Fri, 14 Jul 2006 16:10:25 +0000 (16:10 +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:
  Refactored xsltValueOf(). Changed to use xmlXPathCastToString()
  directly, rather than creating an intermediate object with
  xmlXPathConvertString(). This now does not add a text-node to
  the result if the string is empty (this has impact on
  serialization, since an empty text-node is serialized as
  <foo></foo>, and now it will be serialized as <foo/>).
  Refactored other functions in transform.c:
  Mostly code cleanup/restructuring. Minimized number of
  function variables for instruction which eat up function stack
  memory when recursing templates (xsltIf(), xsltChoose(),
  xsltApplyTemplates(),  xsltCallTemplate()).
  Changed XSLT tests to use xmlXPathCompiledEvalToBoolean().
  Implemented redefinition checks at compilation-time and
  eliminating them at transformation time in the refactored code
  paths.
  Introduced the field @currentTemplateRule on xsltTransformContext to
  reflect the "Current Template Rule" as defined by the spec.
  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 by Libxslt.
  Added XML_COMMENT_NODE and XML_CDATA_SECTION_NODE to the macro
  IS_XSLT_REAL_NODE.
  Misc code cleanup/restructuring and everything else I already forgot.
  Refactored lifetime of temporary result tree fragments.
  Substituted all calls to the now deprecated xsltRegisterTmpRVT()
  for the new xsltRegisterLocalRVT().
  Fragments of xsl:variable and xsl:param are freed when the
  variable/pram is freed.
  Fragments created when evaluating a "select" of xsl:varible and
  xsl:param are also bound to the lifetime of the var/param.
  EXSLT's func:function now uses the following functions to let take
  care the transformation's garbage collector of returned tree
  fragments:
    xsltExtensionInstructionResultRegister(),
    xsltExtensionInstructionResultFinalize()
  Fixes:
  #339222 - xsl:param at invalid position inside an xsl:template is
            not catched
  #346015 - Non-declared caller-parameters are accepted
  #160400 - Compiles invalid XSLT; unbound variable accepted
  #308441 - namespaced parameters become unregistered
  #307103 - problem with proximity position in predicates of match
            patterns
  #328218 - problem with exsl:node-set() when converting strings
            to node sets
  #318088 - infinite recursion detection
  #321505 - Multiple contiguous CDATA in output
  #334493 - "--param" option does not have root context
  #114377 - weird func:result/xsl:variable/exsl:node-set interaction
  #150309 - Regression caused by fix for 142768

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 5c46b20..625f593 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,64 @@
+Fri Jul 14 17:55:42 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:
+         Refactored xsltValueOf(). Changed to use xmlXPathCastToString()
+         directly, rather than creating an intermediate object with
+         xmlXPathConvertString(). This now does not add a text-node to
+         the result if the string is empty (this has impact on
+         serialization, since an empty text-node is serialized as
+         <foo></foo>, and now it will be serialized as <foo/>).
+         Refactored other functions in transform.c:
+         Mostly code cleanup/restructuring. Minimized number of
+         function variables for instruction which eat up function stack
+         memory when recursing templates (xsltIf(), xsltChoose(),
+         xsltApplyTemplates(),  xsltCallTemplate()).
+         Changed XSLT tests to use xmlXPathCompiledEvalToBoolean().
+         Implemented redefinition checks at compilation-time and
+         eliminating them at transformation time in the refactored code
+         paths.
+         Introduced the field @currentTemplateRule on xsltTransformContext to
+         reflect the "Current Template Rule" as defined by the spec.
+         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 by Libxslt.
+         Added XML_COMMENT_NODE and XML_CDATA_SECTION_NODE to the macro
+         IS_XSLT_REAL_NODE.
+         Misc code cleanup/restructuring and everything else I already forgot.
+         Refactored lifetime of temporary result tree fragments.
+         Substituted all calls to the now deprecated xsltRegisterTmpRVT()
+         for the new xsltRegisterLocalRVT().
+         Fragments of xsl:variable and xsl:param are freed when the
+         variable/pram is freed.
+         Fragments created when evaluating a "select" of xsl:varible and
+         xsl:param are also bound to the lifetime of the var/param.
+         EXSLT's func:function now uses the following functions to let take
+         care the transformation's garbage collector of returned tree
+         fragments:
+           xsltExtensionInstructionResultRegister(),
+           xsltExtensionInstructionResultFinalize()
+         Fixes:
+         #339222 - xsl:param at invalid position inside an xsl:template is
+                   not catched
+         #346015 - Non-declared caller-parameters are accepted
+         #160400 - Compiles invalid XSLT; unbound variable accepted
+         #308441 - namespaced parameters become unregistered
+         #307103 - problem with proximity position in predicates of match
+                   patterns
+         #328218 - problem with exsl:node-set() when converting strings
+                   to node sets
+         #318088 - infinite recursion detection
+         #321505 - Multiple contiguous CDATA in output
+         #334493 - "--param" option does not have root context
+         #114377 - weird func:result/xsl:variable/exsl:node-set interaction
+         #150309 - Regression caused by fix for 142768
+
 Wed Jun 21 15:13:27 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
 
        * tests/docs/bug-54.xml tests/general/bug-54.out
index ffed71b..7b07ea2 100644 (file)
-#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) {
-    xmlChar *strval;
-    xmlNodePtr retNode;
-    xmlXPathObjectPtr ret;
-
-    if (nargs != 1) {
-       xmlXPathSetArityError(ctxt);
-       return;
-    }
-
-    if (xmlXPathStackIsNodeSet (ctxt)) {
-       xsltFunctionNodeSet (ctxt, nargs);
-       return;
-    }
-
-    strval = xmlXPathPopString (ctxt);
-    retNode = xmlNewDocText (NULL, strval);
-    ret = xmlXPathNewValueTree (retNode);
-    if (ret == NULL) {
-        xsltGenericError(xsltGenericErrorContext,
-                        "exsltNodeSetFunction: ret == NULL\n");
-    } else {
-        ret->type = XPATH_NODESET;
-    }
-
-    if (strval != NULL)
-       xmlFree (strval);
-
-    valuePush (ctxt, ret);
-}
-
-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);
-}
+#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
index 86db663..87ef8da 100644 (file)
-/*
- * 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)
-        xsltRegisterTmpRVT(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);
-
-}
+/*\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
index 51f7d44..4d904c9 100644 (file)
-#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? */
-};
-
-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);
-
-/**
- * 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, content = NULL;
-    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;
-       content = func->content;
-    }
-    else
-       paramNode = NULL;
-    if ((paramNode == NULL) && (func->nargs != 0)) {
-       xsltGenericError(xsltGenericErrorContext,
-                        "exsltFuncFunctionFunction: nargs != 0 and "
-                        "param == NULL\n");
-       return;
-    }
-
-    /* set params */
-    for (i = func->nargs; (i > nargs) && (paramNode != NULL); i--) {
-       paramNode = paramNode->prev;
-       if (content != NULL)
-           content = content->prev;
-    }
-    while ((i-- > 0) && (paramNode != NULL)) {
-       obj = valuePop(ctxt);
-       /* FIXME: this is a bit hackish */
-       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),
-                         content, NULL, params);
-    tctxt->insert = oldInsert;
-    tctxt->varsBase = oldBase; /* restore original scope */
-    if (params != NULL)
-       xsltFreeStackElemList(params);
-
-    if (data->error != 0)
-       return;
-
-    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);
-       return;
-    }
-    xmlFreeNode(fake);
-    valuePush(ctxt, ret);
-}
-
-
-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;
-    xmlNsPtr *oldNsList;
-    int oldNsNr;
-
-    /* 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) {
-       /* 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;
-       }
-       oldNsList = ctxt->xpathCtxt->namespaces;
-       oldNsNr = ctxt->xpathCtxt->nsNr;
-       ctxt->xpathCtxt->namespaces = comp->nsList;
-       ctxt->xpathCtxt->nsNr = comp->nsNr;
-       ret = xmlXPathCompiledEval(comp->select, ctxt->xpathCtxt);
-       ctxt->xpathCtxt->nsNr = oldNsNr;
-       ctxt->xpathCtxt->namespaces = oldNsList;
-       if (ret == NULL) {
-           xsltGenericError(xsltGenericErrorContext,
-                            "exsltFuncResultElem: ret == NULL\n");
-           return;
-       }
-    } 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;
-       }
-       xsltRegisterTmpRVT(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 */
-       }
-    } 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);
-}
+#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
index 6ad6d6c..484310a 100644 (file)
-#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) {
-        xsltRegisterTmpRVT(tctxt, container);
-        ret = xmlXPathNewNodeSet(NULL);
-        if (ret != NULL) {
-            ret->boolval = 0; /* Freeing is not handled there anymore */
-            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;
-    }
-
-    container = xsltCreateRVT(tctxt);
-    if (container != NULL) {
-        xsltRegisterTmpRVT(tctxt, container);
-        ret = xmlXPathNewNodeSet(NULL);
-        if (ret != NULL) {
-            ret->boolval = 0; /* Freeing is not handled there anymore */
-            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);
-}
+#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
index 46e365c..795e797 100644 (file)
-/*
- * 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 currentNode,
-                      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) || (currentNode == 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 instruction was no 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, currentNode, 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) {
-           ns = xsltTreeAcquireStoredNs(ctxt->document->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, currentNode, 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;
-}
+/*\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
index 75fd90d..c3d5400 100644 (file)
-/*
- * 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
- *
- * 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);
-}
-
+/*\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
index 871c8b9..f03d71c 100644 (file)
-/*
- * 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 xsltdoc;
-    xmlDocPtr doc;
-    xmlXPathContextPtr xptrctxt = NULL;
-    xmlXPathObjectPtr object = NULL;
-
-    tctxt = xsltXPathGetTransformContext(ctxt);
-    if (tctxt == NULL) {
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
-                          "document() : internal error tctxt == NULL\n");
-       valuePush(ctxt, xmlXPathNewNodeSet(NULL));
-       return;
-    } 
-       
-    uri = xmlParseURI((const char *) URI);
-    if (uri == NULL) {
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), 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);
-       xsltdoc = xsltLoadDocument(tctxt, URI);
-       xmlFree(URI);
-    } else
-       xsltdoc = xsltLoadDocument(tctxt, URI);
-    xmlFreeURI(uri);
-    
-    if (xsltdoc == NULL) {
-       if ((URI == NULL) ||
-           (URI[0] == '#') ||
-           (xmlStrEqual(tctxt->style->doc->URL, URI))) {
-           doc = tctxt->style->doc;
-       } else {
-           valuePush(ctxt, xmlXPathNewNodeSet(NULL));
-
-           if (fragment != NULL)
-               xmlFree(fragment);
-
-           return;
-       }
-    } else
-       doc = xsltdoc->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(xsltXPathGetTransformContext(ctxt), NULL, NULL,
-                          "document() : internal error xptrctxt == NULL\n");
-       goto out_fragment;
-    }
-
-    object = xmlXPtrEval(fragment, xptrctxt);
-#endif
-    xmlFree(fragment);
-       if (xptrctxt != NULL)
-               xmlXPathFreeContext(xptrctxt);
-
-    if (object == NULL)
-       goto out_fragment;
-       
-    switch (object->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(xsltXPathGetTransformContext(ctxt), NULL, NULL,
-                          "document() : XPointer does not select a node set: #%s\n", 
-                          fragment);
-       goto out_object;
-    }
-    
-    valuePush(ctxt, object);
-    return;
-
-out_object:
-    xmlXPathFreeObject(object);
-
-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){
-    xmlNodeSetPtr nodelist;
-    xmlXPathObjectPtr obj1, obj2;
-    xmlChar *key = NULL, *value;
-    const xmlChar *keyURI;
-    xsltTransformContextPtr tctxt;
-    xsltDocumentPtr oldDocumentPtr;
-    xmlDocPtr oldXPathDocPtr;
-    
-    if (nargs != 2) {
-       xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
-               "key() : expects two arguments\n");
-       ctxt->error = XPATH_INVALID_ARITY;
-       return;
-    }
-
-    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;
-    }
-    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 {
-       xmlChar *qname, *prefix;
-
-       /*
-        * 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(ctxt->context, prefix);
-               if (keyURI == NULL) {
-                   xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
-                       "key() : prefix %s is not bound\n", prefix);
-               }
-               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(xsltXPathGetTransformContext(ctxt), NULL, NULL,
-               "key() : invalid arg expecting a string\n");
-           ctxt->error = XPATH_INVALID_TYPE;
-           xmlXPathFreeObject(obj1);
-
-           return;
-       }
-       obj2 = valuePop(ctxt);
-       value = obj2->stringval;
-
-       tctxt = xsltXPathGetTransformContext(ctxt);
-       oldDocumentPtr = tctxt->document;
-       oldXPathDocPtr = tctxt->xpathCtxt->doc;
-       if ((ctxt->context->doc != NULL) &&
-                   (tctxt->document->doc != ctxt->context->doc)) {
-           /*
-            * The xpath context document needs to be changed.  If the
-            * current context document is a node-set, we must use an
-            * xsltDocument associated with the node-set, which may or
-            * may not currently exist.
-            */
-           if (xmlStrEqual((const xmlChar *)ctxt->context->doc->name,
-                       BAD_CAST " fake node libxslt")) {       /* node-set */
-               /*
-                * Check whether we already have an xsltDocument set up
-                */
-               if (ctxt->context->doc->_private == NULL)       /* nope */
-                   ctxt->context->doc->_private =
-                       xsltNewDocument(tctxt, ctxt->context->doc);
-               tctxt->document = ctxt->context->doc->_private;
-           }
-           else {
-               tctxt->document = xsltFindDocument(tctxt, ctxt->context->doc);
-               if (tctxt->document == NULL)
-                   tctxt->document = oldDocumentPtr;
-               else
-                   tctxt->xpathCtxt->doc = ctxt->context->doc;
-           }
-       }
-       nodelist = xsltGetKey(tctxt, key, keyURI, value);
-       tctxt->document = oldDocumentPtr;
-       tctxt->xpathCtxt->doc = oldXPathDocPtr;
-       valuePush(ctxt, xmlXPathWrapNodeSet(
-                       xmlXPathNodeSetMerge(NULL, nodelist)));
-    }
-
-
-    if (obj1 != NULL)
-       xmlXPathFreeObject(obj1);
-    if (obj2 != NULL)
-       xmlXPathFreeObject(obj2);
-    if (key != NULL)
-       xmlFree(key);
-}
-
-/**
- * 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);
-}
+/*\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
index 220b741..c054561 100644 (file)
-/*
- * 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
- *
- * Lookup a key
- *
- * 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);
-}
-
-/**
- * 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);
-}
-
-/**
- * xsltInitCtxtKey:
- * @ctxt: an XSLT transformation context
- * @doc:  an XSLT document
- * @keyd: the key definition
- *
- * Computes the key tables this key and for the current input document.
- */
-int
-xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc,
-               xsltKeyDefPtr keyd) {
-    int i;
-    xmlNodeSetPtr nodelist = NULL, keylist;
-    xmlXPathObjectPtr res = NULL;
-    xmlChar *str, **list;
-    xsltKeyTablePtr table;
-    int        oldPos, oldSize;
-    xmlNodePtr oldInst;
-    xmlNodePtr oldNode;
-    xsltDocumentPtr oldDoc;
-    xmlDocPtr oldXDoc;
-    int oldNsNr;
-    xmlNsPtr *oldNamespaces;
-
-    doc->nbKeysComputed++;
-    /*
-     * Evaluate the nodelist
-     */
-
-    oldXDoc= ctxt->xpathCtxt->doc;
-    oldPos = ctxt->xpathCtxt->proximityPosition;
-    oldSize = ctxt->xpathCtxt->contextSize;
-    oldNsNr = ctxt->xpathCtxt->nsNr;
-    oldNamespaces = ctxt->xpathCtxt->namespaces;
-    oldInst = ctxt->inst;
-    oldDoc = ctxt->document;
-    oldNode = ctxt->node;
-
-    if (keyd->comp == NULL)
-       goto error;
-    if (keyd->usecomp == NULL)
-       goto error;
-
-    ctxt->document = doc;
-    ctxt->xpathCtxt->doc = doc->doc;
-    ctxt->xpathCtxt->node = (xmlNodePtr) doc->doc;
-    ctxt->node = (xmlNodePtr) doc->doc;
-    /* TODO : clarify the use of namespaces in keys evaluation */
-    ctxt->xpathCtxt->namespaces = keyd->nsList;
-    ctxt->xpathCtxt->nsNr = keyd->nsNr;
-    ctxt->inst = keyd->inst;
-    res = xmlXPathCompiledEval(keyd->comp, ctxt->xpathCtxt);
-    ctxt->xpathCtxt->contextSize = oldSize;
-    ctxt->xpathCtxt->proximityPosition = oldPos;
-    ctxt->inst = oldInst;
-
-    if (res != NULL) {
-       if (res->type == XPATH_NODESET) {
-           nodelist = res->nodesetval;
-#ifdef WITH_XSLT_DEBUG_KEYS
-           if (nodelist != NULL)
-               XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
-                    "xsltInitCtxtKey: %s evaluates to %d nodes\n",
-                                keyd->match, nodelist->nodeNr));
-#endif
-       } else {
-#ifdef WITH_XSLT_DEBUG_KEYS
-           XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
-                "xsltInitCtxtKey: %s is not a node set\n", keyd->match));
-#endif
-           goto error;
-       }
-    } else {
-#ifdef WITH_XSLT_DEBUG_KEYS
-       XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltInitCtxtKey: %s evaluation failed\n", keyd->match));
-#endif
-       ctxt->state = XSLT_STATE_STOPPED;
-       goto error;
-    }
-
-    /*
-     * for each node in the list evaluate the key and insert the node
-     */
-    if ((nodelist == NULL) || (nodelist->nodeNr <= 0))
-       goto error;
-
-    /**
-     * Multiple key definitions for the same name are allowed, so
-     * we must check if the key is already present for this doc
-     */
-    table = (xsltKeyTablePtr) doc->keys;
-    while (table != NULL) {
-        if (xmlStrEqual(table->name, keyd->name) &&
-           (((keyd->nameURI == NULL) && (table->nameURI == NULL)) ||
-            ((keyd->nameURI != NULL) && (table->nameURI != NULL) &&
-             (xmlStrEqual(table->nameURI, keyd->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(keyd->name, keyd->nameURI);
-        if (table == NULL)
-           goto error;
-        table->next = doc->keys;
-        doc->keys = table;
-    }
-
-    for (i = 0;i < nodelist->nodeNr;i++) {
-       if (IS_XSLT_REAL_NODE(nodelist->nodeTab[i])) {
-           ctxt->node = nodelist->nodeTab[i];
-
-           list = xsltEvalXPathKeys(ctxt, keyd->usecomp, keyd);
-           if (list != NULL) {
-               int ix = 0;
-
-               str = list[ix++];
-               while (str != NULL) {
-#ifdef WITH_XSLT_DEBUG_KEYS
-                   XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
-                        "xsl:key : node associated to(%s,%s)\n",
-                                    keyd->name, str));
-#endif
-                   keylist = xmlHashLookup(table->keys, str);
-                   if (keylist == NULL) {
-                       keylist = xmlXPathNodeSetCreate(nodelist->nodeTab[i]);
-                       xmlHashAddEntry(table->keys, str, keylist);
-                   } else {
-                       xmlXPathNodeSetAdd(keylist, nodelist->nodeTab[i]);
-                   }
-                   switch (nodelist->nodeTab[i]->type) {
-                        case XML_ELEMENT_NODE:
-                        case XML_TEXT_NODE:
-                        case XML_CDATA_SECTION_NODE:
-                        case XML_PI_NODE:
-                        case XML_COMMENT_NODE:
-                           nodelist->nodeTab[i]->psvi = keyd;
-                           break;
-                        case XML_ATTRIBUTE_NODE: {
-                           xmlAttrPtr attr = (xmlAttrPtr) 
-                                             nodelist->nodeTab[i];
-                           attr->psvi = keyd;
-                           break;
-                       }
-                        case XML_DOCUMENT_NODE:
-                        case XML_HTML_DOCUMENT_NODE: {
-                           xmlDocPtr kdoc = (xmlDocPtr) 
-                                           nodelist->nodeTab[i];
-                           kdoc->psvi = keyd;
-                           break;
-                       }
-                       default:
-                           break;
-                   }
-                   xmlFree(str);
-                   str = list[ix++];
-               }
-               xmlFree(list);
-#ifdef WITH_XSLT_DEBUG_KEYS
-           } else {
-               XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext,
-                    "xsl:key : use %s failed to return strings\n",
-                                keyd->use));
-#endif
-           }
-       }
-    }
-
-error:
-    ctxt->document = oldDoc;
-    ctxt->xpathCtxt->doc = oldXDoc;
-    ctxt->xpathCtxt->nsNr = oldNsNr;
-    ctxt->xpathCtxt->namespaces = oldNamespaces;
-    ctxt->node = oldNode;
-    if (res != NULL)
-       xmlXPathFreeObject(res);
-    return(0);
-}
-
-/**
- * xsltInitCtxtKeys:
- * @ctxt:  an XSLT transformation context
- * @doc:  an XSLT document
- *
- * 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 doc) {
-    xsltStylesheetPtr style;
-    xsltKeyDefPtr keyd;
-
-    if ((ctxt == NULL) || (doc == NULL))
-       return;
-#ifdef WITH_XSLT_DEBUG_KEYS
-    if ((doc->doc != NULL) && (doc->doc->URL != NULL))
-       XSLT_TRACE(ctxt,XSLT_TRACE_KEYS,xsltGenericDebug(xsltGenericDebugContext, "Initializing keys on %s\n",
-                    doc->doc->URL));
-#endif
-    style = ctxt->style;
-    while (style != NULL) {
-       keyd = (xsltKeyDefPtr) style->keys;
-       while (keyd != NULL) {
-           xsltInitCtxtKey(ctxt, doc, keyd);
-
-           keyd = keyd->next;
-       }
-
-       style = xsltNextImport(style);
-    }
-}
-
-/**
- * xsltFreeDocumentKeys:
- * @doc: a XSLT document
- *
- * Free the keys associated to a document
- */
-void   
-xsltFreeDocumentKeys(xsltDocumentPtr doc) {
-    if (doc != NULL)
-        xsltFreeKeyTableList(doc->keys);
-}
-
+/*\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
index 0cb302d..5202630 100644 (file)
-/*
- * 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)
- *  - xsltApplyOneTemplateInt() (*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;
-}
+/*\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
index 4fd593a..7df37a2 100644 (file)
-/*
- * 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"
-
-#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 ((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,
-               xsltDocumentPtr document)
-{
-    xsltStylesheetPtr style, style2;
-    xsltKeyDefPtr keyd, keyd2;
-    xsltKeyTablePtr table;
-
-    if ((ctxt == NULL) || (document == NULL))
-       return(-1);
-    if (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) 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, document, keyd2);
-                           if (document->nbKeysComputed == ctxt->nbKeys)
-                               return(0);
-                       }
-                       keyd2 = keyd2->next;            
-                   }       
-                   style2 = xsltNextImport(style2);
-               }
-           }       
-           keyd = keyd->next;
-       }
-       style = xsltNextImport(style);
-    }
-    return(0);
-}
-#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->nbKeysComputed < ctxt->nbKeys))
-       {
-           /*
-           * Compute all remaining keys for this document.
-           *
-           * REVISIT TODO: I think this could be further optimized.        
-           */
-           xsltComputeAllKeys(ctxt, ctxt->document);
-
-           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);
-    }
-    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);
-}
-
+/*\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
index 344de8c..f85543e 100644 (file)
-/*
- * 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,
-           "xsl: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;
-
-       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 = xmlStrdup(URI);
-               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 = URI;
-               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;
-
-    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
-     */
-    prop = xsltGetCNsProp(style, inst, (const xmlChar *)"name", XSLT_NAMESPACE);
-    if (prop == NULL) {
-       xsltTransformError(NULL, style, inst,
-            "xsl:variable : 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:variable : could not compile select expression '%s'\n",
-                            comp->select);
-           if (style != NULL) style->errors++;
-       }
-       if (inst->children != NULL) {
-           xsltTransformError(NULL, style, inst,
-       "xsl:variable : content should be empty since select is present \n");
-           if (style != NULL) style->warnings++;
-       }
-    }
-}
-
-/**
- * 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 = xmlStrdup(URI);
-               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 */
+/*\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
index c20e287..1d82852 100644 (file)
-/*
- * 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
- * @currentNode:  the current node in the source tree
- * @parent:  the content parent
- *
- * Evaluate a template string value, i.e. the parent list is interpreted
- * as template content and the resulting tree string value is returned
- * This is needed for example by xsl:comment and xsl:processing-instruction
- *
- * Returns the computed string value or NULL, must be deallocated by the
- *    caller.
- */
-xmlChar *
-xsltEvalTemplateString(xsltTransformContextPtr ctxt,
-                      xmlNodePtr currentNode,
-                      xmlNodePtr parent)
-{
-    xmlNodePtr oldInsert, insert = NULL;
-    xmlChar *ret;
-
-    if ((ctxt == NULL) || (currentNode == NULL) || (parent == NULL))
-       return(NULL);
-
-    if (parent->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, currentNode,
-               "Failed to create temporary node\n");
-       return(NULL);
-    }
-    oldInsert = ctxt->insert;
-    ctxt->insert = insert;
-    /* OPTIMIZE TODO: if parent->children consists only of text-nodes. */
-    xsltApplyOneTemplate(ctxt, currentNode, parent->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 xsltApplyOneTemplateInt() (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);
-}
-
-
+/*\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
index b9a6e8f..54907e1 100644 (file)
@@ -1,77 +1,77 @@
-/*
- * 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 node,
-                                                xmlNodePtr parent);
-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__ */
-
+/*\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
index 76b5af8..ed1bfc0 100644 (file)
-/*
- * 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
-
-static void
-xsltApplyOneTemplateInt(xsltTransformContextPtr ctxt, xmlNodePtr node,
-                     xmlNodePtr list, xsltTemplatePtr templ,
-                     xsltStackElemPtr params, int notcur);
-
-int xsltMaxDepth = 5000;
-
-/*
- * 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);
-
-/**
- * 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);
-}
-/**
- * varsPush:
- * @ctxt: the transformation context
- * @value:  the variable to push on the stack
- *
- * Push a variable on the stack
- *
- * Returns the new index in the stack or 0 in case of error
- */
-static int
-varsPush(xsltTransformContextPtr ctxt, xsltStackElemPtr value)
-{
-    if (ctxt->varsMax == 0) {
-        ctxt->varsMax = 4;
-        ctxt->varsTab =
-            (xsltStackElemPtr *) xmlMalloc(ctxt->varsMax *
-                                           sizeof(ctxt->varsTab[0]));
-        if (ctxt->varsTab == NULL) {
-            xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
-            return (0);
-        }
-    }
-    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 (0);
-        }
-    }
-    ctxt->varsTab[ctxt->varsNr] = value;
-    ctxt->vars = value;
-    return (ctxt->varsNr++);
-}
-/**
- * varsPop:
- * @ctxt: the transformation context
- *
- * Pop a variable value from the stack
- *
- * Returns the stored variable value
- */
-static xsltStackElemPtr
-varsPop(xsltTransformContextPtr ctxt)
-{
-    xsltStackElemPtr ret;
-
-    if (ctxt->varsNr <= 0)
-        return (0);
-    ctxt->varsNr--;
-    if (ctxt->varsNr > 0)
-        ctxt->vars = ctxt->varsTab[ctxt->varsNr - 1];
-    else
-        ctxt->vars = (xsltStackElemPtr) 0;
-    ret = ctxt->varsTab[ctxt->varsNr];
-    ctxt->varsTab[ctxt->varsNr] = 0;
-    return (ret);
-}
-/**
- * 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             *
- *                                                                     *
- ************************************************************************/
-
-/**
- * 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));
-
-    /*
-     * 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 = 5;
-    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;
-    }
-    cur->xpathCtxt->proximityPosition = 0;
-    cur->xpathCtxt->contextSize = 0;
-    /*
-    * 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);
-    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.
- *
- * Create a text node
- *
- * Returns: a new xmlNodePtr, or NULL in case of error.
- */
-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
-
-    /* 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))))
-    {
-       if ((target != NULL) && (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) {
-       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 {
-       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
- *
- * Do a copy of a text node
- *
- * Returns: a new xmlNodePtr, or NULL in case of error.
- */
-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
-
-    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)))) {
-       /* 
-       * 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.
-       */
-       copy = xmlNewCDataBlock(ctxt->output, cur->content,
-                               xmlStrlen(cur->content));
-       ctxt->lasttext = NULL;
-    } 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
-        */
-       return(xsltAddTextString(ctxt, target->last, cur->content,
-           xmlStrlen(cur->content)));
-    } 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)
-           return NULL;        
-       if (cur->name == xmlStringTextNoenc)
-           copy->name = xmlStringTextNoenc;
-       
-       /* OPTIMIZE TODO: get rid of xmlDictOwns() in safe cases;
-        *  e.g. attribute values don't need the lookup.
-        *
-        * Must confirm that content is in dict (bug 302821)
-        * TODO: Check if bug 302821 still applies here.
-        */
-       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)
-           return NULL;
-       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");
-    }
-    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:
- *   xsltApplyOneTemplateInt() (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++;
-           xsltApplyOneTemplateInt(ctxt, node, child->children, NULL, NULL, 0);
-       }
-       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
-                   xsltApplyOneTemplateInt(ctxt, cur, template->content,
-                                        template, params, 0);
-               } 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;
-                   xsltApplyOneTemplateInt(ctxt, cur, template->content,
-                                        template, params, 0);
-               } 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;
-                   xsltApplyOneTemplateInt(ctxt, cur, template->content,
-                                        template, params, 0);
-               }
-               break;
-           default:
-               break;
-       }
-       cur = cur->next;
-    }
-    ctxt->xpathCtxt->contextSize = oldSize;
-    ctxt->xpathCtxt->proximityPosition = oldPos;
-}
-
-/**
- * xsltProcessOneNode:
- * @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.
- */
-void
-xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
-                  xsltStackElemPtr params) {
-    xsltTemplatePtr template;
-    xmlNodePtr oldNode;
-    
-    template = xsltGetTemplate(ctxt, node, NULL);
-    /*
-     * If no template is found, apply the default rule.
-     */
-    if (template == NULL) {
-#ifdef WITH_XSLT_DEBUG_PROCESS
-       if (node->type == XML_DOCUMENT_NODE) {
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltProcessOneNode: no template found for /\n"));
-       } else if (node->type == XML_CDATA_SECTION_NODE) {
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltProcessOneNode: no template found for CDATA\n"));
-       } else if (node->type == XML_ATTRIBUTE_NODE) {
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltProcessOneNode: no template found for attribute %s\n",
-                            ((xmlAttrPtr) node)->name));
-       } else  {
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltProcessOneNode: no template found for %s\n", node->name));
-        }
-#endif
-       oldNode = ctxt->node;
-       ctxt->node = node;
-       xsltDefaultProcessOneNode(ctxt, node, params);
-       ctxt->node = oldNode;
-       return;
-    }
-
-    if (node->type == XML_ATTRIBUTE_NODE) {
-#ifdef WITH_XSLT_DEBUG_PROCESS
-       XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltProcessOneNode: applying template '%s' for attribute %s\n",
-                        template->match, node->name));
-#endif
-       xsltApplyOneTemplateInt(ctxt, node, template->content, template, params, 0);
-    } else {
-#ifdef WITH_XSLT_DEBUG_PROCESS
-       if (node->type == XML_DOCUMENT_NODE) {
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltProcessOneNode: applying template '%s' for /\n",
-                            template->match));
-       } else {
-           XSLT_TRACE(ctxt,XSLT_TRACE_PROCESS_NODE,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltProcessOneNode: applying template '%s' for %s\n",
-                            template->match, node->name));
-        }
-#endif
-       xsltApplyOneTemplateInt(ctxt, node, template->content, template, params, 0);
-    }
-}
-
-/**
- * xsltApplyOneTemplate:
- * @ctxt:  a XSLT process context
- * @node:  the node in the source tree.
- * @list:  the template replacement nodelist
- * @templ: if is this a real template processing, the template processed
- * @params:  a set of parameters for the template or NULL
- *
- * Process the apply-templates node on the source node, if params are passed
- * they are pushed on the variable stack but not popped, it's left to the
- * caller to handle them after return (they may be reused).
- */
-void
-xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
-                     xmlNodePtr list, xsltTemplatePtr templ,
-                     xsltStackElemPtr params)
-{
-    xsltApplyOneTemplateInt(ctxt, node, list, templ, params, 0);
-}
-
-/**
- * xsltApplyOneTemplateInt:
- * @ctxt:  a XSLT process context
- * @node:  the node in the source tree.
- * @list:  the template replacement nodelist
- * @templ: if is this a real template processing, the template processed
- * @params:  a set of parameters for the template or NULL
- * @notcur: flag to show current template rule doesn't change
- *
- * See above description for xsltApplyOneTemplate.  Internally there is
- * an additional parameter 'notcur'.  When this parameter is non-zero,
- * ctxt->templ is not changed (i.e. templPush and tempPop are not called).
- * This is used by xsltCallTemplate in order to meet the XSLT spec (5.6)
- * requirement that the "current template rule" should not be changed
- * (bug 157859).
- */
-static void
-xsltApplyOneTemplateInt(xsltTransformContextPtr ctxt, xmlNodePtr node,
-                     xmlNodePtr list, xsltTemplatePtr templ,
-                     xsltStackElemPtr params, int notcur)
-{
-    xmlNodePtr cur = NULL, insert, copy = NULL;
-    xmlNodePtr oldInsert;
-    xmlNodePtr oldCurrent = NULL;
-    xmlNodePtr oldInst = NULL;
-    int oldBase;
-    xmlDocPtr tmpRVT = NULL;
-#ifdef XSLT_REFACTORED
-    xsltStylePreCompPtr info;
-#endif
-
-    int level = 0;
-
-#ifdef WITH_DEBUGGER
-    int addCallResult = 0;
-    xmlNodePtr debugedNode = NULL;
-#endif
-    long start = 0;
-
-    if (ctxt == NULL) return;
-
-#ifdef WITH_DEBUGGER
-    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;
-        }
-
-        if (templ) {
-            xslHandleDebugger(templ->elem, node, templ, ctxt);
-            debugedNode = templ->elem;
-        } else if (list) {
-            xslHandleDebugger(list, node, templ, ctxt);
-            debugedNode = list;
-        } else if (ctxt->inst) {
-            xslHandleDebugger(ctxt->inst, node, templ, ctxt);
-            debugedNode = ctxt->inst;
-        }
-    }
-#endif
-
-    if (list == NULL)
-        return;
-    CHECK_STOPPED;
-
-    if ((ctxt->templNr >= xsltMaxDepth) ||
-        (ctxt->varsNr >= 5 * xsltMaxDepth)) {
-        xsltTransformError(ctxt, NULL, list,
-                         "xsltApplyOneTemplate: loop found ???\n");
-        xsltGenericError(xsltGenericErrorContext,
-                         "try increasing xsltMaxDepth (--maxdepth)\n");
-        xsltDebug(ctxt, node, list, NULL);
-        return;
-    }
-
-    /*
-     * stack saves, beware ordering of operations counts
-     */
-    oldInsert = insert = ctxt->insert;
-    oldInst = ctxt->inst;
-    oldCurrent = ctxt->node;
-    varsPush(ctxt, params);
-    oldBase = ctxt->varsBase;   /* only needed if templ != NULL */
-    if (templ != NULL) {
-        ctxt->varsBase = ctxt->varsNr - 1;
-        ctxt->node = node;
-        if (ctxt->profile) {
-            templ->nbCalls++;
-            start = xsltTimestamp();
-            profPush(ctxt, 0);
-        }
-       tmpRVT = ctxt->tmpRVT;
-       ctxt->tmpRVT = NULL;
-       if (!notcur)
-            templPush(ctxt, templ);
-#ifdef WITH_XSLT_DEBUG_PROCESS
-        if (templ->name != NULL)
-            XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
-                             "applying template '%s'\n", templ->name));
-#endif
-    }
-
-    /*
-     * Insert all non-XSLT nodes found in the template
-     */
-    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,
-                             "xsltApplyOneTemplateInt: insert == NULL !\n"));
-#endif
-            goto error;
-        }
-#ifdef WITH_DEBUGGER
-        if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (debugedNode != cur))
-            xslHandleDebugger(cur, node, 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, node, cur);
-                   goto skip_children;
-               }                                
-               /*
-               * Something really went wrong:
-               */
-               xsltTransformError(ctxt, NULL, cur,
-                   "Internal error in xsltApplyOneTemplateInt(): "
-                   "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,
-                   "xsltApplyOneTemplateInt: 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 xsltApplyOneTemplateInt(): "
-                       "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 xsltApplyOneTemplateInt(): "
-                                   "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."
-               * TODO: Refactor this, since it still uses ns-aliasing.
-               * 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, node, cur)) {
-                       xsltTransformError(ctxt, NULL, cur,
-                           "The is no fallback behaviour defined for "
-                           "the unknown XSLT element '%s'.\n",
-                           cur->name);
-                   }                   
-                   ctxt->insert = oldInsert;
-                   goto skip_children;
-               }
-               /*
-               * Execute the XSLT instruction.
-               */
-               if (info->func != NULL) {
-                   ctxt->insert = insert;
-                   info->func(ctxt, node, cur, (xsltElemPreCompPtr) info);
-                   ctxt->insert = oldInsert;
-                   goto skip_children;
-               }
-               /*
-               * Some XSLT instructions need custom execution.
-               */               
-               if (info->type == XSLT_FUNC_VARIABLE) {
-                   if (level != 0) {
-                       /*
-                       * Build a new subframe and skip all the nodes
-                       * at that level.
-                       */
-                       ctxt->insert = insert;
-                       xsltApplyOneTemplateInt(ctxt, node, cur, NULL, NULL, 0);
-                       while (cur->next != NULL)
-                           cur = cur->next;
-                       ctxt->insert = oldInsert;
-                   } else {
-                       xsltParseStylesheetVariable(ctxt, cur);
-                   }
-               } else if (info->type == XSLT_FUNC_PARAM) {
-                   xsltParseStylesheetParam(ctxt, cur);
-               } else if (info->type == XSLT_FUNC_MESSAGE) {
-                   /*
-                   * TODO: Won't be hit, since we don't compile xsl:message.
-                   */
-                   xsltMessage(ctxt, node, cur);
-               } else {
-                   xsltGenericError(xsltGenericErrorContext,
-                       "Internal error in xsltApplyOneTemplateInt(): "
-                       "Don't know how to process the 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,
-                           "xsltApplyOneTemplate: unknown extension %s\n",
-                           cur->name));
-#endif
-                   ctxt->insert = insert;
-                   if (!xsltApplyFallbacks(ctxt, node, 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,
-                       "xsltApplyOneTemplate: extension construct %s\n",
-                       cur->name));
-#endif             
-                   ctxt->insert = insert;
-                   func(ctxt, node, cur, cur->psvi);
-                   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,
-                   "xsltApplyOneTemplateInt: copy unescaped text '%s'\n",
-                   cur->content));
-            } else {
-                XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,
-                   xsltGenericDebug(xsltGenericDebugContext,
-                   "xsltApplyOneTemplateInt: 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, node, cur);
-                } else {
-                    /*
-                     * That's an error try to apply one of the fallback cases
-                     */
-                    ctxt->insert = insert;
-                    if (!xsltApplyFallbacks(ctxt, node, cur)) {
-                        xsltGenericError(xsltGenericErrorContext,
-                           "xsltApplyOneTemplate: %s was not compiled\n",
-                           cur->name);
-                    }
-                    ctxt->insert = oldInsert;
-                }
-                goto skip_children;
-            }
-
-            if (info->func != NULL) {
-                ctxt->insert = insert;
-                info->func(ctxt, node, cur, (xsltElemPreCompPtr) info);
-                ctxt->insert = oldInsert;
-                goto skip_children;
-            }
-
-            if (IS_XSLT_NAME(cur, "variable")) {
-               if (level != 0) {
-                   /*
-                    * Build a new subframe and skip all the nodes
-                    * at that level.
-                    */
-                   ctxt->insert = insert;
-                   xsltApplyOneTemplateInt(ctxt, node, cur, NULL, NULL, 0);
-                   while (cur->next != NULL)
-                       cur = cur->next;
-                   ctxt->insert = oldInsert;
-               } else {
-                   xsltParseStylesheetVariable(ctxt, cur);
-               }
-            } else if (IS_XSLT_NAME(cur, "param")) {
-                xsltParseStylesheetParam(ctxt, cur);
-            } else if (IS_XSLT_NAME(cur, "message")) {
-                xsltMessage(ctxt, node, cur);
-            } else {
-                xsltGenericError(xsltGenericErrorContext,
-                   "xsltApplyOneTemplate: problem with xsl:%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,
-                                 "xsltApplyOneTemplate: copy CDATA text %s\n",
-                                 cur->content));
-            } else if (cur->name == xmlStringTextNoenc) {
-                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
-                                 "xsltApplyOneTemplate: copy unescaped text %s\n",
-                                 cur->content));
-            } else {
-                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
-                                 "xsltApplyOneTemplate: 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;
-
-            /*
-             * 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,
-                                 "xsltApplyOneTemplate: 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;
-                        xsltApplyOneTemplateInt(ctxt, node, child->children,
-                                             NULL, NULL, 0);
-                    }
-                    child = child->next;
-                }
-
-                if (!found) {
-                    xsltTransformError(ctxt, NULL, cur,
-                                     "xsltApplyOneTemplate: failed to find extension %s\n",
-                                     cur->name);
-                }
-            } else {
-#ifdef WITH_XSLT_DEBUG_PROCESS
-                XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
-                                 "xsltApplyOneTemplate: extension construct %s\n",
-                                 cur->name));
-#endif
-
-                ctxt->insert = insert;
-                function(ctxt, node, cur, cur->psvi);
-                ctxt->insert = oldInsert;
-            }
-            goto skip_children;
-        } else if (cur->type == XML_ELEMENT_NODE) {
-#ifdef WITH_XSLT_DEBUG_PROCESS
-            XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
-                             "xsltApplyOneTemplate: copy node %s\n",
-                             cur->name));
-#endif
-            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);
-            }
-        }
-#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--;
-            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:
-    ctxt->node = oldCurrent;
-    ctxt->inst = oldInst;
-    ctxt->insert = oldInsert;
-    if (params == NULL)
-        xsltFreeStackElemList(varsPop(ctxt));
-    else {
-        xsltStackElemPtr p, tmp = varsPop(ctxt);
-
-        if (tmp != params) {
-            p = tmp;
-            while ((p != NULL) && (p->next != params))
-                p = p->next;
-            if (p == NULL) {
-                xsltFreeStackElemList(tmp);
-            } else {
-                p->next = NULL;
-                xsltFreeStackElemList(tmp);
-            }
-        }
-    }
-    if (templ != NULL) {
-        ctxt->varsBase = oldBase;
-       if (!notcur)
-            templPop(ctxt);
-       /*
-        * Free up all the unreferenced RVT
-        * Also set any global variables instantiated
-        * using them, to be "not yet computed".
-        */
-       if (ctxt->tmpRVT != NULL) {
-           xsltStackElemPtr elem;
-           xmlDocPtr tmp = ctxt->tmpRVT, next;
-            while (tmp != NULL) {
-               elem = (xsltStackElemPtr)tmp->psvi;
-               if (elem != NULL) {
-                   elem->computed = 0;
-                   xmlXPathFreeObject(elem->value);
-               }
-               next = (xmlDocPtr) tmp->next;
-               if (tmp->_private != NULL) {
-                   xsltFreeDocumentKeys(tmp->_private);
-                   xmlFree(tmp->_private);
-               }
-               xmlFreeDoc(tmp);
-               tmp = next;
-           }
-       }
-       ctxt->tmpRVT = tmpRVT;
-        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
-}
-
-/************************************************************************
- *                                                                     *
- *                 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;
-    xsltApplyOneTemplateInt(ctxt, node, inst->children, NULL, NULL, 0);
-
-    /*
-     * 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:
-           xsltApplyOneTemplateInt(ctxt, ctxt->node, inst->children,
-                                NULL, NULL, 0);
-           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)
-       xsltApplyOneTemplateInt(ctxt, ctxt->node, inst->children,
-           NULL, NULL, 0);
-
-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;
-    int oldProximityPosition, oldContextSize;
-    int oldNsNr;
-    xmlNsPtr *oldNamespaces;
-
-    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
-
-    /*
-    * Set up the XPath evaluation context.
-    */
-    oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
-    oldContextSize = ctxt->xpathCtxt->contextSize;
-    oldNsNr = ctxt->xpathCtxt->nsNr;
-    oldNamespaces = ctxt->xpathCtxt->namespaces;
-    ctxt->xpathCtxt->node = 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
-    /*
-    * Evaluate the "select" expression.
-    */
-    res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt);
-    /*
-    * Revert the XPath evaluation context to previous state.
-    */
-    ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
-    ctxt->xpathCtxt->contextSize = oldContextSize;
-    ctxt->xpathCtxt->nsNr = oldNsNr;
-    ctxt->xpathCtxt->namespaces = oldNamespaces;
-
-    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>)
-           * --------------------
-           */
-#ifdef WITH_XSLT_DEBUG_PROCESS
-           XSLT_TRACE(ctxt,XSLT_TRACE_COPY_OF,xsltGenericDebug(xsltGenericDebugContext,
-                "xsltCopyOf: result is a result tree fragment\n"));
-#endif
-           /*
-           * TODO: Is list->nodeTab[0] is an xmlDocPtr?
-           */
-           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 {
-           /* Convert to a string. */
-           res = xmlXPathConvertString(res);
-           if ((res != NULL) && (res->type == XPATH_STRING)) {
-#ifdef WITH_XSLT_DEBUG_PROCESS
-               XSLT_TRACE(ctxt,XSLT_TRACE_COPY_OF,xsltGenericDebug(xsltGenericDebugContext,
-                    "xsltCopyOf: result %s\n", res->stringval));
-#endif
-               /* Append content as text node. */
-               xsltCopyTextString(ctxt, ctxt->insert, res->stringval, 0);
-           }
-       }
-    } 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;
-    int oldProximityPosition, oldContextSize;
-    int oldNsNr;
-    xmlNsPtr *oldNamespaces;
-
-    if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
-       return;
-    if ((comp == NULL) || (comp->select == NULL) || (comp->comp == NULL)) {
-       xsltTransformError(ctxt, NULL, inst,
-            "xsl:value-of : compilation failed\n");
-       return;
-    }
-
-#ifdef WITH_XSLT_DEBUG_PROCESS
-    XSLT_TRACE(ctxt,XSLT_TRACE_VALUE_OF,xsltGenericDebug(xsltGenericDebugContext,
-        "xsltValueOf: select %s\n", comp->select));
-#endif
-
-    oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
-    oldContextSize = ctxt->xpathCtxt->contextSize;
-    oldNsNr = ctxt->xpathCtxt->nsNr;
-    oldNamespaces = ctxt->xpathCtxt->namespaces;
-    ctxt->xpathCtxt->node = 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);
-    ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
-    ctxt->xpathCtxt->contextSize = oldContextSize;
-    ctxt->xpathCtxt->nsNr = oldNsNr;
-    ctxt->xpathCtxt->namespaces = oldNamespaces;
-    if (res != NULL) {
-       if (res->type != XPATH_STRING)
-           res = xmlXPathConvertString(res);
-       if (res->type == XPATH_STRING) {
-           copy = xsltCopyTextString(ctxt, ctxt->insert, res->stringval,
-                              comp->noescape);
-       }
-    } else {
-       ctxt->state = XSLT_STATE_STOPPED;
-    }
-    if (copy == NULL) {
-       if ((res == NULL) || (res->stringval != NULL)) {
-           xsltTransformError(ctxt, NULL, inst,
-               "xsltValueOf: text copy failed\n");
-       }
-    }
-#ifdef WITH_XSLT_DEBUG_PROCESS
-    else
-       XSLT_TRACE(ctxt,XSLT_TRACE_VALUE_OF,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltValueOf: result %s\n", res->stringval));
-#endif
-    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:  a XSLT process context
- * @node:  the node in the source tree.
- * @inst:  the xslt apply-imports node
- * @comp:  precomputed information
- *
- * Process the xslt apply-imports node on the source node
- */
-void
-xsltApplyImports(xsltTransformContextPtr ctxt, xmlNodePtr node,
-                xmlNodePtr inst,
-                xsltStylePreCompPtr comp ATTRIBUTE_UNUSED) {
-    xsltTemplatePtr template;
-
-    if ((ctxt->templ == NULL) || (ctxt->templ->style == NULL)) {
-       xsltTransformError(ctxt, NULL, inst,
-            "xsl:apply-imports : internal error no current template\n");
-       return;
-    }
-    template = xsltGetTemplate(ctxt, node, ctxt->templ->style);
-    if (template != NULL) {
-       xsltApplyOneTemplateInt(ctxt, node, template->content, template, NULL, 0);
-    }
-}
-
-/**
- * xsltCallTemplate:
- * @ctxt:  a XSLT process context
- * @node:  the node in the source tree.
- * @inst:  the xslt call-template node
- * @comp:  precomputed information
- *
- * Process the xslt call-template node 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
-    xmlNodePtr cur = NULL;
-    xsltStackElemPtr params = NULL, param;
-
-    if (ctxt->insert == NULL)
-       return;
-    if (comp == NULL) {
-       xsltTransformError(ctxt, NULL, inst,
-            "xsl:call-template : compilation failed\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,
-                       "xsl:call-template : template %s:%s not found\n",
-                       comp->ns, comp->name);
-           } else {
-               xsltTransformError(ctxt, NULL, inst,
-                       "xsl:call-template : template %s 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
-
-    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.
-       */
-#ifdef XSLT_REFACTORED
-       if (IS_XSLT_ELEM_FAST(cur)) {
-#else
-       if (IS_XSLT_ELEM(cur)) {
-#endif
-           if (IS_XSLT_NAME(cur, "with-param")) {
-               param = xsltParseStylesheetCallerParam(ctxt, cur);
-               if (param != NULL) {
-                   param->next = params;
-                   params = 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
-     * Set the "notcur" flag to abide by Section 5.6 of the spec
-     */
-    xsltApplyOneTemplateInt(ctxt, node, comp->templ->content, comp->templ, params, 1);
-    if (params != NULL)
-       xsltFreeStackElemList(params);
-
-#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 process context
- * @node:  the node in the source tree.
- * @inst:  the apply-templates node
- * @comp:  precomputed information
- *
- * Process the apply-templates node on the source node
- */
-void
-xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
-                  xmlNodePtr inst, xsltStylePreCompPtr castedComp)
-{
-#ifdef XSLT_REFACTORED
-    xsltStyleItemApplyTemplatesPtr comp =
-       (xsltStyleItemApplyTemplatesPtr) castedComp;
-#else
-    xsltStylePreCompPtr comp = castedComp;
-#endif
-    xmlNodePtr cur, delete = NULL, oldNode;
-    xmlXPathObjectPtr res = NULL;
-    xmlNodeSetPtr list = NULL, oldList;
-    int i, oldProximityPosition, oldContextSize;
-    const xmlChar *oldMode, *oldModeURI;
-    xsltStackElemPtr params = NULL, param;
-    int nbsorts = 0;
-    xmlNodePtr sorts[XSLT_MAX_SORT];
-    xmlDocPtr oldXDocPtr;
-    xsltDocumentPtr oldCDocPtr;
-    int oldNsNr;
-    xmlNsPtr *oldNamespaces;
-
-    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
-
-    /*
-     * Get mode if any
-     */
-    oldNode = ctxt->node;
-    oldMode = ctxt->mode;
-    oldModeURI = ctxt->modeURI;
-    ctxt->mode = comp->mode;
-    ctxt->modeURI = comp->modeURI;
-
-    /*
-     * 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
-     */
-    oldXDocPtr = ctxt->xpathCtxt->doc;
-    oldCDocPtr = ctxt->document;
-    oldContextSize = ctxt->xpathCtxt->contextSize;
-    oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
-    oldNsNr = ctxt->xpathCtxt->nsNr;
-    oldNamespaces = ctxt->xpathCtxt->namespaces;
-    oldList = ctxt->nodeList;
-
-    if (comp->select != 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
-
-       ctxt->xpathCtxt->node = 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);
-       ctxt->xpathCtxt->contextSize = oldContextSize;
-       ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
-       if (res != NULL) {
-           if (res->type == XPATH_NODESET) {
-               list = res->nodesetval;
-               res->nodesetval = NULL;
-               /*
-                In order to take care of potential keys we need to
-                do some extra work in the case of an RVT converted
-                into a nodeset (e.g. exslt:node-set())
-                We create a "pseudo-doc" (if not already created) and
-                store it's pointer into _private.  This doc, together
-                with the keyset, will be freed when the RVT is freed.
-               */
-               if ((list != NULL) && (ctxt->document->keys != NULL)) {
-                   if ((list->nodeNr != 0) &&
-                       (list->nodeTab[0]->doc != NULL) &&
-
-                       XSLT_IS_RES_TREE_FRAG(list->nodeTab[0]->doc) &&
-
-                       (list->nodeTab[0]->doc->_private == NULL)) {
-                           list->nodeTab[0]->doc->_private = xsltNewDocument(
-                               ctxt, list->nodeTab[0]->doc);
-                       if (list->nodeTab[0]->doc->_private == NULL) {
-                           xsltTransformError(ctxt, NULL, inst,
-                   "xsltApplyTemplates : failed to allocate subdoc\n");
-                       }
-
-                       ctxt->document = list->nodeTab[0]->doc->_private;
-                   }
-
-               }
-            } else {
-               list = NULL;
-            }
-       } else {
-           ctxt->state = XSLT_STATE_STOPPED;
-       }
-       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 error;
-       }
-    } else {
-       /*
-        * Build an XPath nodelist with the children
-        */
-       list = xmlXPathNodeSetCreate(NULL);
-       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"))) {
-                           delete = 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
-                   delete = cur;
-           }
-           cur = cur->next;
-           if (delete != NULL) {
-#ifdef WITH_XSLT_DEBUG_PROCESS
-               XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
-                    "xsltApplyTemplates: removing ignorable blank cur\n"));
-#endif
-               xmlUnlinkNode(delete);
-               xmlFreeNode(delete);
-               delete = 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
-
-    ctxt->nodeList = list;
-    ctxt->xpathCtxt->contextSize = list->nodeNr;
-
-    /* 
-     * handle (or skip) the xsl:sort and xsl:with-param
-     */
-    cur = inst->children;
-    while (cur!=NULL) {
-#ifdef WITH_DEBUGGER
-        if (ctxt->debugStatus != XSLT_DEBUG_NONE)
-#ifdef XSLT_REFACTORED
-            xslHandleDebugger(cur, node, NULL, ctxt);
-#else
-           /* TODO: Isn't comp->templ always NULL for apply-template? */
-            xslHandleDebugger(cur, node, comp->templ, ctxt);
-#endif
-#endif
-        if (ctxt->state == XSLT_STATE_STOPPED) break;
-#ifdef XSLT_REFACTORED
-       if (IS_XSLT_ELEM_FAST(cur)) {
-#else
-        if (IS_XSLT_ELEM(cur)) {
-#endif
-            if (IS_XSLT_NAME(cur, "with-param")) {
-                param = xsltParseStylesheetCallerParam(ctxt, cur);
-               if (param != NULL) {
-                   param->next = params;
-                   params = param;
-               }
-           } else if (IS_XSLT_NAME(cur, "sort")) {
-               if (nbsorts >= XSLT_MAX_SORT) {
-                   xsltGenericError(xsltGenericErrorContext,
-                       "xsl:apply-template: %s too many sort\n", node->name);
-               } else {
-                   sorts[nbsorts++] = cur;
-               }
-           } else {
-               xsltGenericError(xsltGenericErrorContext,
-                   "xsl:apply-template: misplaced xsl:%s\n", cur->name);
-           }
-        } else {
-            xsltGenericError(xsltGenericErrorContext,
-                 "xsl:apply-template: misplaced %s element\n", cur->name);
-        }
-        cur = cur->next;
-    }
-
-    if (nbsorts > 0) {
-       xsltDoSortFunction(ctxt, sorts, nbsorts);
-    }
-
-    for (i = 0;i < list->nodeNr;i++) {
-       ctxt->node = list->nodeTab[i];
-       ctxt->xpathCtxt->proximityPosition = i + 1;
-       /* For a 'select' nodeset, need to check if document has changed */
-       if ((IS_XSLT_REAL_NODE(list->nodeTab[i])) &&
-           (list->nodeTab[i]->doc!=NULL) &&
-           (list->nodeTab[i]->doc->doc!=NULL) &&
-           (list->nodeTab[i]->doc->doc)!=ctxt->xpathCtxt->doc) {         
-           /* The nodeset is from another document, so must change */
-           ctxt->xpathCtxt->doc=list->nodeTab[i]->doc->doc;
-           if ((list->nodeTab[i]->doc->name != NULL) ||
-               (list->nodeTab[i]->doc->URL != NULL)) {
-               ctxt->document = xsltFindDocument(ctxt,
-                                   list->nodeTab[i]->doc->doc);
-               if (ctxt->document == NULL) {
-                   /* restore the previous context */
-                   ctxt->document = oldCDocPtr;
-               }
-               ctxt->xpathCtxt->node = list->nodeTab[i];
-#ifdef WITH_XSLT_DEBUG_PROCESS
-               if ((ctxt->document != NULL) &&
-                   (ctxt->document->doc != NULL)) {
-                   XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
-                "xsltApplyTemplates: Changing document - context doc %s, xpathdoc %s\n",
-                  ctxt->document->doc->URL, ctxt->xpathCtxt->doc->URL));
-               } else {
-                   XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATES,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltApplyTemplates: Changing document - Return tree fragment\n"));
-               }
-#endif
-           }
-       }
-       xsltProcessOneNode(ctxt, list->nodeTab[i], params);
-    }
-error:
-    if (params != NULL)
-       xsltFreeStackElemList(params);  /* free the parameter list */
-    if (list != NULL)
-       xmlXPathFreeNodeSet(list);
-    /*
-     * res must be deallocated after list
-     */
-    if (res != NULL)
-       xmlXPathFreeObject(res);
-
-    ctxt->nodeList = oldList;
-    ctxt->xpathCtxt->contextSize = oldContextSize;
-    ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
-    ctxt->xpathCtxt->doc = oldXDocPtr;
-    ctxt->document = oldCDocPtr;
-    ctxt->xpathCtxt->nsNr = oldNsNr;
-    ctxt->xpathCtxt->namespaces = oldNamespaces;
-
-    ctxt->node = oldNode;
-    ctxt->mode = oldMode;
-    ctxt->modeURI = oldModeURI;
-}
-
-
-/**
- * xsltChoose:
- * @ctxt:  a XSLT process context
- * @node:  the node in the source tree.
- * @inst:  the xslt choose node
- * @comp:  precomputed information
- *
- * Process the xslt choose node on the source node
- */
-void
-xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr node,
-          xmlNodePtr inst, xsltStylePreCompPtr comp ATTRIBUTE_UNUSED)
-{
-    xmlXPathObjectPtr res = NULL;
-    xmlNodePtr replacement, when;
-    int doit = 1;
-    int oldProximityPosition, oldContextSize;
-    int oldNsNr;
-    xmlNsPtr *oldNamespaces;
-
-    if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
-       return;
-
-    /* 
-     * Check the when's
-     */
-    replacement = inst->children;
-    if (replacement == NULL) {
-       xsltTransformError(ctxt, NULL, inst,
-            "xsl:choose: empty content not allowed\n");
-       goto error;
-    }
-#ifdef XSLT_REFACTORED
-    if (((!IS_XSLT_ELEM_FAST(replacement)) ||
-#else
-    if (((!IS_XSLT_ELEM(replacement)) ||
-#endif
-       (!IS_XSLT_NAME(replacement, "when")))
-           && (!xmlIsBlankNode(replacement))) {
-       xsltTransformError(ctxt, NULL, inst,
-            "xsl:choose: xsl:when expected first\n");
-       goto error;
-    }
-#ifdef XSLT_REFACTORED
-    while ((IS_XSLT_ELEM_FAST(replacement) &&
-#else
-    while ((IS_XSLT_ELEM(replacement) &&
-#endif    
-       (IS_XSLT_NAME(replacement, "when")))
-           || xmlIsBlankNode(replacement)) {
-#ifdef XSLT_REFACTORED
-       xsltStyleItemWhenPtr wcomp =
-           (xsltStyleItemWhenPtr) replacement->psvi;
-#else
-       xsltStylePreCompPtr wcomp = replacement->psvi;
-#endif
-
-       if (xmlIsBlankNode(replacement)) {
-           replacement = replacement->next;
-           continue;
-       }
-       
-       if ((wcomp == NULL) || (wcomp->test == NULL) || (wcomp->comp == NULL)) {
-           xsltTransformError(ctxt, NULL, inst,
-                "xsl:choose: compilation failed !\n");
-           goto error;
-       }
-       when = replacement;
-
-
-#ifdef WITH_DEBUGGER
-        if (xslDebugStatus != XSLT_DEBUG_NONE)
-#ifdef XSLT_REFACTORED
-            xslHandleDebugger(when, node, NULL, ctxt);
-#else
-           /* TODO: Isn't comp->templ always NULL for xsl:choose? */
-            xslHandleDebugger(when, node, comp->templ, ctxt);
-#endif
-#endif
-
-#ifdef WITH_XSLT_DEBUG_PROCESS
-       XSLT_TRACE(ctxt,XSLT_TRACE_CHOOSE,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltChoose: test %s\n", wcomp->test));
-#endif
-
-       oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
-       oldContextSize = ctxt->xpathCtxt->contextSize;
-       oldNsNr = ctxt->xpathCtxt->nsNr;
-       oldNamespaces = ctxt->xpathCtxt->namespaces;
-       ctxt->xpathCtxt->node = node;
-#ifdef XSLT_REFACTORED
-       if (wcomp->inScopeNs != NULL) {
-           ctxt->xpathCtxt->namespaces = wcomp->inScopeNs->list;
-           ctxt->xpathCtxt->nsNr = wcomp->inScopeNs->xpathNumber;
-       } else {
-           ctxt->xpathCtxt->namespaces = NULL;
-           ctxt->xpathCtxt->nsNr = 0;
-       }
-#else
-       ctxt->xpathCtxt->namespaces = wcomp->nsList;
-       ctxt->xpathCtxt->nsNr = wcomp->nsNr;
-#endif
-       res = xmlXPathCompiledEval(wcomp->comp, ctxt->xpathCtxt);
-       ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
-       ctxt->xpathCtxt->contextSize = oldContextSize;
-       ctxt->xpathCtxt->nsNr = oldNsNr;
-       ctxt->xpathCtxt->namespaces = oldNamespaces;
-       if (res != NULL) {
-           if (res->type != XPATH_BOOLEAN)
-               res = xmlXPathConvertBoolean(res);
-           if (res->type == XPATH_BOOLEAN)
-               doit = 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;
-           }
-       } else {
-           ctxt->state = XSLT_STATE_STOPPED;
-       }
-
-#ifdef WITH_XSLT_DEBUG_PROCESS
-       XSLT_TRACE(ctxt,XSLT_TRACE_CHOOSE,xsltGenericDebug(xsltGenericDebugContext,
-           "xsltChoose: test evaluate to %d\n", doit));
-#endif
-       if (doit) {
-           xsltApplyOneTemplateInt(ctxt, ctxt->node, when->children,
-                                NULL, NULL, 0);
-           goto done;
-       }
-       if (res != NULL)
-           xmlXPathFreeObject(res);
-       res = NULL;
-       replacement = replacement->next;
-    }
-#ifdef XSLT_REFACTORED
-    if (IS_XSLT_ELEM_FAST(replacement) &&
-#else
-    if (IS_XSLT_ELEM(replacement) &&
-#endif 
-       (IS_XSLT_NAME(replacement, "otherwise"))) {
-#ifdef WITH_DEBUGGER
-        if (xslDebugStatus != XSLT_DEBUG_NONE)
-#ifdef XSLT_REFACTORED
-            xslHandleDebugger(replacement, node, NULL, ctxt);
-#else
-           /* TODO: Isn't comp->templ always NULL for xsl:otherwise? */
-            xslHandleDebugger(replacement, node, comp->templ, ctxt);
-#endif
-#endif
-
-#ifdef WITH_XSLT_DEBUG_PROCESS
-       XSLT_TRACE(ctxt,XSLT_TRACE_CHOOSE,xsltGenericDebug(xsltGenericDebugContext,
-                        "evaluating xsl:otherwise\n"));
-#endif
-       xsltApplyOneTemplateInt(ctxt, ctxt->node, replacement->children,
-                            NULL, NULL, 0);
-       replacement = replacement->next;
-    }
-    while (xmlIsBlankNode(replacement)) {
-       replacement = replacement->next;
-    }
-    if (replacement != NULL) {
-       xsltTransformError(ctxt, NULL, inst,
-            "xsl:choose: unexpected content %s\n", replacement->name);
-       goto error;
-    }
-
-done:
-error:
-    if (res != NULL)
-       xmlXPathFreeObject(res);
-}
-
-/**
- * xsltIf:
- * @ctxt:  a XSLT process context
- * @node:  the node in the source tree.
- * @inst:  the xslt if node
- * @comp:  precomputed information
- *
- * Process the xslt if node on the source node
- */
-void
-xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr node,
-                  xmlNodePtr inst, xsltStylePreCompPtr castedComp){
-#ifdef XSLT_REFACTORED
-       xsltStyleItemIfPtr comp = (xsltStyleItemIfPtr) castedComp;
-#else
-       xsltStylePreCompPtr comp = castedComp;
-#endif
-    xmlXPathObjectPtr res = NULL;
-    int doit = 1;
-    int oldContextSize, oldProximityPosition;
-    int oldNsNr;
-    xmlNsPtr *oldNamespaces;
-
-    if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
-       return;
-    if ((comp == NULL) || (comp->test == NULL) || (comp->comp == NULL)) {
-       xsltTransformError(ctxt, NULL, inst,
-            "xsl:if : compilation failed\n");
-       return;
-    }
-
-#ifdef WITH_XSLT_DEBUG_PROCESS
-    XSLT_TRACE(ctxt,XSLT_TRACE_IF,xsltGenericDebug(xsltGenericDebugContext,
-        "xsltIf: test %s\n", comp->test));
-#endif
-
-    oldContextSize = ctxt->xpathCtxt->contextSize;
-    oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
-    oldNsNr = ctxt->xpathCtxt->nsNr;
-    oldNamespaces = ctxt->xpathCtxt->namespaces;
-    ctxt->xpathCtxt->node = 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
-    /*
-    * OPTIMIZE TODO: Use a specialized function, which returns only
-    *  true/false.
-    */
-    res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt);
-    ctxt->xpathCtxt->contextSize = oldContextSize;
-    ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
-    ctxt->xpathCtxt->nsNr = oldNsNr;
-    ctxt->xpathCtxt->namespaces = oldNamespaces;
-    if (res != NULL) {
-       if (res->type != XPATH_BOOLEAN)
-           res = xmlXPathConvertBoolean(res);
-       if (res->type == XPATH_BOOLEAN)
-           doit = res->boolval;
-       else {
-#ifdef WITH_XSLT_DEBUG_PROCESS
-           XSLT_TRACE(ctxt,XSLT_TRACE_IF,xsltGenericDebug(xsltGenericDebugContext,
-               "xsltIf: test didn't evaluate to a boolean\n"));
-#endif
-           goto error;
-       }
-    } else {
-       ctxt->state = XSLT_STATE_STOPPED;
-    }
-
-#ifdef WITH_XSLT_DEBUG_PROCESS
-    XSLT_TRACE(ctxt,XSLT_TRACE_IF,xsltGenericDebug(xsltGenericDebugContext,
-       "xsltIf: test evaluate to %d\n", doit));
-#endif
-    if (doit) {
-       xsltApplyOneTemplateInt(ctxt, node, inst->children, NULL, NULL, 0);
-    }
-
-error:
-    if (res != NULL)
-       xmlXPathFreeObject(res);
-}
-
-/**
- * xsltForEach:
- * @ctxt:  a XSLT process context
- * @node:  the node in the source tree.
- * @inst:  the xslt for-each node
- * @comp:  precomputed information
- *
- * Process the xslt for-each node on the source node
- */
-void
-xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
-                  xmlNodePtr inst, xsltStylePreCompPtr castedComp)
-{
-#ifdef XSLT_REFACTORED
-       xsltStyleItemForEachPtr comp = (xsltStyleItemForEachPtr) castedComp;
-#else
-       xsltStylePreCompPtr comp = castedComp;
-#endif
-    xmlXPathObjectPtr res = NULL;
-    xmlNodePtr replacement;
-    xmlNodeSetPtr list = NULL, oldList;
-    int i, oldProximityPosition, oldContextSize;
-    xmlNodePtr oldNode;
-    int nbsorts = 0;
-    xmlNodePtr sorts[XSLT_MAX_SORT];
-    xmlDocPtr oldXDocPtr;
-    xsltDocumentPtr oldCDocPtr;
-    int oldNsNr;
-    xmlNsPtr *oldNamespaces;
-
-    if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
-       return;
-    if ((comp == NULL) || (comp->select == NULL) || (comp->comp == NULL)) {
-       xsltTransformError(ctxt, NULL, inst,
-            "xsl:for-each : compilation failed\n");
-       return;
-    }
-    oldNode = ctxt->node;
-
-#ifdef WITH_XSLT_DEBUG_PROCESS
-    XSLT_TRACE(ctxt,XSLT_TRACE_FOR_EACH,xsltGenericDebug(xsltGenericDebugContext,
-        "xsltForEach: select %s\n", comp->select));
-#endif
-
-    oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
-    oldContextSize = ctxt->xpathCtxt->contextSize;
-    oldNsNr = ctxt->xpathCtxt->nsNr;
-    oldNamespaces = ctxt->xpathCtxt->namespaces;
-    ctxt->xpathCtxt->node = 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   
-    oldCDocPtr = ctxt->document;
-    oldXDocPtr = ctxt->xpathCtxt->doc;
-    res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt);
-    ctxt->xpathCtxt->contextSize = oldContextSize;
-    ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
-    ctxt->xpathCtxt->nsNr = oldNsNr;
-    ctxt->xpathCtxt->namespaces = oldNamespaces;
-    if (res != NULL) {
-       if (res->type == XPATH_NODESET)
-           list = res->nodesetval;
-    } else {
-       ctxt->state = XSLT_STATE_STOPPED;
-    }
-    if (list == NULL) {
-#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;
-    }
-
-#ifdef WITH_XSLT_DEBUG_PROCESS
-    XSLT_TRACE(ctxt,XSLT_TRACE_FOR_EACH,xsltGenericDebug(xsltGenericDebugContext,
-       "xsltForEach: select evaluates to %d nodes\n", list->nodeNr));
-#endif
-
-    oldList = ctxt->nodeList;
-    ctxt->nodeList = list;
-    oldContextSize = ctxt->xpathCtxt->contextSize;
-    oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
-    ctxt->xpathCtxt->contextSize = list->nodeNr;
-
-    /* 
-     * handle and skip the xsl:sort
-     */
-    replacement = inst->children;
-#ifdef XSLT_REFACTORED
-    while (IS_XSLT_ELEM_FAST(replacement) &&
-#else
-    while (IS_XSLT_ELEM(replacement) &&
-#endif
-       (IS_XSLT_NAME(replacement, "sort"))) {
-       if (nbsorts >= XSLT_MAX_SORT) {
-           xsltGenericError(xsltGenericErrorContext,
-               "xsl:for-each: too many sorts\n");
-       } else {
-           sorts[nbsorts++] = replacement;
-       }
-#ifdef WITH_DEBUGGER
-        if (xslDebugStatus != XSLT_DEBUG_NONE)
-            xslHandleDebugger(replacement, node, NULL, ctxt);
-#endif
-       replacement = replacement->next;
-    }
-
-    if (nbsorts > 0) {
-       xsltDoSortFunction(ctxt, sorts, nbsorts);
-    }
-
-
-    for (i = 0;i < list->nodeNr;i++) {
-       ctxt->node = list->nodeTab[i];
-       ctxt->xpathCtxt->proximityPosition = i + 1;
-       /* For a 'select' nodeset, need to check if document has changed */
-       if ((IS_XSLT_REAL_NODE(list->nodeTab[i])) &&
-           (list->nodeTab[i]->doc!=NULL) &&
-           (list->nodeTab[i]->doc->doc!=NULL) &&
-           (list->nodeTab[i]->doc->doc)!=ctxt->xpathCtxt->doc) {         
-           /* The nodeset is from another document, so must change */
-           ctxt->xpathCtxt->doc=list->nodeTab[i]->doc->doc;
-           if ((list->nodeTab[i]->doc->name != NULL) ||
-               (list->nodeTab[i]->doc->URL != NULL)) {
-               ctxt->document = xsltFindDocument(ctxt,
-                                   list->nodeTab[i]->doc->doc);
-               if (ctxt->document == NULL) {
-                   /* restore the previous context */
-                   ctxt->document = oldCDocPtr;
-               }
-               ctxt->xpathCtxt->node = list->nodeTab[i];
-#ifdef WITH_XSLT_DEBUG_PROCESS
-               if ((ctxt->document != NULL) &&
-                   (ctxt->document->doc != NULL)) {
-                   XSLT_TRACE(ctxt,XSLT_TRACE_FOR_EACH,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltForEach: Changing document - context doc %s, xpathdoc %s\n",
-                ctxt->document->doc->URL, ctxt->xpathCtxt->doc->URL));
-               } else {
-                   XSLT_TRACE(ctxt,XSLT_TRACE_FOR_EACH,xsltGenericDebug(xsltGenericDebugContext,
-            "xsltForEach: Changing document - Return tree fragment\n"));
-               }
-#endif
-           }
-       }
-       xsltApplyOneTemplateInt(ctxt, list->nodeTab[i], replacement, NULL, NULL, 0);
-    }
-    ctxt->document = oldCDocPtr;
-    ctxt->nodeList = oldList;
-    ctxt->node = oldNode;
-    ctxt->xpathCtxt->doc = oldXDocPtr;
-    ctxt->xpathCtxt->contextSize = oldContextSize;
-    ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
-    ctxt->xpathCtxt->nsNr = oldNsNr;
-    ctxt->xpathCtxt->namespaces = oldNamespaces;
-
-error:
-    if (res != NULL)
-       xmlXPathFreeObject(res);
-}
-
-/************************************************************************
- *                                                                     *
- *                     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);
-
-    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));
-    ctxt->output = res;
-    ctxt->insert = (xmlNodePtr) res;
-    if (ctxt->globalVars == NULL)
-       ctxt->globalVars = xmlHashCreate(20);
-    if (params != NULL)
-        xsltEvalUserParams(ctxt, params);
-    xsltEvalGlobalVariables(ctxt);
-#ifdef XSLT_REFACTORED_KEYCOMP    
-    xsltCountKeys(ctxt);
-#endif
-    ctxt->node = (xmlNodePtr) doc;
-    varsPush(ctxt, NULL);
-    ctxt->varsBase = ctxt->varsNr - 1;
-    xsltProcessOneNode(ctxt, ctxt->node, NULL);
-    xsltFreeStackElemList(varsPop(ctxt));
-    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;
-    }
-
-
-    /*
-     * 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);
-       }
-    }
-
-    if ((ctxt != NULL) && (userCtxt == NULL))
-       xsltFreeTransformContext(ctxt);
-
-    return (res);
-
-error:
-    if (res != NULL)
-        xmlFreeDoc(res);
-    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);
-
-}
+/*\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
index 124f02a..5adb082 100644 (file)
-/*
- * 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
-
-/************************************************************************
- *                                                                     *
- *  Result Value Tree (Result Tree Fragment) interfaces                        *
- *                                                                     *
- ************************************************************************/
-/**
- * xsltCreateRVT:
- * @ctxt:  an XSLT transformation context
- *
- * Create 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 error
- */
-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);
-
-    container = xmlNewDoc(NULL);
-    if (container == NULL)
-       return(NULL);
-    container->dict = ctxt->dict;
-    xmlDictReference(container->dict);
-#ifdef WITH_XSLT_DEBUG
-    xsltGenericDebug(xsltGenericDebugContext,
-                     "reusing transformation dict for RVT\n");
-#endif
-
-    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)
- *
- * Register the result value tree (XSLT 1.0 term: Result Tree Fragment)
- * for destruction at the end of the context
- *
- * Returns 0 in case of success and -1 in case of error.
- */
-int
-xsltRegisterTmpRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
-{
-    if ((ctxt == NULL) || (RVT == NULL)) return(-1);
-
-    RVT->next = (xmlNodePtr) ctxt->tmpRVT;
-    if (ctxt->tmpRVT != NULL)
-       ctxt->tmpRVT->prev = (xmlNodePtr) RVT;
-    ctxt->tmpRVT = RVT;
-    return(0);
-}
-
-/**
- * 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)
- * for destruction at the end of the processing
- *
- * 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
- *
- * Free all the registered result value tree (Result Tree Fragment)
- * of the transformation
- */
-void
-xsltFreeRVTs(xsltTransformContextPtr ctxt)
-{
-    xmlDocPtr cur, next;
-
-    if (ctxt == NULL) return;
-
-    cur = ctxt->tmpRVT;
-    while (cur != NULL) {
-        next = (xmlDocPtr) cur->next;
-       if (cur->_private != NULL) {
-           xsltFreeDocumentKeys(cur->_private);
-           xmlFree(cur->_private);
-       }
-       xmlFreeDoc(cur);
-       cur = next;
-    }
-    cur = ctxt->persistRVT;
-    while (cur != NULL) {
-        next = (xmlDocPtr) cur->next;
-       if (cur->_private != NULL) {
-           xsltFreeDocumentKeys(cur->_private);
-           xmlFree(cur->_private);
-       }
-       xmlFreeDoc(cur);
-       cur = next;
-    }
-}
-
-/************************************************************************
- *                                                                     *
- *                     Module interfaces                               *
- *                                                                     *
- ************************************************************************/
-
-/**
- * xsltNewStackElem:
- *
- * Create a new XSLT ParserContext
- *
- * Returns the newly allocated xsltParserStackElem or NULL in case of error
- */
-static xsltStackElemPtr
-xsltNewStackElem(void) {
-    xsltStackElemPtr cur;
-
-    cur = (xsltStackElemPtr) xmlMalloc(sizeof(xsltStackElem));
-    if (cur == NULL) {
-       xsltTransformError(NULL, NULL, NULL,
-               "xsltNewStackElem : malloc failed\n");
-       return(NULL);
-    }
-    cur->computed = 0;
-    cur->name = NULL;
-    cur->nameURI = NULL;
-    cur->select = NULL;
-    cur->tree = NULL;
-    cur->value = NULL;
-    cur->comp = NULL;
-    return(cur);
-}
-
-/**
- * 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);
-    }
-    cur->name = elem->name;
-    cur->nameURI = elem->nameURI;
-    cur->select = elem->select;
-    cur->tree = elem->tree;
-    cur->comp = elem->comp;
-    cur->computed = 0;
-    cur->value = NULL;
-    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);
-
-    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.
- */
-static int stack_addr = 0;
-static int stack_cmp = 0;
-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 get equality
-     */
-    for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
-       cur = ctxt->varsTab[i-1];
-       while (cur != NULL) {
-           if (cur->name == name) {
-               if (nameURI == NULL) {
-                   if (cur->nameURI == NULL) {
-                       stack_addr++;
-                       return(cur);
-                   }
-               } else {
-                   if ((cur->nameURI != NULL) &&
-                       (cur->nameURI == nameURI)) {
-                       stack_addr++;
-                       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);
-    else
-        nameURI = NULL;
-    for (i = ctxt->varsNr; i > ctxt->varsBase; i--) {
-       cur = ctxt->varsTab[i-1];
-       while (cur != NULL) {
-           if (cur->name == name) {
-               if (nameURI == NULL) {
-                   if (cur->nameURI == NULL) {
-                       stack_cmp++;
-                       return(cur);
-                   }
-               } else {
-                   if ((cur->nameURI != NULL) &&
-                       (cur->nameURI == nameURI)) {
-                       stack_cmp++;
-                       return(cur);
-                   }
-               }
-
-           }
-           cur = cur->next;
-       }
-    }
-
-    return(NULL);
-}
-
-/**
- * xsltCheckStackElem:
- * @ctxt:  xn XSLT transformation context
- * @name:  the variable name
- * @nameURI:  the variable namespace URI
- *
- * check wether the variable or param is already defined
- *
- * 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
- *
- * add a new element at this level of the stack.
- *
- * 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);
-
-    elem->next = ctxt->varsTab[ctxt->varsNr - 1];
-    ctxt->varsTab[ctxt->varsNr - 1] = elem;
-    ctxt->vars = elem;
-    return(0);
-}
-
-/**
- * xsltAddStackElemList:
- * @ctxt:  xn XSLT transformation context
- * @elems:  a stack element list
- *
- * add the new element list at this level of the stack.
- *
- * Returns 0 in case of success, -1 in case of failure.
- */
-int
-xsltAddStackElemList(xsltTransformContextPtr ctxt, xsltStackElemPtr elems) {
-    xsltStackElemPtr cur;
-
-    if ((ctxt == NULL) || (elems == NULL))
-       return(-1);
-
-    /* TODO: check doublons */
-    if (ctxt->varsTab[ctxt->varsNr - 1] != NULL) {
-       cur = ctxt->varsTab[ctxt->varsNr - 1];
-       while (cur->next != NULL)
-           cur = cur->next;
-       cur->next = elems;
-    } else {
-       elems->next = ctxt->varsTab[ctxt->varsNr - 1];
-       ctxt->varsTab[ctxt->varsNr - 1] = elems;
-       ctxt->vars = elems;
-    }
-    return(0);
-}
-
-/************************************************************************
- *                                                                     *
- *                     Module interfaces                               *
- *                                                                     *
- ************************************************************************/
-
-/**
- * xsltEvalVariable:
- * @ctxt:  the XSLT transformation context
- * @elem:  the variable or parameter.
- * @precomp: pointer to precompiled data
- *
- * Evaluate a variable value.
- *
- * Returns the XPath Object value or NULL in case of error
- */
-static xmlXPathObjectPtr
-xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem,
-                xsltStylePreCompPtr castedComp)
-{
-#ifdef XSLT_REFACTORED
-    xsltStyleItemVariablePtr precomp =
-       (xsltStyleItemVariablePtr) castedComp;
-#else
-    xsltStylePreCompPtr precomp = castedComp;
-#endif   
-    xmlXPathObjectPtr result = NULL;
-    int oldProximityPosition, oldContextSize;
-    xmlNodePtr oldInst, oldNode;
-    xsltDocumentPtr oldDoc;
-    int oldNsNr;
-    xmlNsPtr *oldNamespaces;
-
-    if ((ctxt == NULL) || (elem == NULL))
-       return(NULL);
-
-#ifdef WITH_XSLT_DEBUG_VARIABLE
-    XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
-       "Evaluating variable %s\n", elem->name));
-#endif
-    if (elem->select != NULL) {
-       xmlXPathCompExprPtr comp = NULL;
-
-       if ((precomp != NULL) && (precomp->comp != NULL)) {
-           comp = precomp->comp;
-       } else {
-           comp = xmlXPathCompile(elem->select);
-       }
-       if (comp == NULL)
-           return(NULL);
-       oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
-       oldContextSize = ctxt->xpathCtxt->contextSize;
-       ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
-       oldDoc = ctxt->document;
-       oldNode = ctxt->node;
-       oldInst = ctxt->inst;
-       oldNsNr = ctxt->xpathCtxt->nsNr;
-       oldNamespaces = ctxt->xpathCtxt->namespaces;
-       if (precomp != NULL) {
-           ctxt->inst = precomp->inst;
-#ifdef XSLT_REFACTORED
-           if (precomp->inScopeNs != NULL) {
-               ctxt->xpathCtxt->namespaces = precomp->inScopeNs->list;
-               ctxt->xpathCtxt->nsNr = precomp->inScopeNs->xpathNumber;
-           } else {
-               ctxt->xpathCtxt->namespaces = NULL;
-               ctxt->xpathCtxt->nsNr = 0;
-           }
-#else
-           ctxt->xpathCtxt->namespaces = precomp->nsList;
-           ctxt->xpathCtxt->nsNr = precomp->nsNr;
-#endif
-       } else {
-           ctxt->inst = NULL;
-           ctxt->xpathCtxt->namespaces = NULL;
-           ctxt->xpathCtxt->nsNr = 0;
-       }
-       result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
-       ctxt->xpathCtxt->contextSize = oldContextSize;
-       ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
-       ctxt->xpathCtxt->nsNr = oldNsNr;
-       ctxt->xpathCtxt->namespaces = oldNamespaces;
-       ctxt->inst = oldInst;
-       ctxt->node = oldNode;
-       ctxt->document = oldDoc;
-       if ((precomp == NULL) || (precomp->comp == NULL))
-           xmlXPathFreeCompExpr(comp);
-       if (result == NULL) {
-           if (precomp == NULL)
-               xsltTransformError(ctxt, NULL, NULL,
-                   "Evaluating variable %s failed\n", elem->name);
-           else
-               xsltTransformError(ctxt, NULL, precomp->inst,
-                   "Evaluating 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 {
-           /*
-            * This is a result tree fragment.
-            */
-           xmlDocPtr container;
-           xmlNodePtr oldInsert;
-           xmlDocPtr  oldoutput;
-
-           container = xsltCreateRVT(ctxt);
-           if (container == NULL)
-               return(NULL);
-           /*
-            * Tag the subtree for removal once consumed
-            */
-           xsltRegisterTmpRVT(ctxt, container);
-           oldoutput = ctxt->output;
-           ctxt->output = container;
-           oldInsert = ctxt->insert;
-           ctxt->insert = (xmlNodePtr) container;
-           xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
-           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
-       }
-    }
-    return(result);
-}
-
-/**
- * xsltEvalGlobalVariable:
- * @elem:  the variable or parameter.
- * @ctxt:  the XSLT transformation context
- *
- * Evaluate a global variable value.
- *
- * Returns the XPath Object value or NULL in case of error
- */
-static xmlXPathObjectPtr
-xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt)
-{
-    xmlXPathObjectPtr result = NULL;
-#ifdef XSLT_REFACTORED
-    xsltStyleBasicItemVariablePtr precomp;
-#else
-    xsltStylePreCompPtr precomp;
-#endif    
-    int oldProximityPosition, oldContextSize;
-    xmlDocPtr oldDoc;
-    xmlNodePtr oldInst;
-    int oldNsNr;
-    xmlNsPtr *oldNamespaces;
-    const xmlChar *name;
-
-    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
-
-    name = elem->name;
-    elem->name = BAD_CAST "  being computed ... ";
-
-#ifdef XSLT_REFACTORED
-    precomp = (xsltStyleBasicItemVariablePtr) elem->comp;
-#else
-    precomp = elem->comp;
-#endif
-
-    /*
-    * OPTIMIZE TODO: We should consider if instantiating global vars/params
-    *  on a on-demand basis would be better. 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 comp = NULL;
-
-       if ((precomp != NULL) && (precomp->comp != NULL)) {
-           comp = precomp->comp;
-       } else {
-           comp = xmlXPathCompile(elem->select);
-       }
-       if (comp == NULL) {
-           elem->name = name;
-           return(NULL);
-       }
-       oldDoc = ctxt->xpathCtxt->doc;
-       oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
-       oldContextSize = ctxt->xpathCtxt->contextSize;
-       oldInst = ctxt->inst;
-       oldNsNr = ctxt->xpathCtxt->nsNr;
-       oldNamespaces = ctxt->xpathCtxt->namespaces;
-       
-       if (precomp != NULL) {
-           ctxt->inst = precomp->inst;
-#ifdef XSLT_REFACTORED
-           if (precomp->inScopeNs != NULL) {
-               ctxt->xpathCtxt->namespaces = precomp->inScopeNs->list;
-               ctxt->xpathCtxt->nsNr = precomp->inScopeNs->xpathNumber;
-           } else {
-               ctxt->xpathCtxt->namespaces = NULL;
-               ctxt->xpathCtxt->nsNr = 0;
-           }
-#else
-           ctxt->xpathCtxt->namespaces = precomp->nsList;
-           ctxt->xpathCtxt->nsNr = precomp->nsNr;
-#endif
-       } else {
-           ctxt->inst = NULL;
-           ctxt->xpathCtxt->namespaces = NULL;
-           ctxt->xpathCtxt->nsNr = 0;
-       }
-       ctxt->xpathCtxt->doc = ctxt->tmpDoc;
-       ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->tmpDoc;
-       result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
-
-       ctxt->xpathCtxt->doc = oldDoc;
-       ctxt->xpathCtxt->contextSize = oldContextSize;
-       ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
-       ctxt->inst = oldInst;
-       ctxt->xpathCtxt->nsNr = oldNsNr;
-       ctxt->xpathCtxt->namespaces = oldNamespaces;
-       if ((precomp == NULL) || (precomp->comp == NULL))
-           xmlXPathFreeCompExpr(comp);
-       if (result == NULL) {
-           if (precomp == NULL)
-               xsltTransformError(ctxt, NULL, NULL,
-                   "Evaluating global variable %s failed\n", elem->name);
-           else
-               xsltTransformError(ctxt, NULL, precomp->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 {
-           /*
-            * This is a result tree fragment.
-            */
-           xmlDocPtr container;
-           xmlNodePtr oldInsert;
-           xmlDocPtr  oldoutput;
-
-           container = xsltCreateRVT(ctxt);
-           if (container == NULL)
-               return(NULL);
-           /*
-            * Tag the subtree for removal once consumed
-            */
-           xsltRegisterTmpRVT(ctxt, container);
-           /*
-            * Save a pointer to the global variable for later cleanup
-            */
-           container->psvi = elem;
-           oldoutput = ctxt->output;
-           ctxt->output = container;
-           oldInsert = ctxt->insert;
-           ctxt->insert = (xmlNodePtr) container;
-           xsltApplyOneTemplate(ctxt, ctxt->node, elem->tree, NULL, NULL);
-           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
-       }
-    }
-    if (result != NULL) {
-       elem->value = result;
-       elem->computed = 1;
-    }
-    elem->name = name;
-    return(result);
-}
-
-/**
- * xsltEvalGlobalVariables:
- * @ctxt:  the XSLT transformation context
- *
- * Evaluate the global variables of a stylesheet. This need to be
- * done on parsed stylesheets before starting to apply transformations
- *
- * 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
-
-    ctxt->tmpDoc = ctxt->document->doc;
-    ctxt->node = (xmlNodePtr) ctxt->document->doc;
-    ctxt->xpathCtxt->contextSize = 1;
-    ctxt->xpathCtxt->proximityPosition = 1;
-
-    /*
-     * 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
-     */
-    ctxt->node = (xmlNodePtr) ctxt->document->doc;
-    ctxt->xpathCtxt->contextSize = 1;
-    ctxt->xpathCtxt->proximityPosition = 1;
-    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();
-    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);
-               if (style != NULL) 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 comp;
-    xmlXPathObjectPtr result;
-    int oldProximityPosition;
-    int oldContextSize;
-    int oldNsNr;
-    xmlNsPtr *oldNamespaces;
-    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) {
-        comp = xmlXPathCompile(value);
-       if (comp != NULL) {
-           oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
-           oldContextSize = ctxt->xpathCtxt->contextSize;
-           ctxt->xpathCtxt->node = (xmlNodePtr) ctxt->node;
-
-           /* 
-            * There is really no in scope namespace for parameters on the
-            * command line.
-            */
-
-           oldNsNr = ctxt->xpathCtxt->nsNr;
-           oldNamespaces = ctxt->xpathCtxt->namespaces;
-           ctxt->xpathCtxt->namespaces = NULL;
-           ctxt->xpathCtxt->nsNr = 0;
-           result = xmlXPathCompiledEval(comp, ctxt->xpathCtxt);
-           ctxt->xpathCtxt->contextSize = oldContextSize;
-           ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
-           ctxt->xpathCtxt->nsNr = oldNsNr;
-           ctxt->xpathCtxt->namespaces = oldNamespaces;
-           xmlXPathFreeCompExpr(comp);
-       }
-       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();
-    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();
-    if (elem == NULL)
-       return(NULL);
-    elem->comp = (xsltStylePreCompPtr) comp;
-    elem->name = comp->name;
-    if (comp->select != NULL)
-       elem->select = comp->select;
-    else
-       elem->select = NULL;
-    if (comp->ns)
-       elem->nameURI = comp->ns;
-    elem->tree = tree;
-    if (elem->computed == 0) {
-       elem->value = xsltEvalVariable(ctxt, elem,
-           (xsltStylePreCompPtr) comp);
-       if (elem->value != NULL)
-           elem->computed = 1;
-    }
-    return(elem);
-}
-
-/**
- * xsltRegisterVariable:
- * @ctxt:  the XSLT transformation context
- * @comp:  pointer to precompiled data
- * @tree:  the tree if select is NULL
- * @param:  this is a parameter actually
- *
- * Computes and register a new variable value.
- * TODO: Is this intended for xsl:param as well?
- *
- * Returns 0 in case of success, -1 in case of error
- */
-static int
-xsltRegisterVariable(xsltTransformContextPtr ctxt,
-                    xsltStylePreCompPtr castedComp,
-                    xmlNodePtr tree, int param)
-{
-#ifdef XSLT_REFACTORED
-    xsltStyleBasicItemVariablePtr comp =
-       (xsltStyleBasicItemVariablePtr) castedComp;
-#else
-    xsltStylePreCompPtr comp = castedComp;
-#endif
-    xsltStackElemPtr elem;
-    int present;
-
-    present = xsltCheckStackElem(ctxt, comp->name, comp->ns);
-    if (param == 0) {
-       if ((present != 0) && (present != 3)) {
-           xsltTransformError(ctxt, NULL, comp->inst,
-               "xsl:variable : redefining %s\n", comp->name);
-           return(0);
-       }
-    } else if (present != 0) {
-       if ((present == 1) || (present == 2)) {
-           xsltTransformError(ctxt, NULL, comp->inst,
-               "xsl:param : redefining %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);
-    }
-    elem = xsltBuildVariable(ctxt, (xsltStylePreCompPtr) comp, tree);
-    xsltAddStackElem(ctxt, elem);
-    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);
-    }
-    if (elem->computed == 0) {
-       if (xmlStrEqual(elem->name, BAD_CAST "  being computed ... ")) {
-           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
- * @cur:  the "xsl:with-param" element
- *
- * parse an XSLT transformation param declaration, compute
- * its value but doesn't record it.
- * NOTE that this is also called with an *xsl:param* element
- * from exsltFuncFunctionFunction(). 
- *
- * Returns the new xsltStackElemPtr or NULL
- */
-
-xsltStackElemPtr
-xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr cur)
-{
-#ifdef XSLT_REFACTORED
-    xsltStyleBasicItemVariablePtr comp;
-#else
-    xsltStylePreCompPtr comp;
-#endif
-    xmlNodePtr tree = NULL;
-    xsltStackElemPtr elem = NULL;
-    
-    if ((cur == NULL) || (ctxt == NULL))
-       return(NULL);
-#ifdef XSLT_REFACTORED
-    comp = (xsltStyleBasicItemVariablePtr) cur->psvi;
-#else
-    comp = (xsltStylePreCompPtr) cur->psvi;
-#endif     
-    if (comp == NULL) {
-       xsltTransformError(ctxt, NULL, cur,
-           "xsl:with-param : compilation error\n");
-       return(NULL);
-    }
-
-    if (comp->name == NULL) {
-       xsltTransformError(ctxt, NULL, cur,
-           "xsl:with-param : missing name attribute\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 = cur->children;
-    } else {
-#ifdef WITH_XSLT_DEBUG_VARIABLE
-       XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
-           "        select %s\n", comp->select));
-#endif
-       tree = cur;
-    }
-
-    elem = xsltBuildVariable(ctxt, (xsltStylePreCompPtr) comp, tree);
-
-    return(elem);
-}
-
-/**
- * xsltParseGlobalVariable:
- * @style:  the XSLT stylesheet
- * @cur:  the "variable" element
- *
- * parse an XSLT transformation variable declaration and record
- * its value.
- */
-
-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
- * @cur:  the "variable" element
- *
- * parse an XSLT transformation variable declaration and record
- * its value.
- */
-
-void
-xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr cur)
-{
-#ifdef XSLT_REFACTORED
-    xsltStyleItemVariablePtr comp;
-#else
-    xsltStylePreCompPtr comp;
-#endif
-
-    if ((cur == NULL) || (ctxt == NULL))
-       return;
-
-#ifdef XSLT_REFACTORED
-    comp = (xsltStyleItemVariablePtr) cur->psvi;
-#else
-    comp = (xsltStylePreCompPtr) cur->psvi;
-#endif   
-    if (comp == NULL) {
-       xsltTransformError(ctxt, NULL, cur,
-            "xsl:variable : compilation failed\n");
-       return;
-    }
-
-    if (comp->name == NULL) {
-       xsltTransformError(ctxt, NULL, cur,
-           "xsl:variable : missing name attribute\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, cur->children, 0);
-}
-
-/**
- * xsltParseStylesheetParam:
- * @ctxt:  the XSLT transformation context
- * @cur:  the "param" element
- *
- * parse an XSLT transformation param declaration and record
- * its value.
- */
-
-void
-xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur)
-{
-#ifdef XSLT_REFACTORED
-    xsltStyleItemParamPtr comp;
-#else
-    xsltStylePreCompPtr comp;
-#endif
-
-    if ((cur == NULL) || (ctxt == NULL))
-       return;
-#ifdef XSLT_REFACTORED
-    comp = (xsltStyleItemParamPtr) cur->psvi;
-#else
-    comp = (xsltStylePreCompPtr) cur->psvi;
-#endif 
-    if (comp == NULL) {
-       xsltTransformError(ctxt, NULL, cur,
-            "xsl:param : compilation failed\n");
-       return;
-    }
-
-    if (comp->name == NULL) {
-       xsltTransformError(ctxt, NULL, cur,
-           "xsl:param : missing name attribute\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 context;
-    xmlXPathObjectPtr ret;
-
-    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
-    context = (xsltTransformContextPtr) ctxt;
-    ret = xsltVariableLookup(context, name, ns_uri);
-    if (ret == NULL) {
-       xsltTransformError(ctxt, NULL, NULL,
-           "unregistered variable %s\n", name);
-    }
-#ifdef WITH_XSLT_DEBUG_VARIABLE
-    if (ret != NULL)
-       XSLT_TRACE(context,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
-           "found variable %s\n", name));
-#endif
-    return(ret);
-}
-
-
+/*\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
index 96141c6..67899c1 100644 (file)
-/*
- * 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 */
-
-/**
- * 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);
-
-    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;
-
-    /*
-    * TODO: This will gather the ns-decls of elements even if
-    * outside xsl:stylesheet. Example:
-    * <doc xmlns:foo="urn:test:foo">
-    *          <xsl:stylesheet ...    
-    * </doc>
-    * Will have foo="urn:test:foo" in the list.
-    * Is this OK?
-    */
-
-    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;
-       
-       /*
-       * 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;
-       }
-       /*
-       * 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;
-       /*
-       * Apply namespace aliasing
-       * ------------------------
-       * 
-       * 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 = cctxt->nsAliases;
-           do {
-               /*
-               * TODO: What to do with xmlns="" ?
-               */
-               if ((alias->literalNs != NULL) &&
-                   (xmlStrEqual(alias->literalNs->href, ns->href)))
-               {
-                   /*
-                   * Recognized as an namespace alias; convert it to
-                   * the target namespace.
-                   */
-                   if (alias->targetNs != NULL)
-                       ns = alias->literalNs;
-                   else {
-                       /*
-                       * The target is the NULL namespace.
-                       */
-                       goto skip_ns;
-                   }
-                   break;
-               }
-               alias = alias->next;
-           } while (alias != NULL);            
-       }
-       
-       /*
-       * 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);
-}
-
-/*
-* 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;
-    }
-    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 >= 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);
-}
-
-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(): Precompute the XSLT-instruction.
-    *  This will compile the information found on the current
-    *  element's attributes. NOTE that this won't process the
-    *  children of the current element.
-    */
-    xsltStylePreCompute(cctxt->style, elem);
-    /*
-    * 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:
-           /*  <!-- 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:
-           /* <!-- 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:
-    if (elem->children != NULL)
-       xsltParseSequenceConstructor(cctxt, elem->children);
-    
-exit:
-    xsltCompilerNodePop(cctxt, elem);
-    return(0);
-
-internal_err:
-    xsltCompilerNodePop(cctxt, elem);
-    return(-1);
-}
-
-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);
-}
-
-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(0);
-    }
-    /*
-    * 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 xsltApplyOneTemplateInt() 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 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" (or "sequence constructor"
- *  in XSLT 2.0) content model. Since 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);
-}
+/*\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
index 89c068b..fc60961 100644 (file)
-/*
- * 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_IS_TEXT_NODE(n) ((n != NULL) && \
-    (((n)->type == XML_TEXT_NODE) || \
-     ((n)->type == XML_CDATA_SECTION_NODE)))
-
-
-#if 0
-
-extern const xmlChar *xsltDocFragFake;
-
-#define XSLT_MARK_RES_TREE_FRAG(n) (n)->psvi = (void *) xsltDocFragFake;
-
-#define XSLT_IS_RES_TREE_FRAG(n) \
-    ((n != NULL) && ((n)->type == XML_DOCUMENT_NODE) && \
-     ((n)->psvi == xsltDocFragFake))
-
-#else
-
-#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] == ' ') && \
-    xmlStrEqual(BAD_CAST (n)->name, BAD_CAST " fake node libxslt"))
-
-#endif
-
-/**
- * XSLT_REFACTORED_KEYCOMP:
- *
- * Internal define to enable on-demand xsl:key computation.
- */
-#define XSLT_REFACTORED_KEYCOMP
-
-/**
- * XSLT_REFACTORED:
- *
- * Internal define to enable the refactored parts of Libxslt.
- */
-/* #define XSLT_REFACTORED */
-/* ==================================================================== */
-
-#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 */
-};
-
-/**
- * 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.
- * 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 xsltStyleBasicItemVariable xsltStyleItemParam;
-typedef xsltStyleItemParam *xsltStyleItemParamPtr;
-
-/**
- * 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;
-};
-
-#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;    
-};   
-
-#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 */
-
-/*
- * 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 tree if no eval string or the location */
-    xmlXPathObjectPtr value;   /* The value if computed */
-};
-
-#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
-};
-
-/*
- * 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 document */
-    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
-     */
-    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;
-    /*
-     * temporary storage for doc ptr, currently only used for
-     * global var evaluation
-     */
-    xmlDocPtr          tmpDoc;
-    /*
-     * all document text strings are internalized
-     */
-    int internalized;
-    int nbKeys;
-    int hasTemplKeyPatterns;
-};
-
-/**
- * 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                        
-                       xsltRegisterPersistRVT  (xsltTransformContextPtr ctxt,
-                                                xmlDocPtr RVT);
-XSLTPUBFUN void XSLTCALL                       
-                       xsltFreeRVTs            (xsltTransformContextPtr ctxt);
-                       
-/*
- * 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__ */
-
+/*\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
index ed3aeb2..5ac608a 100644 (file)
-/*
- * 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) {
-        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();
-}
-
+/*\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
index 058d143..3595c6a 100644 (file)
-/*
- * 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_ATTRIBUTE_NODE) ||                             \
-      ((n)->type == XML_DOCUMENT_NODE) ||                              \
-      ((n)->type == XML_HTML_DOCUMENT_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__ */
-
-
+/*\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