Next step of refactoring (plus some bug-fixes). For more details see
authorKasimier T. Buchcik <kbuchcik@src.gnome.org>
Fri, 5 May 2006 21:18:25 +0000 (21:18 +0000)
committerKasimier T. Buchcik <kbuchcik@src.gnome.org>
Fri, 5 May 2006 21:18:25 +0000 (21:18 +0000)
* libxslt/xsltInternals.h libxslt/attributes.c
  libxslt/documents.c libxslt/extensions.c
  libxslt/extensions.h libxslt/functions.c
  libxslt/imports.c libxslt/keys.c libxslt/preproc.c
  libxslt/transform.c libxslt/variables.c libxslt/xslt.c
  libxslt/xsltutils.c libxslt/xsltutils.h libexslt/functions.c:
  Next step of refactoring (plus some bug-fixes).
  For more details see #340780.

15 files changed:
ChangeLog
libexslt/functions.c
libxslt/attributes.c
libxslt/documents.c
libxslt/extensions.c
libxslt/extensions.h
libxslt/imports.c
libxslt/keys.c
libxslt/preproc.c
libxslt/transform.c
libxslt/variables.c
libxslt/xslt.c
libxslt/xsltInternals.h
libxslt/xsltutils.c
libxslt/xsltutils.h

index 1feee53..a55491e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Fri May  5 23:10:47 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
+
+       * libxslt/xsltInternals.h libxslt/attributes.c
+         libxslt/documents.c libxslt/extensions.c
+         libxslt/extensions.h libxslt/functions.c
+         libxslt/imports.c libxslt/keys.c libxslt/preproc.c
+         libxslt/transform.c libxslt/variables.c libxslt/xslt.c
+         libxslt/xsltutils.c libxslt/xsltutils.h libexslt/functions.c:
+         Next step of refactoring (plus some bug-fixes).
+         For more details see #340780.
+
 Fri May  5 14:31:53 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
 
        * tests/exslt/common/node-set.5.out
index 57e90c4..51f7d44 100644 (file)
@@ -128,6 +128,10 @@ exsltFuncRegisterImportFunc (exsltFuncFunctionData *data,
  * @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
  */
@@ -170,8 +174,9 @@ exsltFuncInit (xsltTransformContextPtr ctxt, const xmlChar *URI) {
  * @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,
@@ -188,6 +193,7 @@ exsltFuncShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
  * @URI: the namespace URI for the extension
  *
  * Allocates the stylesheet data for EXSLT - Function
+ * Called at compile-time.
  *
  * Returns the allocated data
  */
@@ -201,9 +207,10 @@ exsltFuncStyleInit (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
  * exsltFuncStyleShutdown:
  * @style: an XSLT stylesheet
  * @URI: the namespace URI for the extension
- * @data: the stylesheet data to free up
+ * @data: the stylesheet data to free up 
  *
  * Shutdown the EXSLT - Function module
+ * Called at compile-time.
  */
 static void
 exsltFuncStyleShutdown (xsltStylesheetPtr style ATTRIBUTE_UNUSED,
@@ -431,8 +438,19 @@ exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) {
      * Register the function data such that it can be retrieved
      * by exslFuncFunctionFunction
      */
-    data = (xmlHashTablePtr) xsltStyleGetExtData (style,
-                                                 EXSLT_FUNCTIONS_NAMESPACE);
+#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");
@@ -441,9 +459,10 @@ exsltFuncFunctionComp (xsltStylesheetPtr style, xmlNodePtr inst) {
     }
 
     if (xmlHashAddEntry2 (data, ns->href, name, func) < 0) {
-       xsltGenericError(xsltGenericErrorContext,
-                        "Failed to register function {%s}%s\n",
+       xsltTransformError(NULL, style, inst,
+           "Failed to register function {%s}%s\n",
                         ns->href, name);
+       style->errors++;
     } else {
        xsltGenericDebug(xsltGenericDebugContext,
                         "exsltFuncFunctionComp: register {%s}%s\n",
index 9e6dbb4..849b2f6 100644 (file)
@@ -46,6 +46,7 @@
 #include "templates.h"
 #include "imports.h"
 #include "transform.h"
+#include "preproc.h"
 
 #define WITH_XSLT_DEBUG_ATTRIBUTES
 #ifdef WITH_XSLT_DEBUG
@@ -143,6 +144,11 @@ xsltFreeAttrElemList(xsltAttrElemPtr list) {
     }
 }
 
+#ifdef XSLT_REFACTORED
+    /*
+    * This was moved to xsltParseStylesheetAttributeSet().
+    */
+#else
 /**
  * xsltAddAttrElemList:
  * @list:  an XSLT AttrElem list
@@ -161,7 +167,7 @@ xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) {
     if (list == NULL)
        return(xsltNewAttrElem(attr));
     cur = list;
-    while (cur != NULL) {
+    while (cur != NULL) {      
        next = cur->next;
        if (cur->attr == attr)
            return(cur);
@@ -173,6 +179,7 @@ xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) {
     }
     return(list);
 }
+#endif /* XSLT_REFACTORED */
 
 /**
  * xsltMergeAttrElemList:
@@ -185,7 +192,8 @@ xsltAddAttrElemList(xsltAttrElemPtr list, xmlNodePtr attr) {
  * Returns the new list pointer
  */
 static xsltAttrElemPtr
-xsltMergeAttrElemList(xsltAttrElemPtr list, xsltAttrElemPtr old) {
+xsltMergeAttrElemList(xsltStylesheetPtr style,
+                     xsltAttrElemPtr list, xsltAttrElemPtr old) {
     xsltAttrElemPtr cur;
     int add;
 
@@ -233,19 +241,23 @@ xsltMergeAttrElemList(xsltAttrElemPtr list, xsltAttrElemPtr old) {
        }
 
        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 = xmlStrdup(old->set);
+                   list->set = xmlDictLookup(style->dict, old->set, -1);
                    if (old->ns != NULL)
-                       list->ns = xmlStrdup(old->ns);
+                       list->ns = xmlDictLookup(style->dict, old->ns, -1);
                }
            } else if (add) {
                cur->next = xsltNewAttrElem(old->attr);
                if (old->set != NULL) {
-                   cur->next->set = xmlStrdup(old->set);
+                   cur->next->set = xmlDictLookup(style->dict, old->set, -1);
                    if (old->ns != NULL)
-                       cur->next->ns = xmlStrdup(old->ns);
+                       cur->next->ns = xmlDictLookup(style->dict, old->ns, -1);
                }
            }
        }
@@ -273,24 +285,23 @@ void
 xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
     const xmlChar *ncname;
     const xmlChar *prefix;
-    const xmlChar *attrib, *endattr;
-    xmlChar *prop;
-    xmlChar *attributes;
-    xmlNodePtr list;
-    xsltAttrElemPtr values;
+    xmlChar *value;
+    xmlNodePtr child;
+    xsltAttrElemPtr attrItems;
 
     if ((cur == NULL) || (style == NULL))
        return;
 
-    prop = xmlGetNsProp(cur, (const xmlChar *)"name", NULL);
-    if (prop == NULL) {
+    value = xmlGetNsProp(cur, (const xmlChar *)"name", NULL);
+    if (value == NULL) {
        xsltGenericError(xsltGenericErrorContext,
             "xsl:attribute-set : name is missing\n");
        return;
     }
 
-    ncname = xsltSplitQName(style->dict, prop, &prefix);
-    xmlFree(prop);
+    ncname = xsltSplitQName(style->dict, value, &prefix);
+    xmlFree(value);
+    value = NULL;
 
     if (style->attributeSets == NULL) {
 #ifdef WITH_XSLT_DEBUG_ATTRIBUTES
@@ -302,80 +313,141 @@ xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur) {
     if (style->attributeSets == NULL)
        return;
 
-    values = xmlHashLookup2(style->attributeSets, ncname, prefix);
+    attrItems = xmlHashLookup2(style->attributeSets, ncname, prefix);
 
     /*
-     * check the children list
-     */
-    list = cur->children;
-    while (list != NULL) {
-       if (IS_XSLT_ELEM(list)) {
-           if (!IS_XSLT_NAME(list, "attribute")) {
-               xsltGenericError(xsltGenericErrorContext,
-                   "xsl:attribute-set : unexpected child xsl:%s\n",
-                                list->name);
-           } else {
+    * 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);
+           xsltGenericDebug(xsltGenericDebugContext,
+               "add attribute to list %s\n", ncname);
 #endif
-                values = xsltAddAttrElemList(values, list);
+           /*
+           * 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;
+               }
            }
-       } else {
-           xsltGenericError(xsltGenericErrorContext,
-               "xsl:attribute-set : unexpected child %s\n", list->name);
+           /*
+           * 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
        }
-       list = list->next;
+
+#ifdef XSLT_REFACTORED
+next_child:
+#endif
+       child = child->next;
     }
 
     /*
-     * Check a possible use-attribute-sets definition
-     */
-    /* TODO check recursion */
-
-    attributes = xmlGetNsProp(cur, (const xmlChar *)"use-attribute-sets",
+    * Process attribue "use-attribute-sets".
+    */
+    /* TODO check recursion */    
+    value = xmlGetNsProp(cur, (const xmlChar *)"use-attribute-sets",
        NULL);
-    if (attributes == NULL) {
-       goto done;
-    }
-
-    attrib = attributes;
-    while (*attrib != 0) {
-       while (IS_BLANK(*attrib)) attrib++;
-       if (*attrib == 0)
-           break;
-        endattr = attrib;
-       while ((*endattr != 0) && (!IS_BLANK(*endattr))) endattr++;
-       attrib = xmlDictLookup(style->dict, attrib, endattr - attrib);
-       if (attrib) {
-           const xmlChar *ncname2 = NULL;
-           const xmlChar *prefix2 = NULL;
-           xsltAttrElemPtr values2;
-
+    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, attrib);
+               xsltGenericDebug(xsltGenericDebugContext,
+                   "xsl:attribute-set : %s adds use %s\n", ncname, curval);
 #endif
-           ncname2 = xsltSplitQName(style->dict, attrib, &prefix2);
-           values2 = xsltNewAttrElem(NULL);
-           if (values2 != NULL) {
-               values2->set = ncname2;
-               values2->ns = prefix2;
-               values = xsltMergeAttrElemList(values, values2);
-               xsltFreeAttrElem(values2);
+               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;
        }
-       attrib = endattr;
+       xmlFree(value);
+       value = NULL;
     }
-    xmlFree(attributes);
 
-done:
     /*
      * Update the value
      */
-    if (values == NULL)
-       values = xsltNewAttrElem(NULL);
-    xmlHashUpdateEntry2(style->attributeSets, ncname, prefix, values, NULL);
+    /*
+    * 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);
@@ -447,15 +519,12 @@ xsltResolveSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,
                    /*
                     * Then merge
                     */
-                   xsltMergeAttrElemList(values, refs);
+                   xsltMergeAttrElemList(style, values, refs);
                    /*
                     * Then suppress the reference
                     */
-                   xmlFree((char *)tmp->set);
                    tmp->set = NULL;
-                   if (tmp->ns != NULL) {
-                       xmlFree((char *)tmp->ns);
-                   }
+                   tmp->ns = NULL;
                }
            }
        }
@@ -492,7 +561,7 @@ xsltMergeSASCallback(xsltAttrElemPtr values, xsltStylesheetPtr style,
                "xsl:attribute-set : logic error merging from imports for"
                " attribute-set %s\n", name);
        } else {
-           topSet = xsltMergeAttrElemList(topSet, values);
+           topSet = xsltMergeAttrElemList(style, topSet, values);
            xmlHashUpdateEntry2(style->attributeSets, name, ns, topSet, NULL);
        }
        xsltFreeAttrElemList(values);
index b6ee9b0..0963e1c 100644 (file)
@@ -192,18 +192,42 @@ xsltNewStyleDocument(xsltStylesheetPtr style, xmlDocPtr doc) {
 
 /**
  * xsltFreeStyleDocuments:
- * @style: an XSLT style sheet
+ * @style: an XSLT stylesheet (representing a stylesheet-level)
  *
- * Free up all the space used by the loaded documents
+ * 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
+    xsltNsMapPtr nsMap;
+#endif
+    
+    if (style == NULL)
+       return;
+
+#ifdef XSLT_REFACTORED
+    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
+       /*
+       * Restore all changed namespace URIs of ns-decls.
+       */
+       if (nsMap)
+           xsltRestoreDocumentNamespaces(nsMap, doc->doc);
+#endif
+
        xsltFreeDocumentKeys(doc);
        if (!doc->main)
            xmlFreeDoc(doc->doc);
index 450474a..b7dad9b 100644 (file)
@@ -469,12 +469,19 @@ xsltFreeExts(xsltStylesheetPtr style)
 /**
  * xsltRegisterExtPrefix:
  * @style: an XSLT stylesheet
- * @prefix: the prefix used
+ * @prefix: the prefix used (optional)
  * @URI: the URI associated to the extension
- *
+ * 
  * Registers an extension namespace
- *
- * Returns 0 in case of success, -1 in case of failure
+ * This is called from xslt.c during compile-time.
+ * The given prefix is not needed.
+ * Called by:
+ *   xsltParseExtElemPrefixes() (new function)
+ *   xsltRegisterExtPrefix() (old function)
+ *
+ * Returns 0 in case of success, 1 if the @URI was already
+ *         registered as an extension namespace and
+ *         -1 in case of failure
  */
 int
 xsltRegisterExtPrefix(xsltStylesheetPtr style,
@@ -482,7 +489,7 @@ xsltRegisterExtPrefix(xsltStylesheetPtr style,
 {
     xsltExtDefPtr def, ret;
 
-    if ((style == NULL) || (prefix == NULL) | (URI == NULL))
+    if ((style == NULL) || (URI == NULL))
         return (-1);
 
 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
@@ -491,11 +498,22 @@ xsltRegisterExtPrefix(xsltStylesheetPtr style,
                      URI);
 #endif
     def = (xsltExtDefPtr) style->nsDefs;
+#ifdef XSLT_REFACTORED
+    /*
+    * The extension is associated with a namespace name.
+    */
+    while (def != NULL) {
+        if (xmlStrEqual(URI, def->URI))
+            return (1);
+        def = def->next;
+    }
+#else
     while (def != NULL) {
         if (xmlStrEqual(prefix, def->prefix))
             return (-1);
         def = def->next;
     }
+#endif
     ret = xsltNewExtDef(prefix, URI);
     if (ret == NULL)
         return (-1);
@@ -506,6 +524,12 @@ xsltRegisterExtPrefix(xsltStylesheetPtr style,
      * check wether there is an extension module with a stylesheet
      * initialization function.
      */
+#ifdef XSLT_REFACTORED
+    /*
+    * Don't initialize modules based on specified namespaced via
+    * the attribute "[xsl:]extension-element-prefixes".
+    */
+#else
     if (xsltExtensionsHash != NULL) {
         xsltExtModulePtr module;
 
@@ -515,11 +539,11 @@ xsltRegisterExtPrefix(xsltStylesheetPtr style,
                 module = xmlHashLookup(xsltExtensionsHash, URI);
             }
         }
-
         if (module != NULL) {
             xsltStyleGetExtData(style, URI);
         }
     }
+#endif
     return (0);
 }
 
@@ -600,82 +624,197 @@ xsltFreeCtxtExts(xsltTransformContextPtr ctxt)
 }
 
 /**
- * xsltStyleGetExtData:
+ * xsltStyleGetStylesheetExtData:
  * @style: an XSLT stylesheet
  * @URI:  the URI associated to the exension module
  *
- * Retrieve the data associated to the extension module in this given
- * stylesheet.
+ * Fires the compile-time initialization callback
+ * of an extension module and returns a container
+ * holding the user-data (retrieved via the callback).
  *
- * Returns the pointer or NULL if not present
+ * Returns the create module-data container
+ *         or NULL if such a module was not registered.
  */
-void *
-xsltStyleGetExtData(xsltStylesheetPtr style, const xmlChar * URI)
+static xsltExtDataPtr
+xsltStyleInitializeStylesheetModule(xsltStylesheetPtr style,
+                                    const xmlChar * URI)
 {
-    xsltExtDataPtr data = NULL;
-    xsltStylesheetPtr tmp;
-
-
-    if ((style == NULL) || (URI == NULL))
-        return (NULL);
+    xsltExtDataPtr dataContainer;
+    void *userData = NULL;
+    xsltExtModulePtr module;
+    
+    if ((style == NULL) || (URI == NULL))      
+       return(NULL);
 
-    tmp = style;
-    while (tmp != NULL) {
-        if (tmp->extInfos != NULL) {
-            data = (xsltExtDataPtr) xmlHashLookup(tmp->extInfos, URI);
-            if (data != NULL)
-                break;
-        }
-        tmp = xsltNextImport(tmp);
-    }
-    if (data == NULL) {
-        if (style->extInfos == NULL) {
-            style->extInfos = xmlHashCreate(10);
-            if (style->extInfos == NULL)
-                return (NULL);
-        }
+    if (xsltExtensionsHash == NULL) {
+#ifdef WITH_XSLT_DEBUG_EXTENSIONS
+       xsltGenericDebug(xsltGenericDebugContext,
+           "Not registered extension module: %s\n", URI);
+#endif
+       return(NULL);
     }
-    if (data == NULL) {
-        void *extData;
-        xsltExtModulePtr module;
 
-        module = xmlHashLookup(xsltExtensionsHash, URI);
-        if (module == NULL) {
+    module = xmlHashLookup(xsltExtensionsHash, URI);
+    if (module == NULL) {
 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
-            xsltGenericDebug(xsltGenericDebugContext,
-                             "Not registered extension module: %s\n", URI);
+       xsltGenericDebug(xsltGenericDebugContext,
+           "Not registered extension module: %s\n", URI);
 #endif
-            return (NULL);
-        } else {
-            if (module->styleInitFunc == NULL) {
+       return (NULL);
+    }
+    /*
+    * The specified module was registered so initialize it.
+    */
+    if (style->extInfos == NULL) {
+       style->extInfos = xmlHashCreate(10);
+       if (style->extInfos == NULL)
+           return (NULL);
+    }
+    /*
+    * Fire the initialization callback if available.
+    */
+    if (module->styleInitFunc == NULL) {
 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
-                xsltGenericDebug(xsltGenericDebugContext,
-                                 "Registering style module: %s\n", URI);
+       xsltGenericDebug(xsltGenericDebugContext,
+           "Initializing module with *no* callback: %s\n", URI);
 #endif
-                extData = NULL;
-            } else {
+    } else {
 #ifdef WITH_XSLT_DEBUG_EXTENSIONS
-                xsltGenericDebug(xsltGenericDebugContext,
-                                 "Initializing module: %s\n", URI);
+       xsltGenericDebug(xsltGenericDebugContext,
+           "Initializing module with callback: %s\n", URI);
 #endif
-                extData = module->styleInitFunc(style, URI);
-            }
+       /*
+       * Fire the initialization callback.
+       */
+       userData = module->styleInitFunc(style, URI);
+    }    
+    /*
+    * Store the user-data in the context of the given stylesheet.
+    */
+    dataContainer = xsltNewExtData(module, userData);
+    if (dataContainer == NULL)
+       return (NULL);
+
+    if (xmlHashAddEntry(style->extInfos, URI,
+       (void *) dataContainer) < 0)
+    {
+       xsltTransformError(NULL, style, NULL,       
+           "Failed to register module '%s'.\n", URI);
+       style->errors++;
+       if (module->styleShutdownFunc)
+           module->styleShutdownFunc(style, URI, userData);
+       xsltFreeExtData(dataContainer);
+       return (NULL);
+    }
 
-            data = xsltNewExtData(module, extData);
-            if (data == NULL)
-                return (NULL);
-            if (xmlHashAddEntry(style->extInfos, URI, (void *) data) < 0) {
-                xsltGenericError(xsltGenericErrorContext,
-                                 "Failed to register module data: %s\n",
-                                 URI);
-                if (module->styleShutdownFunc)
-                    module->styleShutdownFunc(style, URI, extData);
-                xsltFreeExtData(data);
-                return (NULL);
-            }
-        }
+    return(dataContainer);
+}
+
+/**
+ * xsltStyleGetExtData:
+ * @style: an XSLT stylesheet
+ * @URI:  the URI associated to the exension module
+ *
+ * Retrieve the data associated to the extension module
+ * in this given stylesheet.
+ * Called by:
+ *   xsltRegisterExtPrefix(),
+ *   ( xsltExtElementPreCompTest(), xsltExtInitTest )
+ *
+ * Returns the pointer or NULL if not present
+ */
+void *
+xsltStyleGetExtData(xsltStylesheetPtr style, const xmlChar * URI)
+{
+    xsltExtDataPtr dataContainer = NULL;
+    xsltStylesheetPtr tmpStyle;
+
+    if ((style == NULL) || (URI == NULL) ||
+       (xsltExtensionsHash == NULL))
+       return (NULL);
+
+    
+#ifdef XSLT_REFACTORED
+    /*
+    * This is intended for global storage, so only the main
+    * stylesheet will hold the data.
+    */
+    tmpStyle = style;
+    while (tmpStyle->parent != NULL)
+       tmpStyle = tmpStyle->parent;
+    if (tmpStyle->extInfos != NULL) {
+       dataContainer =
+           (xsltExtDataPtr) xmlHashLookup(tmpStyle->extInfos, URI);
+       if (dataContainer != NULL) {
+           /*
+           * The module was already initialized in the context
+           * of this stylesheet; just return the user-data that
+           * comes with it.
+           */
+           return(dataContainer->extData);
+       }
     }
-    return (data->extData);
+#else
+    /*
+    * Old behaviour.
+    */
+    tmpStyle = style;
+    while (tmpStyle != NULL) {
+       if (tmpStyle->extInfos != NULL) {
+           dataContainer =
+               (xsltExtDataPtr) xmlHashLookup(tmpStyle->extInfos, URI);
+           if (dataContainer != NULL) {
+               return(dataContainer->extData);
+           }
+       }
+       tmpStyle = xsltNextImport(tmpStyle);
+    }
+    tmpStyle = style;
+#endif
+
+    dataContainer =
+        xsltStyleInitializeStylesheetModule(tmpStyle, URI);
+    if (dataContainer != NULL)
+       return (dataContainer->extData);
+    return(NULL);
+}
+
+/**
+ * xsltStyleGetExtDataPerStylesheetLevel:
+ * @style: an XSLT stylesheet
+ * @URI:  the URI associated to the exension module
+ *
+ * Retrieve the data associated to the extension module in this given
+ * stylesheet.
+ *
+ * Returns the pointer or NULL if not present
+ */
+void *
+xsltStyleStylesheetLevelGetExtData(xsltStylesheetPtr style,
+                                  const xmlChar * URI)
+{
+    xsltExtDataPtr dataContainer = NULL;
+
+    if ((style == NULL) || (URI == NULL) ||
+       (xsltExtensionsHash == NULL))
+       return (NULL);
+
+    if (style->extInfos != NULL) {
+       dataContainer = (xsltExtDataPtr) xmlHashLookup(style->extInfos, URI);
+       /*
+       * The module was already initialized in the context
+       * of this stylesheet; just return the user-data that
+       * comes with it.
+       */
+       if (dataContainer)
+           return(dataContainer->extData);
+    }  
+
+    dataContainer =
+        xsltStyleInitializeStylesheetModule(style, URI);
+    if (dataContainer != NULL)
+       return (dataContainer->extData);
+    return(NULL);
 }
 
 /**
@@ -939,8 +1078,13 @@ xsltShutdownExt(xsltExtDataPtr data, xsltStylesheetPtr style,
                      "Shutting down module : %s\n", URI);
 #endif
     module->styleShutdownFunc(style, URI, data->extData);
-    xmlHashRemoveEntry(style->extInfos, URI,
-                       (xmlHashDeallocator) xsltFreeExtData);
+    /*
+    * Don't remove the entry from the hash table here, since
+    * this will produce segfaults - this fixes bug #340624.
+    *
+    * xmlHashRemoveEntry(style->extInfos, URI,
+    *   (xmlHashDeallocator) xsltFreeExtData);
+    */    
 }
 
 /**
@@ -964,29 +1108,59 @@ xsltShutdownExts(xsltStylesheetPtr style)
 /**
  * xsltCheckExtPrefix:
  * @style: the stylesheet
- * @prefix: the namespace prefix (possibly NULL)
+ * @URI: the namespace URI (possibly NULL)
  *
- * Check if the given prefix is one of the declared extensions
+ * Check if the given prefix is one of the declared extensions.
+ * This is intended to be called only at compile-time.
+ * Called by:
+ *  xsltGetInheritedNsList() (xslt.c)
+ *  xsltParseTemplateContent (xslt.c)
  *
  * Returns 1 if this is an extension, 0 otherwise
  */
 int
-xsltCheckExtPrefix(xsltStylesheetPtr style, const xmlChar * prefix)
-{
+xsltCheckExtPrefix(xsltStylesheetPtr style, const xmlChar * URI)
+{    
+#ifdef XSLT_REFACTORED
+    if ((style == NULL) || (style->compCtxt == NULL) ||
+       (XSLT_CCTXT(style)->inode == NULL) ||
+       (XSLT_CCTXT(style)->inode->extElemNs == NULL))
+        return (0);    
+    /*
+    * Lookup the extension namespaces registered
+    * at the current node in the stylesheet's tree.
+    */
+    if (XSLT_CCTXT(style)->inode->extElemNs != NULL) {
+       int i;
+       xsltPointerListPtr list = XSLT_CCTXT(style)->inode->extElemNs;
+
+       for (i = 0; i < list->number; i++) {
+           if (xmlStrEqual((const xmlChar *) list->items[i],
+               URI))
+           {
+               return(1);
+           }       
+       }
+    }
+#else
     xsltExtDefPtr cur;
 
     if ((style == NULL) || (style->nsDefs == NULL))
         return (0);
-
-    if (prefix == NULL)
-        prefix = BAD_CAST "#default";
-
+    if (URI == NULL)
+        URI = BAD_CAST "#default";
     cur = (xsltExtDefPtr) style->nsDefs;
     while (cur != NULL) {
-        if (xmlStrEqual(prefix, cur->prefix))
+       /*
+       * TODO: This is the old behaviour and it won't work
+       *  correctly, since it works with the namespace prefix,
+       *  but it should work with the namespace name.
+       */
+        if (xmlStrEqual(URI, cur->prefix))
             return (1);
         cur = cur->next;
     }
+#endif
     return (0);
 }
 
@@ -1281,13 +1455,39 @@ xsltPreComputeExtModuleElement(xsltStylesheetPtr style, xmlNodePtr inst)
 
     ext = (xsltExtElementPtr)
         xmlHashLookup2(xsltElementsHash, inst->name, inst->ns->href);
+    /*
+    * EXT TODO: Now what?
+    */
     if (ext == NULL)
         return (NULL);
 
-    if (ext->precomp != NULL)
+    if (ext->precomp != NULL) {
+       /*
+       * REVISIT TODO: Check if the text below is correct.
+       * This will return a xsltElemPreComp structure or NULL.
+       * 1) If the the author of the extension needs a
+       *  custom structure to hold the specific values of
+       *  this extension, he will derive a structure based on
+       *  xsltElemPreComp; thus we obviously *cannot* refactor
+       *  the xsltElemPreComp structure, since all already derived
+       *  user-defined strucures will break.
+       *  Example: For the extension xsl:document,
+       *   in xsltDocumentComp() (preproc.c), the structure
+       *   xsltStyleItemDocument is allocated, filled with
+       *   specific values and returned.
+       * 2) If the author needs no values to be stored in
+       *  this structure, then he'll return NULL;
+       */
         comp = ext->precomp(style, inst, ext->transform);
-    if (comp == NULL)
+    }
+    if (comp == NULL) {
+       /*
+       * Default creation of a xsltElemPreComp structure, if
+       * the author of this extension did not create a custom
+       * structure.
+       */
         comp = xsltNewElemPreComp(style, inst, ext->transform);
+    }
 
     return (comp);
 }
@@ -1553,6 +1753,13 @@ xsltGetExtInfo(xsltStylesheetPtr style, const xmlChar * URI)
 {
     xsltExtDataPtr data;
 
+    /*
+    * TODO: Why do we have a return type of xmlHashTablePtr?
+    *   Is the user-allocated data for extension modules expected
+    *   to be a xmlHashTablePtr only? Or is this intended for
+    *   the EXSLT module only?
+    */
+
     if (style != NULL && style->extInfos != NULL) {
         data = xmlHashLookup(style->extInfos, URI);
         if (data != NULL && data->extData != NULL)
index 79130e4..1036fae 100644 (file)
@@ -93,7 +93,12 @@ XSLTPUBFUN void * XSLTCALL
 XSLTPUBFUN void * XSLTCALL             
                xsltStyleGetExtData     (xsltStylesheetPtr style,
                                         const xmlChar *URI);
-
+#ifdef XSLT_REFACTORED
+XSLTPUBFUN void * XSLTCALL
+               xsltStyleStylesheetLevelGetExtData(
+                                        xsltStylesheetPtr style,
+                                        const xmlChar * URI);
+#endif
 XSLTPUBFUN void XSLTCALL               
                xsltShutdownCtxtExts    (xsltTransformContextPtr ctxt);
 
@@ -210,7 +215,7 @@ XSLTPUBFUN int XSLTCALL
                                         const xmlChar *URI);
 XSLTPUBFUN int XSLTCALL                
                xsltCheckExtPrefix      (xsltStylesheetPtr style,
-                                        const xmlChar *prefix);
+                                        const xmlChar *URI);
 XSLTPUBFUN int XSLTCALL                
                xsltInitCtxtExts        (xsltTransformContextPtr ctxt);
 XSLTPUBFUN void XSLTCALL               
index 1a2b12d..8ff9f3d 100644 (file)
@@ -41,6 +41,7 @@
 #include "xslt.h"
 #include "xsltInternals.h"
 #include "xsltutils.h"
+#include "preproc.h"
 #include "imports.h"
 #include "documents.h"
 #include "security.h"
@@ -229,7 +230,16 @@ xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
            "xsl:include : unable to load %s\n", URI);
        goto error;
     }
-
+#ifdef XSLT_REFACTORED    
+    if (IS_XSLT_ELEM_FAST(cur) && (cur->psvi != NULL)) {
+       ((xsltStyleItemIncludePtr) cur->psvi)->include = include;
+    } else {
+       xsltTransformError(NULL, style, cur,
+           "Internal error: (xsltParseStylesheetInclude) "
+           "The xsl:include element was not compiled.\n", URI);
+       style->errors++;
+    }
+#endif
     oldDoc = style->doc;
     style->doc = include->doc;
     /* chain to stylesheet for recursion checking */
@@ -237,6 +247,12 @@ xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) {
     style->includes = include;
     oldNopreproc = style->nopreproc;
     style->nopreproc = include->preproc;
+    /*
+    * TODO: This will change some values of the
+    *  including stylesheet with every included module
+    *  (e.g. excluded-result-prefixes)
+    *  We need to strictly seperate such stylesheet-owned values.
+    */
     result = xsltParseStylesheetProcess(style, include->doc);
     style->nopreproc = oldNopreproc;
     include->preproc = 1;
@@ -359,6 +375,13 @@ xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node) {
  * @nameURI: the template name URI
  *
  * Finds the named template, apply import precedence rule.
+ * REVISIT TODO: We'll change the nameURI fields of
+ *  templates to be in the string dict, so if the
+ *  specified @nameURI is in the same dict, then use pointer
+ *  comparison. Check if this can be done in a sane way.
+ *  Maybe this function is not needed internally at
+ *  transformation-time if we hard-wire the called templates
+ *  to the caller.
  *
  * Returns the xsltTemplatePtr or NULL if not found
  */
index cb7c998..c03d172 100644 (file)
@@ -369,6 +369,14 @@ xsltAddKey(xsltStylesheetPtr style, const xmlChar *name,
     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,
index 899c5fa..3e2d70c 100644 (file)
@@ -52,6 +52,11 @@ const xmlChar *xsltExtMarker = (const xmlChar *) "Extension Element";
  *                                                                     *
  ************************************************************************/
 
+#ifdef XSLT_REFACTORED
+    /*
+    * Grammar checks are now performed in xslt.c.
+    */
+#else
 /**
  * xsltCheckTopLevelElement:
  * @style: the XSLT stylesheet
@@ -197,6 +202,7 @@ xsltCheckParentElement(xsltStylesheetPtr style, xmlNodePtr inst,
                       inst->name);
     style->errors++;
 }
+#endif
 
 /************************************************************************
  *                                                                     *
@@ -350,7 +356,6 @@ xsltNewStylePreComp(xsltStylesheetPtr style, xsltStyleType type) {
        case XSLT_FUNC_PARAM:       
        case XSLT_FUNC_VARIABLE:            
        case XSLT_FUNC_WHEN:
-       case XSLT_FUNC_OTHERWISE:
            break;
        default:
        if (cur->func == NULL) {
@@ -518,7 +523,8 @@ xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst,
     * "output" in XSLT_SAXON_NAMESPACE
     * "write" XSLT_XALAN_NAMESPACE
     * "document" XSLT_XT_NAMESPACE
-    * "document" XSLT_NAMESPACE
+    * "document" XSLT_NAMESPACE (from the abandoned old working
+    *                            draft of XSLT 1.1)
     * (in libexslt/common.c)
     * "document" in EXSLT_COMMON_NAMESPACE
     */
@@ -544,6 +550,8 @@ xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst,
        *   (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",
@@ -557,6 +565,10 @@ xsltDocumentComp(xsltStylesheetPtr style, xmlNodePtr inst,
        /*
        * 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) {
@@ -770,11 +782,17 @@ xsltCopyComp(xsltStylesheetPtr style, xmlNodePtr inst) {
        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
@@ -807,13 +825,14 @@ xsltTextComp(xsltStylesheetPtr style, xmlNodePtr inst) {
        if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
            comp->noescape = 1;
        } else if (!xmlStrEqual(prop,
-                               (const xmlChar *)"no")){
+           (const xmlChar *)"no")){
            xsltTransformError(NULL, style, inst,
-"xsl:text: disable-output-escaping allows only yes or no\n");
+               "xsl:text: disable-output-escaping allows only yes or no\n");
            if (style != NULL) style->warnings++;
        }
     }
 }
+#endif /* else of XSLT_REFACTORED */
 
 /**
  * xsltElementComp:
@@ -1774,85 +1793,6 @@ xsltParamComp(xsltStylesheetPtr style, xmlNodePtr inst) {
     }
 }
 
-#ifdef XSLT_REFACTORED
-
-/*
-* xsltCompilerGetInScopeNSInfo:
-*
-* 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.
-*/
-xsltNsListPtr
-xsltCompilerGetInScopeNSInfo(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
-{
-    xsltNsListPtr nsi = NULL;
-    xmlNsPtr *list = NULL;
-    /*
-    * 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.
-    */
-    list = xmlGetNsList(node->doc, node);
-    if (list == NULL)
-       return(NULL);
-    /*
-    * Initialize the list hold by the stylesheet.
-    */
-    if (cctxt->sheet->inScopeNamespaces == NULL) {
-       cctxt->sheet->inScopeNamespaces = xsltPointerListCreate();
-       if (cctxt->sheet->inScopeNamespaces == NULL) {      
-           xsltTransformError(NULL, cctxt->sheet, NULL,
-               "xsltCompilerGetInScopeNSInfo: malloc failed.\n");          
-           goto internal_err;      
-       }
-    }
-    /*
-    * Create the info-structure.
-    */
-    nsi = (xsltNsListPtr) xmlMalloc(sizeof(xsltNsList));
-    if (nsi == NULL) { 
-       xsltTransformError(NULL, cctxt->sheet, NULL,
-           "xsltCompilerGetInScopeNSInfo: malloc failed.\n");
-       goto internal_err;
-    }
-    memset(nsi, 0, sizeof(xsltNsList));
-    nsi->list = list;
-    /*
-    * Eval the number of ns-decls; this is used to speed up
-    * XPath-context initialization.
-    */
-    while (list[nsi->number] != NULL)
-       nsi->number++;
-    /*
-    * Store the ns-list in the stylesheet.
-    */
-    if (xsltPointerListAdd(
-       (xsltPointerListPtr)cctxt->sheet->inScopeNamespaces,
-       (void *) nsi) == -1)
-    {  
-       xmlFree(nsi);
-       nsi = NULL;
-       xsltTransformError(NULL, cctxt->sheet, NULL,
-           "xsltCompilerGetInScopeNSInfo: failed to add ns-info.\n");
-       goto internal_err;
-    }     
-
-    return(nsi);
-
-internal_err:
-    if (list != NULL)
-       xmlFree(list);    
-    cctxt->sheet->errors++;
-    return(NULL);
-}
-#endif /* XSLT_REFACTORED */
-
 /************************************************************************
  *                                                                     *
  *                 Generic interface                                   *
@@ -1870,10 +1810,11 @@ xsltFreeStylePreComps(xsltStylesheetPtr style) {
     xsltElemPreCompPtr cur, next;
 
     if (style == NULL)
-       return;
+       return;        
+    
     cur = style->preComps;
     while (cur != NULL) {
-       next = cur->next;
+       next = cur->next;               
        if (cur->type == XSLT_FUNC_EXTENSION)
            cur->free(cur);
        else
@@ -1882,6 +1823,221 @@ xsltFreeStylePreComps(xsltStylesheetPtr style) {
     }
 }
 
+#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
@@ -1895,10 +2051,14 @@ 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.    
+    *   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 (inst->psvi != NULL)
+       return;
+
     if (IS_XSLT_ELEM(inst)) {
        xsltStylePreCompPtr cur;
 
@@ -1965,7 +2125,7 @@ xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
        } else if (IS_XSLT_NAME(inst, "call-template")) {
            xsltCheckInstructionElement(style, inst);
            xsltCallTemplateComp(style, inst);
-       } else if (IS_XSLT_NAME(inst, "param")) {
+       } else if (IS_XSLT_NAME(inst, "param")) {          
            if (xsltCheckTopLevelElement(style, inst, 0) == 0)
                xsltCheckInstructionElement(style, inst);
            xsltParamComp(style, inst);
@@ -2034,18 +2194,7 @@ xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
            if (style != NULL) style->warnings++;
        }
        
-       
        cur = (xsltStylePreCompPtr) inst->psvi;
-
-#ifdef XSLT_REFACTORED
-       /*
-       * Assign the current list of in-scope namespaces to the
-       * item. This is needed for XPath expressions.
-       */
-       if (cur != NULL) {
-           cur->inScopeNS = XSLT_CCTXT(style)->inode->inScopeNS;                   
-       }
-#else
        /*
        * A ns-list is build for every XSLT item in the
        * node-tree. This is needed for XPath expressions.
@@ -2060,7 +2209,6 @@ xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
            }
            cur->nsNr = i;
        }
-#endif
     } else {
        inst->psvi =
            (void *) xsltPreComputeExtModuleElement(style, inst);
@@ -2073,3 +2221,4 @@ xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst) {
            inst->psvi = (void *) xsltExtMarker;
     }
 }
+#endif /* XSLT_REFACTORED */
index f3b392f..ae66aa0 100644 (file)
@@ -1624,7 +1624,11 @@ xsltApplyOneTemplateInt(xsltTransformContextPtr ctxt, xmlNodePtr node,
             xslHandleDebugger(cur, node, templ, ctxt);
 #endif
 
+#ifdef XSLT_REFACTORED
+       if (IS_XSLT_ELEM_FAST(cur)) {
+#else
         if (IS_XSLT_ELEM(cur)) {
+#endif
             /*
              * This is an XSLT node
              */
@@ -2949,9 +2953,9 @@ xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
     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->number;
+    if (comp->inScopeNs != NULL) {
+       ctxt->xpathCtxt->namespaces = comp->inScopeNs->list;
+       ctxt->xpathCtxt->nsNr = comp->inScopeNs->number;
     } else {
        ctxt->xpathCtxt->namespaces = NULL;
        ctxt->xpathCtxt->nsNr = 0;
@@ -3065,9 +3069,9 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
     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->number;
+    if (comp->inScopeNs != NULL) {
+       ctxt->xpathCtxt->namespaces = comp->inScopeNs->list;
+       ctxt->xpathCtxt->nsNr = comp->inScopeNs->number;
     } else {
        ctxt->xpathCtxt->namespaces = NULL;
        ctxt->xpathCtxt->nsNr = 0;
@@ -3232,7 +3236,11 @@ xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
        *   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) {
@@ -3345,9 +3353,9 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
 
        ctxt->xpathCtxt->node = node;
 #ifdef XSLT_REFACTORED
-       if (comp->inScopeNS != NULL) {
-           ctxt->xpathCtxt->namespaces = comp->inScopeNS->list;
-           ctxt->xpathCtxt->nsNr = comp->inScopeNS->number;
+       if (comp->inScopeNs != NULL) {
+           ctxt->xpathCtxt->namespaces = comp->inScopeNs->list;
+           ctxt->xpathCtxt->nsNr = comp->inScopeNs->number;
        } else {
            ctxt->xpathCtxt->namespaces = NULL;
            ctxt->xpathCtxt->nsNr = 0;
@@ -3500,7 +3508,11 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
 #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) {
@@ -3620,13 +3632,23 @@ xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr node,
             "xsl:choose: empty content not allowed\n");
        goto error;
     }
-    if (((!IS_XSLT_ELEM(replacement)) || (!IS_XSLT_NAME(replacement, "when")))
+#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;
     }
-    while ((IS_XSLT_ELEM(replacement) && (IS_XSLT_NAME(replacement, "when")))
+#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 =
@@ -3669,9 +3691,9 @@ xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr node,
        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->number;
+       if (wcomp->inScopeNs != NULL) {
+           ctxt->xpathCtxt->namespaces = wcomp->inScopeNs->list;
+           ctxt->xpathCtxt->nsNr = wcomp->inScopeNs->number;
        } else {
            ctxt->xpathCtxt->namespaces = NULL;
            ctxt->xpathCtxt->nsNr = 0;
@@ -3715,7 +3737,12 @@ xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr node,
        res = NULL;
        replacement = replacement->next;
     }
-    if (IS_XSLT_ELEM(replacement) && (IS_XSLT_NAME(replacement, "otherwise"))) {
+#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
@@ -3791,9 +3818,9 @@ xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr node,
     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->number;
+    if (comp->inScopeNs != NULL) {
+       ctxt->xpathCtxt->namespaces = comp->inScopeNs->list;
+       ctxt->xpathCtxt->nsNr = comp->inScopeNs->number;
     } else {
        ctxt->xpathCtxt->namespaces = NULL;
        ctxt->xpathCtxt->nsNr = 0;
@@ -3886,9 +3913,9 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
     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->number;
+    if (comp->inScopeNs != NULL) {
+       ctxt->xpathCtxt->namespaces = comp->inScopeNs->list;
+       ctxt->xpathCtxt->nsNr = comp->inScopeNs->number;
     } else {
        ctxt->xpathCtxt->namespaces = NULL;
        ctxt->xpathCtxt->nsNr = 0;
@@ -3933,7 +3960,12 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
      * handle and skip the xsl:sort
      */
     replacement = inst->children;
-    while (IS_XSLT_ELEM(replacement) && (IS_XSLT_NAME(replacement, "sort"))) {
+#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");
index 88caf17..8bb8771 100644 (file)
@@ -467,9 +467,9 @@ xsltEvalVariable(xsltTransformContextPtr ctxt, xsltStackElemPtr elem,
        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->number;
+           if (precomp->inScopeNs != NULL) {
+               ctxt->xpathCtxt->namespaces = precomp->inScopeNs->list;
+               ctxt->xpathCtxt->nsNr = precomp->inScopeNs->number;
            } else {
                ctxt->xpathCtxt->namespaces = NULL;
                ctxt->xpathCtxt->nsNr = 0;
@@ -628,9 +628,9 @@ xsltEvalGlobalVariable(xsltStackElemPtr elem, xsltTransformContextPtr ctxt)
        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->number;
+           if (precomp->inScopeNs != NULL) {
+               ctxt->xpathCtxt->namespaces = precomp->inScopeNs->list;
+               ctxt->xpathCtxt->nsNr = precomp->inScopeNs->number;
            } else {
                ctxt->xpathCtxt->namespaces = NULL;
                ctxt->xpathCtxt->nsNr = 0;
@@ -1389,10 +1389,12 @@ xsltVariableLookup(xsltTransformContextPtr ctxt, const xmlChar *name,
 /**
  * xsltParseStylesheetCallerParam:
  * @ctxt:  the XSLT transformation context
- * @cur:  the "param" element
+ * @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
  */
@@ -1417,19 +1419,19 @@ xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr cur)
 #endif     
     if (comp == NULL) {
        xsltTransformError(ctxt, NULL, cur,
-           "xsl:param : compilation error\n");
+           "xsl:with-param : compilation error\n");
        return(NULL);
     }
 
     if (comp->name == NULL) {
        xsltTransformError(ctxt, NULL, cur,
-           "xsl:param : missing name attribute\n");
+           "xsl:with-param : missing name attribute\n");
        return(NULL);
     }
 
 #ifdef WITH_XSLT_DEBUG_VARIABLE
     XSLT_TRACE(ctxt,XSLT_TRACE_VARIABLES,xsltGenericDebug(xsltGenericDebugContext,
-           "Handling param %s\n", comp->name));
+           "Handling xsl:with-param %s\n", comp->name));
 #endif
 
     if (comp->select == NULL) {
@@ -1467,11 +1469,15 @@ xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur)
 
     if ((cur == NULL) || (style == NULL))
        return;
-
-    xsltStylePreCompute(style, cur);
+    
 #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) {
@@ -1486,8 +1492,15 @@ xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur)
        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,
@@ -1518,11 +1531,15 @@ xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) {
 
     if ((cur == NULL) || (style == NULL))
        return;
-
-    xsltStylePreCompute(style, cur);
+    
 #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) {
@@ -1537,8 +1554,15 @@ xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur) {
        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
index 63a7ed8..8d1dd03 100644 (file)
@@ -51,6 +51,40 @@ 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;
+
+static const xmlChar *xsltLibxsltDataElementNameMeta =
+    (const xmlChar *) "meta";
+
+static const xmlChar *xsltLibxsltDataElementNamespaceMeta =
+    (const xmlChar *) XSLT_DEFAULT_URL;
+
+static const xmlChar *xsltUserDataElemMarker =
+    (const xmlChar *) "User Data Element";
+
+/*
+* 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";
+
+#endif
+
 /*
  * Harmless but avoiding a problem when compiling against a
  * libxml <= 2.3.11 without LIBXML_DEBUG_ENABLED
@@ -75,11 +109,39 @@ double xmlXPathStringEvalNumber(const xmlChar *str);
     (((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 prefix to push on the stack
+ * @value:  the excluded namespace name to push on the stack
  *
- * Push an excluded prefix on the stack
+ * Push an excluded namespace name on the stack
  *
  * Returns the new index in the stack or 0 in case of error
  */
@@ -135,6 +197,7 @@ exclPrefixPop(xsltStylesheetPtr style)
     style->exclPrefixTab[style->exclPrefixNr] = 0;
     return (ret);
 }
+#endif
 
 /************************************************************************
  *                                                                     *
@@ -270,7 +333,7 @@ xsltFreeDecimalFormatList(xsltStylesheetPtr self)
 
 /**
  * xsltDecimalFormatGetByName:
- * @sheet: the XSLT stylesheet
+ * @style: the XSLT stylesheet
  * @name: the decimal-format name to find
  *
  * Find decimal-format by name
@@ -278,21 +341,21 @@ xsltFreeDecimalFormatList(xsltStylesheetPtr self)
  * Returns the xsltDecimalFormatPtr
  */
 xsltDecimalFormatPtr
-xsltDecimalFormatGetByName(xsltStylesheetPtr sheet, xmlChar *name)
+xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name)
 {
     xsltDecimalFormatPtr result = NULL;
 
     if (name == NULL)
-       return sheet->decimalFormat;
+       return style->decimalFormat;
 
-    while (sheet != NULL) {
-       for (result = sheet->decimalFormat->next;
+    while (style != NULL) {
+       for (result = style->decimalFormat->next;
             result != NULL;
             result = result->next) {
            if (xmlStrEqual(name, result->name))
                return result;
        }
-       sheet = xsltNextImport(sheet);
+       style = xsltNextImport(style);
     }
     return result;
 }
@@ -331,8 +394,11 @@ xsltFreeTemplate(xsltTemplatePtr template) {
     if (template == NULL)
        return;
     if (template->match) xmlFree(template->match);
-    if (template->name) xmlFree(template->name);
-    if (template->nameURI) xmlFree(template->nameURI);
+/*
+*   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);
@@ -359,69 +425,247 @@ xsltFreeTemplateList(xsltTemplatePtr template) {
     }
 }
 
+#ifdef XSLT_REFACTORED
 /**
- * xsltNewStylesheet:
+ * xsltCompilerCreate:
  *
- * Create a new XSLT Stylesheet
+ * Create an XSLT compiler context.
  *
- * Returns the newly allocated xsltStylesheetPtr or NULL in case of error
+ * Returns the allocated xsltCompilerCtxtPtr or NULL in case of error.
  */
-xsltStylesheetPtr
-xsltNewStylesheet(void) {
-    xsltStylesheetPtr cur;
-#ifdef XSLT_REFACTORED
-    xsltCompilerCtxtPtr cctxt;
-#endif
+static xsltCompilerCtxtPtr
+xsltCompilerCreate(xsltStylesheetPtr style) {
+    xsltCompilerCtxtPtr ret;
 
-    cur = (xsltStylesheetPtr) xmlMalloc(sizeof(xsltStylesheet));
-    if (cur == NULL) {
-       xsltTransformError(NULL, NULL, NULL,
-               "xsltNewStylesheet : malloc failed\n");
+    ret = (xsltCompilerCtxtPtr) xmlMalloc(sizeof(xsltCompilerCtxt));
+    if (ret == NULL) {
+       xsltTransformError(NULL, style, NULL,
+           "xsltCompilerCreate: allocation of compiler "
+           "context failed.\n");
        return(NULL);
     }
-    memset(cur, 0, sizeof(xsltStylesheet));
-#ifdef XSLT_REFACTORED
+    memset(ret, 0, sizeof(xsltCompilerCtxt));
+
+    ret->errSeverity = XSLT_ERROR_SEVERITY_ERROR;
+
+    style->compCtxt = (void *) ret;
+    ret->style = style;
+    ret->tmpList = xsltPointerListCreate(20);
+    if (ret->tmpList == NULL) {
+       xmlFree(ret);
+       return(NULL);
+    }
+    ret->dict = style->dict;
+    return(ret);
+}
+
+static void
+xsltCompilerCtxtFree(xsltCompilerCtxtPtr cctxt)
+{    
+    if (cctxt == NULL)
+       return;
     /*
-    * Create the compiler context.
+    * Free node-infos.
     */
-    cctxt = (xsltCompilerCtxtPtr) xmlMalloc(sizeof(xsltCompilerCtxt));
-    if (cctxt == NULL) {
-       xmlFree(cur);
+    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);
+    xmlFree(cctxt);
+}
+
+static void
+xsltFreeNamespaceMap(xsltNsMapPtr item)
+{
+    xsltNsMapPtr tmp;
+    
+    while (item) {
+       tmp = item;
+       item = item->next;
+       xmlFree(tmp);
+    } 
+    return;
+}
+
+static xsltNsMapPtr
+xsltNewNamespaceMapItem(xsltCompilerCtxtPtr cctxt,                     
+                       xmlDocPtr doc,
+                       xmlNodePtr elem,
+                       xmlNsPtr ns)
+{
+    xsltNsMapPtr ret;
+
+    if ((cctxt == NULL) || (doc == NULL) || (elem == 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);
+}
+
+static void
+xsltFreePrincipalStylesheetData(xsltPrincipalStylesheetDataPtr data)
+{
+    if (data == NULL)
+       return;
+
+    if (data->inScopeNamespaces != NULL) {
+       int i;
+       xsltNsListPtr nsi;
+       xsltPointerListPtr list =
+           (xsltPointerListPtr) data->inScopeNamespaces;
+
+       for (i = 0; i < list->number; i++) {
+           /*
+           * REVISIT TODO: Free info of in-scope namespaces.
+           */
+           nsi = (xsltNsListPtr) 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;
+    }
+    xsltFreeNamespaceMap(data->nsMap);
+    xmlFree(data);
+}
+
+static xsltPrincipalStylesheetDataPtr
+xsltNewPrincipalStylesheetData(void)
+{
+    xsltPrincipalStylesheetDataPtr ret;
+
+    ret = (xsltPrincipalStylesheetDataPtr)
+       xmlMalloc(sizeof(xsltPrincipalStylesheetData));
+    if (ret == NULL) {
        xsltTransformError(NULL, NULL, NULL,
-               "xsltNewStylesheet : malloc of compilation context failed\n");
+           "xsltNewPrincipalStylesheetData: memory allocation failed.\n");
        return(NULL);
     }
-    memset(cctxt, 0, sizeof(xsltCompilerCtxt));
-    cur->compCtxt = (void *) cctxt;
-    cctxt->sheet = cur;
-#endif
+    memset(ret, 0, sizeof(xsltPrincipalStylesheetData));
+    
     /*
-    * TODO: This here seems to be the best place where to create
-    *   the compilation context, right?
-    */
-           
-    cur->omitXmlDeclaration = -1;
-    cur->standalone = -1;
-    cur->decimalFormat = xsltNewDecimalFormat(NULL);
-    cur->indent = -1;
-    cur->errors = 0;
-    cur->warnings = 0;
-    cur->exclPrefixNr = 0;
-    cur->exclPrefixMax = 0;
-    cur->exclPrefixTab = NULL;
-    cur->extInfos = NULL;
-    cur->extrasNr = 0;
-    cur->internalized = 1;
-    cur->literal_result = 0;
-    cur->dict = xmlDictCreate();
+    * 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 element 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");
+       "creating dictionary for stylesheet\n");
 #endif
 
     xsltInit();
 
-    return(cur);
+    return(ret);
+
+internal_err:
+    if (ret != NULL)
+       xsltFreeStylesheet(ret);
+    return(NULL);
 }
 
 /**
@@ -495,149 +739,190 @@ xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
 
 /**
  * xsltFreeStylesheetList:
- * @sheet:  an XSLT stylesheet list
+ * @style:  an XSLT stylesheet list
  *
- * Free up the memory allocated by the list @sheet
+ * Free up the memory allocated by the list @style
  */
 static void
-xsltFreeStylesheetList(xsltStylesheetPtr sheet) {
+xsltFreeStylesheetList(xsltStylesheetPtr style) {
     xsltStylesheetPtr next;
 
-    while (sheet != NULL) {
-       next = sheet->next;
-       xsltFreeStylesheet(sheet);
-       sheet = next;
+    while (style != NULL) {
+       next = style->next;
+       xsltFreeStylesheet(style);
+       style = next;
     }
 }
 
-#ifdef XSLT_REFACTORED
 /**
- * xsltFreeInScopeNamespaces:
- * @sheet:  an XSLT stylesheet
+ * xsltCleanupStylesheetTree:
+ *
+ * @doc: the document-node
+ * @node: the element where the stylesheet is rooted at
  *
- * Frees the list of in-scope namespace lists.
+ * 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 void
-xsltFreeInScopeNamespaces(xsltStylesheetPtr sheet)
+static int
+xsltCleanupStylesheetTree(xmlDocPtr doc, xmlNodePtr rootElem)
 {
-    if (sheet->inScopeNamespaces == NULL)
-       return;
-    else {
-       int i;
-       xsltNsListPtr nsi;
-       xsltPointerListPtr list = sheet->inScopeNamespaces;
+    xmlNodePtr cur;
 
-       for (i = 0; i < list->number; i++) {
+    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) {
            /*
-           * REVISIT TODO: Free info of in-scope namespaces.
+           * Clear the PSVI field.
            */
-           nsi = (xsltNsListPtr) list->items[i];
-           if (nsi->list != NULL)
-               xmlFree(nsi->list);
-           xmlFree(nsi);
+           cur->psvi = NULL;
+           if (cur->children) {
+               cur = cur->children;
+               continue;
+           }
        }
-       xsltPointerListFree(list);
-       sheet->inScopeNamespaces = NULL;
-    }
-    return;
-}
 
-static void
-xsltCompilerCtxtFree(xsltCompilerCtxtPtr cctxt)
-{    
-    if (cctxt == NULL)
-       return;
-    /*
-    * Free node-infos.
-    */
-    if (cctxt->inodeList != NULL) {
-       xsltCompilerNodeInfoPtr tmp, cur = cctxt->inodeList;
-       while (cur != NULL) {
-           tmp = cur;
+leave_node:
+       if (cur == rootElem)
+           break;
+       if (cur->next != NULL)
            cur = cur->next;
-           xmlFree(tmp);
+       else {
+           cur = cur->parent;
+           if (cur == NULL)
+               break;
+           goto leave_node;
        }
     }
-    xmlFree(cctxt);
+    return(0);
 }
-#endif
 
 /**
  * xsltFreeStylesheet:
- * @sheet:  an XSLT stylesheet
+ * @style:  an XSLT stylesheet
  *
- * Free up the memory allocated by @sheet
+ * Free up the memory allocated by @style
  */
 void
-xsltFreeStylesheet(xsltStylesheetPtr sheet)
+xsltFreeStylesheet(xsltStylesheetPtr style)
 {
-    if (sheet == NULL)
+    if (style == NULL)
         return;
-
-    xsltFreeKeys(sheet);
-    xsltFreeExts(sheet);
-    xsltFreeTemplateHashes(sheet);
-    xsltFreeDecimalFormatList(sheet);
-    xsltFreeTemplateList(sheet->templates);
-    xsltFreeAttributeSetsHashes(sheet);
-    xsltFreeNamespaceAliasHashes(sheet);
+    
 #ifdef XSLT_REFACTORED
-    if (sheet->inScopeNamespaces != NULL)
-       xsltFreeInScopeNamespaces(sheet);
+    /*
+    * Start with a cleanup of the main stylesheet's doc.
+    */
+    if ((style->principal == style) && (style->doc))
+       xsltCleanupStylesheetTree(style->doc,
+           xmlDocGetRootElement(style->doc));
+    /*
+    * 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);        
+    }
+#else
+    /*
+    * Start with a cleanup of the main stylesheet's doc.
+    */
+    if ((style->parent == NULL) && (style->doc))
+       xsltCleanupStylesheetTree(style->doc,
+           xmlDocGetRootElement(style->doc));
 #endif
-    xsltFreeStyleDocuments(sheet);
-    xsltFreeStylePreComps(sheet);
-    xsltShutdownExts(sheet);
-    if (sheet->doc != NULL)
-        xmlFreeDoc(sheet->doc);
-    if (sheet->variables != NULL)
-        xsltFreeStackElemList(sheet->variables);
-    if (sheet->cdataSection != NULL)
-        xmlHashFree(sheet->cdataSection, NULL);
-    if (sheet->stripSpaces != NULL)
-        xmlHashFree(sheet->stripSpaces, NULL);
-    if (sheet->nsHash != NULL)
-        xmlHashFree(sheet->nsHash, NULL);
-
-    if (sheet->exclPrefixTab != NULL)
-        xmlFree(sheet->exclPrefixTab);
-    if (sheet->method != NULL)
-        xmlFree(sheet->method);
-    if (sheet->methodURI != NULL)
-        xmlFree(sheet->methodURI);
-    if (sheet->version != NULL)
-        xmlFree(sheet->version);
-    if (sheet->encoding != NULL)
-        xmlFree(sheet->encoding);
-    if (sheet->doctypePublic != NULL)
-        xmlFree(sheet->doctypePublic);
-    if (sheet->doctypeSystem != NULL)
-        xmlFree(sheet->doctypeSystem);
-    if (sheet->mediaType != NULL)
-        xmlFree(sheet->mediaType);
-    if (sheet->attVTs)
-        xsltFreeAVTList(sheet->attVTs);
-
-    if (sheet->imports != NULL)
-        xsltFreeStylesheetList(sheet->imports);
+
+    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
     /*
-    * TODO: Just a paranoid cleanup, in case the compilation
-    *   context was not freed after the compilation.
+    * If this is the principal stylesheet, then
+    * free its internal data.
     */
-    if (sheet->compCtxt != NULL) {
-       xsltCompilerCtxtFree((xsltCompilerCtxtPtr) sheet->compCtxt);
-    }
+    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(sheet->dict);
+    xmlDictFree(style->dict);
 
-    memset(sheet, -1, sizeof(xsltStylesheet));
-    xmlFree(sheet);
+    memset(style, -1, sizeof(xsltStylesheet));
+    xmlFree(style);
 }
 
 /************************************************************************
@@ -646,6 +931,11 @@ xsltFreeStylesheet(xsltStylesheetPtr sheet)
  *                                                                     *
  ************************************************************************/
 
+#ifdef XSLT_REFACTORED
+    /*
+    * This is now performed in an optimized way in xsltParseXSLTTemplate.
+    */
+#else
 /**
  * xsltGetInheritedNsList:
  * @style:  the stylesheet
@@ -676,7 +966,7 @@ xsltGetInheritedNsList(xsltStylesheetPtr style,
     *          <xsl:stylesheet ...    
     * </doc>
     * Will have foo="urn:test:foo" in the list.
-    * Is this a bug?
+    * Is this OK?
     */
 
     if ((style == NULL) || (template == NULL) || (node == NULL) ||
@@ -688,6 +978,7 @@ xsltGetInheritedNsList(xsltStylesheetPtr style,
             while (cur != NULL) {
                if (xmlStrEqual(cur->href, XSLT_NAMESPACE))
                    goto skip_ns;
+
                if ((cur->prefix != NULL) &&
                    (xsltCheckExtPrefix(style, cur->prefix)))
                    goto skip_ns;
@@ -751,6 +1042,7 @@ skip_ns:
     }
     return (nbns);
 }
+#endif /* else of XSLT_REFACTORED */
 
 /**
  * xsltParseStylesheetOutput:
@@ -842,7 +1134,7 @@ xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)
         } else {
            xsltTransformError(NULL, style, cur,
                              "invalid value for standalone: %s\n", prop);
-            if (style != NULL) style->warnings++;
+            style->errors++;
         }
         xmlFree(prop);
     }
@@ -856,7 +1148,7 @@ xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)
         } else {
            xsltTransformError(NULL, style, cur,
                              "invalid value for indent: %s\n", prop);
-            if (style != NULL) style->warnings++;
+            style->errors++;
         }
         xmlFree(prop);
     }
@@ -871,7 +1163,7 @@ xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)
            xsltTransformError(NULL, style, cur,
                              "invalid value for omit-xml-declaration: %s\n",
                              prop);
-            if (style != NULL) style->warnings++;
+            style->errors++;
         }
         xmlFree(prop);
     }
@@ -894,34 +1186,51 @@ xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)
             while ((*end != 0) && (!IS_BLANK(*end)))
                 end++;
             element = xmlStrndup(element, end - element);
-            if (element) {
-               const xmlChar *URI;
+            if (element) {             
 #ifdef WITH_XSLT_DEBUG_PARSING
                 xsltGenericDebug(xsltGenericDebugContext,
                                  "add cdata section output element %s\n",
                                  element);
 #endif
-
-               URI = xsltGetQNameURI(cur, &element);
-               if (element == NULL) {
-                   if (style != NULL) style->errors++;
+               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 {
-                   xmlNsPtr ns;
-                   
-                   xmlHashAddEntry2(style->cdataSection, element, URI,
-                                    (void *) "cdata");
-                   /*
-                    * if prefix is NULL, we must check whether it's
-                    * necessary to also put in the name of the default
-                    * namespace.
-                    */
-                   if (URI == NULL) {
-                       ns = xmlSearchNs(style->doc, cur, NULL);
-                       if (ns != NULL)  
-                           xmlHashAddEntry2(style->cdataSection, element,
-                               ns->href, (void *) "cdata");
+                   const xmlChar *URI;
+
+                   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);
                    }
-                   xmlFree(element);
                }
             }
             element = end;
@@ -935,6 +1244,9 @@ xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)
            xmlFree(style->mediaType);
        style->mediaType = prop;
     }
+    if (cur->children != NULL) {
+       xsltParseContentError(style, cur->children);
+    }
 }
 
 /**
@@ -1046,6 +1358,9 @@ xsltParseStylesheetDecimalFormat(xsltStylesheetPtr style, xmlNodePtr cur)
        if (format->patternSeparator != NULL) xmlFree(format->patternSeparator);
        format->patternSeparator  = prop;
     }
+    if (cur->children != NULL) {
+       xsltParseContentError(style, cur->children);
+    }
 }
 
 /**
@@ -1106,8 +1421,13 @@ xsltParseStylesheetPreserveSpace(xsltStylesheetPtr style, xmlNodePtr cur) {
        element = end;
     }
     xmlFree(elements);
+    if (cur->children != NULL) {
+       xsltParseContentError(style, cur->children);
+    }
 }
 
+#ifdef XSLT_REFACTORED
+#else
 /**
  * xsltParseStylesheetExtPrefix:
  * @style:  the XSLT stylesheet
@@ -1122,7 +1442,6 @@ xsltParseStylesheetPreserveSpace(xsltStylesheetPtr style, xmlNodePtr cur) {
  *      literal result element 
  *   3) TODO: an extension element."
  */
-
 static void
 xsltParseStylesheetExtPrefix(xsltStylesheetPtr style, xmlNodePtr cur,
                             int isXsltElem) {
@@ -1178,6 +1497,7 @@ xsltParseStylesheetExtPrefix(xsltStylesheetPtr style, xmlNodePtr cur,
     }
     xmlFree(prefixes);
 }
+#endif /* else of XSLT_REFACTORED */
 
 /**
  * xsltParseStylesheetStripSpace:
@@ -1237,8 +1557,13 @@ xsltParseStylesheetStripSpace(xsltStylesheetPtr style, xmlNodePtr cur) {
        element = end;
     }
     xmlFree(elements);
+    if (cur->children != NULL) {
+       xsltParseContentError(style, cur->children);
+    }
 }
 
+#ifdef XSLT_REFACTORED
+#else
 /**
  * xsltParseStylesheetExcludePrefix:
  * @style:  the XSLT stylesheet
@@ -1307,55 +1632,109 @@ xsltParseStylesheetExcludePrefix(xsltStylesheetPtr style, xmlNodePtr cur,
     xmlFree(prefixes);
     return(nb);
 }
+#endif /* else of XSLT_REFACTORED */
 
 #ifdef XSLT_REFACTORED
 
-static xsltCompilerNodeInfoPtr
-xsltCompilerNodePush(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
+/*
+* 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;
+
     if ((cctxt->inode != NULL) && (cctxt->inode->next != NULL)) {      
-       cctxt->inode = cctxt->inode->next;
+       inode = cctxt->inode->next;
     } else if ((cctxt->inode == NULL) && (cctxt->inodeList != NULL)) {
-       cctxt->inode = cctxt->inodeList;        
+       inode = cctxt->inodeList;       
     } else {
        /*
        * Create a new node-info.
        */
-       cctxt->inode = (xsltCompilerNodeInfoPtr)
+       inode = (xsltCompilerNodeInfoPtr)
            xmlMalloc(sizeof(xsltCompilerNodeInfo));
-       if (cctxt->inode == NULL) {
-           xsltTransformError(NULL, cctxt->sheet, NULL,
+       if (inode == NULL) {
+           xsltTransformError(NULL, cctxt->style, NULL,
                "xsltCompilerNodePush: malloc failed.\n");
            return(NULL);
        }
-       memset(cctxt->inode, 0, sizeof(xsltCompilerNodeInfo));
+       memset(inode, 0, sizeof(xsltCompilerNodeInfo));
        if (cctxt->inodeList == NULL)
-           cctxt->inodeList = cctxt->inode;
+           cctxt->inodeList = inode;
        else {
-           cctxt->inodeLast->next = cctxt->inode;
-           cctxt->inode->prev = cctxt->inodeLast;
+           cctxt->inodeLast->next = inode;
+           inode->prev = cctxt->inodeLast;
        }
-       cctxt->inodeLast = cctxt->inode;
+       cctxt->inodeLast = inode;
+       cctxt->maxNodeInfos++;
     }
     /*
     * REVISIT TODO: Keep the reset always complete.
     */
     cctxt->depth++;
-    cctxt->inode->depth = cctxt->depth;
-    cctxt->inode->templ = NULL;
-    cctxt->inode->item = NULL;
-    cctxt->inode->node = node;
+
     /*
-    * Inherit the list of in-scope namespaces.
+    * NOTE: Be carefull with the @node, since it might be
+    *  a doc-node.
     */
-    if (cctxt->inode->prev != NULL)
-       cctxt->inode->inScopeNS = cctxt->inode->prev->inScopeNS;
-    else
-       cctxt->inode->inScopeNS = NULL;
+    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;
     
-    return(cctxt->inode);
+    if (inode->prev != NULL) {
+       /*
+       * Inherit the following information:
+       */
+       inode->inScopeNs = inode->prev->inScopeNs;
+       /*
+       * in-scope namespaces
+       */
+       inode->exclResultNs = inode->prev->exclResultNs;
+       /*
+       * extension-element namespaces
+       */
+       inode->extElemNs = inode->prev->extElemNs;
+       /*
+       * whitespace perservation
+       */
+       inode->preserveWhitespace = inode->prev->preserveWhitespace;
+       /*
+       * forwards-compatible mode
+       */
+       inode->forwardsCompat = inode->prev->forwardsCompat;    
+    } else {
+       inode->inScopeNs = NULL;
+       inode->exclResultNs = NULL;
+       inode->extElemNs = NULL;
+       inode->preserveWhitespace = 0;
+       inode->forwardsCompat = 0;
+    }
+    cctxt->inode = inode;
+    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)
 {    
@@ -1363,134 +1742,931 @@ xsltCompilerNodePop(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
        xmlGenericError(xmlGenericErrorContext,
            "xsltCompilerNodePop: Top-node mismatch.\n");
        return;
-    }          
-    if (cctxt->inode->node != node)
+    }
+    /*
+    * NOTE: Be carefull with the @node, since it might be
+    *  a doc-node.
+    */
+    if (cctxt->inode->node != node) {
        xmlGenericError(xmlGenericErrorContext,
        "xsltCompilerNodePop: Node mismatch.\n");
-    if (cctxt->inode->depth != cctxt->depth)
+       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 xsltNsListPtr
+xsltCompilerBuildInScopeNsList(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
+{
+    xsltNsListPtr nsi = NULL;
+    xmlNsPtr *list = NULL;
+    /*
+    * 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.
+    */
+    list = xmlGetNsList(node->doc, node);
+    if (list == NULL)
+       return(NULL);
+    /*
+    * Create the info-structure.
+    */
+    nsi = (xsltNsListPtr) xmlMalloc(sizeof(xsltNsList));
+    if (nsi == NULL) { 
+       xsltTransformError(NULL, cctxt->style, NULL,
+           "xsltCompilerBuildInScopeNsList: malloc failed.\n");
+       goto internal_err;
+    }
+    memset(nsi, 0, sizeof(xsltNsList));
+    nsi->list = list;
+    /*
+    * Eval the number of ns-decls; this is used to speed up
+    * XPath-context initialization.
+    */
+    while (list[nsi->number] != NULL)
+       nsi->number++;
+    /*
+    * 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;
+    }     
+
+    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);
+}
 
 /**
- * xsltPrecomputeStylesheet:
- * @style:  the XSLT stylesheet
- * @cur:  the current child list
- *
- * Clean-up the stylesheet content from unwanted ignorable blank nodes
- * and run the preprocessing of all XSLT constructs.
+ * xsltCompilerUtilsCreateMergedList:
+ * @dest: the destination list (optional)
+ * @first: the first list
+ * @second: the second list (optional)
  *
- * and process xslt:text
+ * Appends the content of @second to @first into @destination.
+ * If @destination is NULL a new list will be created.
  *
- * URGENT TODO: In order to avoid separation of the parsing of the stylesheet's
- *   node-tree, this should either only strip whitespace-only text-nodes,
- *   or it should be merged completely with the stylesheet-parsing
- *   functions (e.g. xsltParseStylesheetTop()).
+ * Returns the merged list of items or NULL if there's nothing to merge.
  */
-static void
-xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur) {
-    xmlNodePtr delete;
-    int internalize = 0;
-#ifdef XSLT_REFACTORED
-    xsltCompilerCtxtPtr cctxt;
-#endif
+static xsltPointerListPtr
+xsltCompilerUtilsCreateMergedList(xsltPointerListPtr first,
+                           xsltPointerListPtr second)
+{
+    xsltPointerListPtr ret;
+    size_t num;
 
-    if ((style == NULL) || (cur == NULL)
-#ifdef XSLT_REFACTORED
-       ||(style->compCtxt == NULL)
-#endif
-       )
-        return;
+    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);
+}
 
-    if ((cur->doc != NULL) && (style->dict != NULL) &&
-        (cur->doc->dict == style->dict))
+/*
+* 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 isXsltElem)
+{    
+    xsltPointerListPtr list = NULL;
+    xmlChar *value = NULL;
+
+    if ((cctxt == NULL) || (node == NULL))
+       return(NULL);
+    
+    if (isXsltElem)
+       value = xmlGetNsProp(node, BAD_CAST "exclude-result-prefixes", NULL);
+    else
+       value = xmlGetNsProp(node, BAD_CAST "exclude-result-prefixes",
+           XSLT_NAMESPACE);
+
+    if (value == NULL)
+       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.
+    */
+    if (xsltPointerListAddSize(
+       cctxt->psData->exclResultNamespaces, list, 5) == -1)
+    {
+       xsltPointerListFree(list);
+       list = NULL;
+       goto exit;
+    }
+
+exit:
+    if (value != NULL)
+       xmlFree(value);
+    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 isXsltElem)
+{    
+    xsltPointerListPtr list = NULL;
+    xmlChar *value;
+    int i;
+
+    if ((cctxt == NULL) || (node == NULL))
+       return(NULL);
+
+    if (isXsltElem)
+       value = xmlGetNsProp(node, BAD_CAST "extension-element-prefixes", NULL);
+    else
+       value = xmlGetNsProp(node, BAD_CAST "extension-element-prefixes",
+           XSLT_NAMESPACE);
+
+    if (value == NULL) 
+       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;
+    }
+
+exit:
+    if (value != NULL)
+       xmlFree(value);
+    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 isXsltElem)
+{
+    xmlChar *value;
+
+    if ((cctxt == NULL) || (node == NULL))
+       return(-1);
+
+    if (isXsltElem)
+       value = xmlGetNsProp(node, BAD_CAST "version", NULL);
+    else
+       value = xmlGetNsProp(node, BAD_CAST "version", XSLT_NAMESPACE);
+
+    if (value == NULL) 
+       return(0);
+    
+    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;
+    }
+    xmlFree(value);
+    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;
+    xsltNsMapPtr nsMapItem;
+
+    if ((cctxt == NULL) || (cctxt->style == NULL) ||
+       (node == NULL) || (node->type != XML_ELEMENT_NODE))
+        return(-1);
+
+    doc = node->doc;
+    if (doc == NULL)
+       return(-1);
+
+    style = cctxt->style;
+    if ((style->dict != NULL) && (doc->dict == style->dict))
        internalize = 1;
     else
         style->internalized = 0;
-#ifdef XSLT_REFACTORED
-    cctxt = (xsltCompilerCtxtPtr) style->compCtxt;    
-#endif
+
     /*
-     * This content comes from the stylesheet
-     * For stylesheets, the set of whitespace-preserving
-     * element names consists of just xsl:text.
-     */
-    delete = NULL;
+    * 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 (delete != NULL) {
+       if (deleteNode != NULL) {
+
 #ifdef WITH_XSLT_DEBUG_BLANKS
            xsltGenericDebug(xsltGenericDebugContext,
-            "xsltPrecomputeStylesheet: removing ignorable blank node\n");
+            "xsltParsePreprocessStylesheetTree: removing node\n");
 #endif
-           xmlUnlinkNode(delete);
-           xmlFreeNode(delete);
-           delete = NULL;
+           xmlUnlinkNode(deleteNode);
+           xmlFreeNode(deleteNode);
+           deleteNode = NULL;
        }
        if (cur->type == XML_ELEMENT_NODE) {
-           int exclPrefixes;       
+           
+           /*
+           * Clear the PSVI field.
+           */
+           cur->psvi = NULL;
 
-#ifdef XSLT_REFACTORED
            xsltCompilerNodePush(cctxt, cur);
-#endif
+
+           inXSLText = 0;
+           textNode = NULL;        
+           findSpaceAttr = 1;      
+           cctxt->inode->stripWhitespace = 0;
            /*
-            * Internalize attributes values.
-            */
-           if ((internalize) && (cur->properties != NULL)) {
-               xmlAttrPtr prop = cur->properties;
-               xmlNodePtr txt;
+           * TODO: I'd love to use a string pointer comparison here :-/
+           */
+           if (IS_XSLT_ELEM(cur)) {
+               if (cur->ns->href != nsNameXSLT) {
+                   nsMapItem = xsltNewNamespaceMapItem(cctxt,                  
+                       doc, cur, cur->ns);
+                   if (nsMapItem == NULL)
+                       goto internal_err;
+                   cur->ns->href = nsNameXSLT;
+               }
 
-               while (prop != NULL) {
-                   txt = prop->children;
-                   if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
-                       (txt->content != NULL) &&
-                       (!xmlDictOwns(style->dict, txt->content))) {
-                       xmlChar *tmp;
+               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; */
 
-                       /*
-                        * 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;
+               /*
+               * 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;
                        }
-                   }
-                   prop = prop->next;
+
+                       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:
            /*
-           * TODO: "exclude-result-prefixes"
-           *   SPEC 1.0:
-           *   "exclude-result-prefixes" is only allowed on literal
-           *   result elements and "xsl:exclude-result-prefixes" only
-           *   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."
+           * Process attributes.
+           * ------------------
            */
-           if (IS_XSLT_ELEM(cur)) {
-               exclPrefixes = 0;
-#ifdef XSLT_REFACTORED
-               if ((cctxt->depth == 0) && (cur->nsDef != NULL)) {
-                   /*
-                   * In every case, we need the in-scope namespaces of the
-                   * element, where the stylesheet is rooted at.
-                   * Otherwise we need to pre-compute the in-scope namespaces
-                   * only if there's a new ns-decl.
+           if (cur->properties != NULL) {
+               if (cur->children == NULL)
+                   findSpaceAttr = 0;
+               attr = cur->properties;
+               do {
+                   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.
+                   * ----------------------------
                    */
-                   cctxt->inode->inScopeNS =
-                       xsltCompilerGetInScopeNSInfo(cctxt, cur);
+                   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;
                }
-#endif         
+           }
+           if (IS_XSLT_ELEM(cur)) {
+               exclPrefixes = 0;
                xsltStylePreCompute(style, cur);
                if (IS_XSLT_NAME(cur, "text")) {
                    for (;exclPrefixes > 0;exclPrefixes--)
@@ -1498,25 +2674,9 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur) {
                    goto skip_children;
                }
            } else {
-#ifdef XSLT_REFACTORED
-               if (cctxt->depth == 0)
-                   cctxt->inode->inScopeNS =
-                       xsltCompilerGetInScopeNSInfo(cctxt, cur);
-#endif
                exclPrefixes = xsltParseStylesheetExcludePrefix(style, cur, 0);
            }
-
-           /*
-            * Remove excluded prefixes
-            * TODO BUG:
-            *   This will incorrectly apply excluded-result-prefixes
-            *   of the including stylesheet to the included stylesheet.
-            *   We need to localize the list of excluded-prefixes for
-            *   every processed stylesheet.
-            * SPEC 1.0: "a subtree rooted at an xsl:stylesheet element
-            *   does not include any stylesheets imported or included by
-            *   children of that xsl:stylesheet element."
-            */
+                    
            if ((cur->nsDef != NULL) && (style->exclPrefixNr > 0)) {
                xmlNsPtr ns = cur->nsDef, prev = NULL, next;
                xmlNodePtr root = NULL;
@@ -1547,188 +2707,1093 @@ xsltPrecomputeStylesheet(xsltStylesheetPtr style, xmlNodePtr cur) {
                                break;
                            }
                        }
-                       if (moved == 0)
-                           prev = ns;
-                       ns = next;
+                       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_IN_XSLT_NS(elem)))
+       return(-1);
+    /*
+    * Detection of handled content of extension elements.
+    */
+    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_IN_XSLT_NS(child)) {
+                   xsltStyleType type;
+
+                   type = xsltGetXSLTElementTypeByNode(cctxt, child);
+                   if ((type == XSLT_FUNC_WITHPARAM) ||
+                       (type == XSLT_FUNC_SORT))
+                   {
+                       /* cctxt->inode->type = type; */
+                       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_IN_XSLT_NS(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) {
+       xsltTransformError(NULL, cctxt->style, elem,
+           "This XSLT element must have no content.\n");
+       cctxt->style->errors++;
+    }
+    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_IN_XSLT_NS(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_IN_XSLT_NS(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 int
+xsltParseForwardsCompatUnexpectedXSLTElem(xsltCompilerCtxtPtr cctxt,
+                                         xmlNodePtr node)
+{
+    if ((cctxt == NULL) || (node == NULL))
+       return(-1);
+
+    /*
+    * Detection of handled content of extension elements.
+    */
+    if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
+       cctxt->inode->extContentHandled = 1;
+    }
+
+    node->psvi = NULL;
+    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_IN_XSLT_NS(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 elements.
+    */
+    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 elements
+    * 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) {
+               /*
+               * Process 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_IN_XSLT_NS(cur)) { 
+               /*
+               * TODO: Using the XSLT-marker is still not stable yet.
+               */
+               /* if (cur->psvi == xsltXSLTElemMarker) { */        
+               /*
+               * This is element in the XSLT namespace.
+               * =====================================
+               */
+               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:                    
+                       /* cctxt->inode->type = type; */
+                       /*
+                       * Parse the XSLT element.
+                       */
+                       cctxt->inode->curChildType = type;
+                       xsltParseAnyXSLTElem(cctxt, cur);
+                       break;
+                   default:
+                       cur->psvi = NULL;
+                       /*
+                       * Ignore unknown elements in the
+                       * XSLT namespace if in forwards-compatible
+                       * mode.
+                       */
+                       if (cctxt->inode->forwardsCompat) {                         
+                           /*
+                           * This will parse xsl:fallback elements.
+                           */
+                           xsltParseForwardsCompatUnexpectedXSLTElem(
+                               cctxt, cur);
+                       } else {
+                           xsltParseContentError(cctxt->style, cur);
+                       }
+                       cur = cur->next;
+                       continue;
+               }
+           } else {
+               /*
+               * This is a non-XSLT element.
+               * ==========================
+               */
+               xsltCompilerNodePush(cctxt, cur);               
+               /*
+               * The current element is either a literal result element
+               * or an extension element.
+               *
+               * 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, 0);
+               /*
+               * Eval if we have an extension element here.
+               */
+               if ((cur->ns != NULL) &&
+                   (cctxt->inode->extElemNs != NULL) &&
+                   (xsltCheckExtPrefix(cctxt->style, cur->ns->href) == 1))
+               {
+                   /*
+                   * This is an extension element.
+                   * ============================
+                   * 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: (xsltParseNonXSLTElement) "
+                           " 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 element 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 {
+                   /*
+                   * This is a 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
+                   */
+                   cctxt->inode->category = XSLT_ELEMENT_CATEGORY_LR;              
+                   if (cur->properties != NULL) {
+                       /*
+                       * Attribute "xsl:exclude-result-prefixes".
+                       */
+                       cctxt->inode->exclResultNs =
+                           xsltParseExclResultPrefixes(cctxt, cur,
+                               cctxt->inode->exclResultNs, 0);
+                       /*
+                       * Attribute "xsl:version".
+                       */
+                       xsltParseAttrXSLTVersion(cctxt, cur, 0);
+                   }
+                   /*
+                   * TODO: Create the literal result item.
+                   * TODO: Check what this *defaultAlias* mechanism does. Do we
+                   *  need to create the compiled item after such namespace
+                   *  conversion?
+                   */
+                   if ((cur->ns == NULL) && (cctxt->style->defaultAlias != NULL) &&
+                       (cur->type == XML_ELEMENT_NODE))
+                   {
+                       
+                       cur->ns = xmlSearchNsByHref(cur->doc, cur,
+                           cctxt->style->defaultAlias);
+                   }
+                   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);
                    }
                }
-           }
-
-           /*
-            * 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) {
-                   delete = 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)) {
-           delete = 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;
+               * Leave the non-XSLT element.
+               */
+               xsltCompilerNodePop(cctxt, cur);
            }
        }
-#ifdef XSLT_REFACTORED
-       if (cur->type == XML_ELEMENT_NODE) {
-           /* Leaving the scope of an element-node. */
-           xsltCompilerNodePop(cctxt, cur);
-       }
-#endif
-
-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);
+       cur = cur->next;
     }
-    if (delete != NULL) {
-#ifdef WITH_XSLT_DEBUG_PARSING
+    if (deleteNode != NULL) {
+#ifdef WITH_XSLT_DEBUG_BLANKS
        xsltGenericDebug(xsltGenericDebugContext,
-        "xsltPrecomputeStylesheet: removing ignorable blank node\n");
+           "xsltParseSequenceConstructor: removing xsl:text element\n");
 #endif
-       xmlUnlinkNode(delete);
-       xmlFreeNode(delete);
-       delete = NULL;
+       xmlUnlinkNode(deleteNode);
+       xmlFreeNode(deleteNode);
+       deleteNode = NULL;
     }
 }
 
 /**
- * xsltGatherNamespaces:
+ * xsltParseTemplateContent:
  * @style:  the XSLT stylesheet
+ * @templ:  the node containing the content to be parsed
  *
- * Browse the stylesheet and build the namspace hash table which
- * will be used for XPath interpretation. If needed do a bit of normalization
+ * 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;
 
-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.
-    * 
+    * Detection of handled content of extension elements.
     */
-    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;
-           }
-       }
+    if (XSLT_CCTXT(style)->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
+       XSLT_CCTXT(style)->inode->extContentHandled = 1;
+    }
 
+    if (templ->children != NULL) {     
+       xmlNodePtr child = templ->children;
        /*
-        * 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;
-       }
-       
+       * Process xsl:param elements, which can only occur as the
+       * immediate children of xsl:template (well, and of any
+       * user-defined extension element if needed).
+       */      
        do {
-           cur = cur->parent;
-           if (cur == NULL)
-               break;
-           if (cur == (xmlNodePtr) style->doc) {
-               cur = NULL;
-               break;
-           }
-           if (cur->next != NULL) {
-               cur = cur->next;
+           if ((child->type == XML_ELEMENT_NODE) &&
+               IS_IN_XSLT_NS(child) && IS_XSLT_NAME(child, "param"))
+           {
+               XSLT_CCTXT(style)->inode->curChildType = XSLT_FUNC_PARAM;
+               xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);
+           } else
                break;
-           }
-       } while (cur != NULL);
+           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
@@ -1738,7 +3803,6 @@ xsltGatherNamespaces(xsltStylesheetPtr style) {
  * Clean-up the template content from unwanted ignorable blank nodes
  * and process xslt:text
  */
-
 void
 xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
     xmlNodePtr cur, delete;
@@ -1761,6 +3825,13 @@ xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
        }
        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;
@@ -1837,8 +3908,10 @@ xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
                delete = cur;
                goto skip_children;
            }
-       } else if ((cur->ns != NULL) && (style->nsDefs != NULL) &&
-                  (xsltCheckExtPrefix(style, cur->ns->prefix))) {
+       }
+       else if ((cur->ns != NULL) && (style->nsDefs != NULL) &&
+           (xsltCheckExtPrefix(style, cur->ns->prefix)))
+       {
            /*
             * okay this is an extension element compile it too
             */
@@ -1862,7 +3935,6 @@ xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
                }
            }
        }
-
        /*
         * Skip to next node
         */
@@ -1930,6 +4002,8 @@ skip_children:
     }
 }
 
+#endif /* else XSLT_REFACTORED */
+
 /**
  * xsltParseStylesheetKey:
  * @style:  the XSLT stylesheet
@@ -1949,7 +4023,7 @@ xsltParseStylesheetKey(xsltStylesheetPtr style, xmlNodePtr key) {
     xmlChar *name = NULL;
     xmlChar *nameURI = NULL;
 
-    if (key == NULL)
+    if ((style == NULL) || (key == NULL))
        return;
 
     /*
@@ -1996,22 +4070,234 @@ xsltParseStylesheetKey(xsltStylesheetPtr style, xmlNodePtr key) {
     }
 
     /*
-     * register the keys
-     */
-    xsltAddKey(style, name, nameURI, match, use, key);
+     * 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;
+   
+
+    /*
+    * Get inherited namespaces.
+    */
+    if (cctxt->inode->inScopeNs != NULL) {
+       int i, j;
+       xmlNsPtr ns;
+       xsltPointerListPtr extElemList = cctxt->inode->extElemNs;
+       xsltPointerListPtr exclResultList = cctxt->inode->exclResultNs;
+       xsltNsListPtr inScopeNs = cctxt->inode->inScopeNs;
+
+       for (i = 0; i < inScopeNs->number; i++) {
+           ns = inScopeNs->list[i];
+           /*
+           * Exclude the XSLT namespace.
+           */
+           if (xmlStrEqual(ns->href, XSLT_NAMESPACE))
+               goto skip_ns;
+           /*
+           * Exclude excluded result namespaces.
+           */
+           if (exclResultList) {
+               for (j = 0; j < exclResultList->number; j++)
+                   if (xmlStrEqual(ns->href,
+                       BAD_CAST exclResultList->items[j]))
+                       goto skip_ns;
+           }
+           /*
+           * Exclude extension-element namespaces.
+           */
+           if (extElemList) {
+               for (j = 0; j < extElemList->number; j++)
+                   if (xmlStrEqual(ns->href, BAD_CAST extElemList->items[j]))
+                       goto skip_ns;
+           }
+           /*
+           * Add the xmlNs item.
+           */
+           if (templ->inheritedNs == NULL) {
+               templ->inheritedNs = (xmlNsPtr *) xmlMalloc(
+                   inScopeNs->number * sizeof(xmlNsPtr));
+               if (templ->inheritedNs == NULL) {
+                   xmlGenericError(xmlGenericErrorContext,
+                       "xsltGetInheritedNsList : out of memory!\n");
+                   cctxt->style->errors++;
+                   goto error;
+               }
+               memset(templ->inheritedNs, 0,
+                   inScopeNs->number * sizeof(xmlNsPtr));
+           }
+           templ->inheritedNs[templ->inheritedNsNr++] = ns;
+skip_ns:
+           {}
+       }       
+#ifdef WITH_XSLT_DEBUG_PARSING
+       if (templ->inheritedNsNr != 0) {
+           xsltGenericDebug(xsltGenericDebugContext,
+               "xsl:template has %d inherited namespaces\n",
+               templ->inheritedNsNr);
+       }
+#endif
+    }
+
+    /*
+    * 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.
+       */
+       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;
+       
+       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);
+    
+    templ->elem = templNode;
+    templ->content = templNode->children;
+    xsltAddTemplate(cctxt->style, templ, templ->mode, templ->modeURI);
 
 error:
-    if (use != NULL)
-       xmlFree(use);
-    if (match != NULL)
-       xmlFree(match);
-    if (name != NULL)
-       xmlFree(name);
-    if (nameURI != NULL)
-       xmlFree(nameURI);
+    xsltCompilerNodePop(cctxt, templNode);
+
+    return;
 }
 
+#else /* XSLT_REFACTORED */
+
 /**
  * xsltParseStylesheetTemplate:
  * @style:  the XSLT stylesheet
@@ -2092,16 +4378,7 @@ xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
     if (prop != NULL) {
         const xmlChar *URI;
        xsltTemplatePtr cur;
-
-       if (ret->name != NULL) {
-           xmlFree(ret->name);
-           ret->name = NULL;
-       }
-       if (ret->nameURI != NULL) {
-           xmlFree(ret->nameURI);
-           ret->nameURI = NULL;
-       }
-
+       
        URI = xsltGetQNameURI(template, &prop);
        if (prop == NULL) {
            if (style != NULL) style->errors++;
@@ -2112,119 +4389,727 @@ xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template) {
                    "xsl:template : error invalid name '%s'\n", prop);
                if (style != NULL) style->errors++;
                goto error;
-           } 
-           ret->name = prop;
+           }
+           ret->name = xmlDictLookup(style->dict, BAD_CAST prop, -1);
+           xmlFree(prop);
+           prop = NULL;
            if (URI != NULL)
-               ret->nameURI = xmlStrdup(URI);
+               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, prop) &&
+               if ((URI != NULL && xmlStrEqual(cur->name, ret->name) &&
                                xmlStrEqual(cur->nameURI, URI) ) ||
                    (URI == NULL && cur->nameURI == NULL &&
-                               xmlStrEqual(cur->name, prop))) {
+                               xmlStrEqual(cur->name, ret->name))) {
                    xsltTransformError(NULL, style, template,
-                       "xsl:template: error duplicate name '%s'\n", prop);
+                       "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);
+}
+
+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);
+}
+
+static int
+xsltParseMetaInfo(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
+{
+#define XSLT_MODULE_SCOPE_GLOBAL 0
+#define XSLT_MODULE_SCOPE_SSLEVEL 1
+    xmlNodePtr cur;
+    xmlChar *value = NULL, *value2 = NULL;
+    int moduleScope;
+
+    if ((cctxt == NULL) || (node == NULL) || (node->children == NULL))
+       return(-1);
+
+    /*
+    * Remove whitespace in case we had a xml:space.
+    */
+    xsltParseRemoveWhitespace(node);
+    
+    cur = node->children;
+    while (cur != NULL) {
+       if (value != NULL) {
+           xmlFree(value);
+           value = NULL;
+       }
+       if (value2 != NULL) {
+           xmlFree(value2);
+           value2 = NULL;
+       }
+       /*
+       * Process the module-registration specific elements.
+       */
+       if ((cur->type == XML_ELEMENT_NODE) &&
+           (cur->ns == NULL))
+       {
+           if (xmlStrEqual(cur->name, "initialize-module")) {
+               /*
+               * TODO: Validation of attributes.
+               */
+               value = xmlGetNsProp(cur, "namespace", NULL);
+               if (value != NULL) {
+                   moduleScope = XSLT_MODULE_SCOPE_GLOBAL;
+                   value2 = xmlGetNsProp(cur, "scope", NULL);
+                   if (value != NULL) {
+                       if (xmlStrEqual(value2, "global"))
+                           moduleScope = XSLT_MODULE_SCOPE_GLOBAL;
+                       else if (xmlStrEqual(value2, "stylesheet-level"))
+                           moduleScope = XSLT_MODULE_SCOPE_SSLEVEL;
+                       else {
+                           xsltTransformError(NULL, cctxt->style, cur,
+                               "Attribute 'scope': Invalid value. "
+                               "Only the values 'global' and "
+                               "'stylesheet-level' are expected.\n");
+                       }
+                   }
+                   /*
+                   * Call the module initialization.
+                   */
+                   if (moduleScope == XSLT_MODULE_SCOPE_GLOBAL) {
+                       /*
+                       * Initialize the modle using global user-data
+                       * storage. This means that this module
+                       * will be initialized only *once* (regardless
+                       * of the number of stylesheet-modules) and the
+                       * user-data will be only stored in the main
+                       * stylesheet.
+                       */
+                       xsltStyleGetExtData(cctxt->style, BAD_CAST value);
+                   } else {
+                       /*
+                       * Initialize the modle using per-stylesheet
+                       * user-data storage. This means that this module
+                       * will be initialized (and user-data is stored)
+                       * in the stylesheet at the current stylesheet-level.
+                       */
+                       xsltStyleStylesheetLevelGetExtData(cctxt->style,
+                           BAD_CAST value);
+                   }
+                   goto next_item;
+               }
+           }
+       }
+       xsltParseContentError(cctxt->style, cur);
+
+next_item:
+       cur = cur->next;         
+    }
+    if (value != NULL) {
+       xmlFree(value);
+       value = NULL;
+    }
+    if (value2 != NULL) {
+       xmlFree(value2);
+       value2 = NULL;
+    }
+
+    return(0);
+}
+
+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_IN_XSLT_NS(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;
+
+    /*
+    * 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, 1) == 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, 1);
+    /*
+    * Attribute "exclude-result-prefixes".
+    */
+    cctxt->inode->exclResultNs =
+       xsltParseExclResultPrefixes(cctxt, node, NULL, 1);
+
+    /*
+    * 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;
+    }
+    /*
+    * REVISIT TODO: Process Libxslt's module handling user-defined
+    *  data element.
+    */        
+    cur = start;
+    while ((cur != NULL) &&
+       xsltParseFindTopLevelElem(cctxt, cur,
+       xsltLibxsltDataElementNameMeta,
+       xsltLibxsltDataElementNamespaceMeta, 0, &cur) == 1)
+    {  
+       if (xsltParseMetaInfo(cctxt, cur) == -1)
+           goto internal_err;
+       cur->psvi = (void *) xsltUserDataElemMarker;
+       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;
+           }
+           if (cur->psvi == xsltUserDataElemMarker) {
+               cur->psvi = NULL;
+               cur = cur->next;
+               continue;
+           }
+           /*
+           * Process all XSLT elements.
+           */
+           if (IS_IN_XSLT_NS(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++;
-                   goto error;
+                   cur = cur->next;
+                   continue;
                }
-               cur = cur->next;
+               /* 
+               * 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")) {
+                   xsltNamespaceAlias(style, cur);
+               } 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,
+                   "xsltParseStylesheetTop : found foreign element %s\n",
+                   cur->name);
+#endif
            }
        }
+       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);
+exit:
+    xsltCompilerNodePop(cctxt, node);
+#ifdef WITH_XSLT_DEBUG_PARSING
+    xsltGenericDebug(xsltGenericDebugContext,
+                   "parsed %d templates\n", templates);
+#endif
+    return(0);
 
-error:
-    return;
+internal_err:
+    xsltCompilerNodePop(cctxt, node);
+    return(-1);
 }
 
-#ifdef XSLT_REFACTORED_PARSING
-/*
-* xsltParseStylesheetTreeNew:
-*
-* Parses and compiles an XSLT stylesheet's XML tree.
-*
-* TODO: Adjust error report text.
-*/
+/**
+ * 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
-xsltParseStylesheetTreeNew(xsltStylesheetPtr sheet, xmlNodePtr cur)
+xsltParseXSLTStylesheetElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
 {
-    xsltCompilerCtxtPtr cctxt;
-    xmlNodePtr top = cur;
-    int depth = 0, simpleSyntax = 0;
+    xmlNodePtr cur;
 
-    if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE) ||
-       (sheet == NULL) || (sheet->compCtxt == NULL))
+    if ((cctxt == NULL) || (node == NULL))
        return(-1);
-    cctxt = (xsltCompilerCtxtPtr) sheet->compCtxt;
-
+    
+    if (node->children == NULL)
+       goto exit;    
     /*
-    * Evalute if we have a simplified syntax.
+    * Process top-level elements:
+    *  xsl:import (must be first)
+    *  xsl:include (this is just a pre-processing)
     */
-    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
-       /*
-       * TODO: Initialize.
-       */
-    } else {
-       simpleSyntax = 1;       
-       /*
-       * TODO: Create the initial template.
-       * TODO: Initialize.
-       */
-    }        
+    cur = node->children;
     /*
-    * Reset the compiler context.
-    */
-    cctxt->depth = 0;
-    cctxt->inode = NULL;
+    * 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;
     /*
-    * Initialize the in-scope namespaces. We need to have
-    * the in-scope ns-decls of the first given node, regardless
-    * if it's a XSLT instruction or a literal result element.
+    * Pre-process all xsl:include elements.
     */
-    xsltCompilerNodePush(cctxt, cur);
-    xsltCompilerGetInScopeNSInfo(cctxt, cur);
-    goto next_sibling;
-
-    while (cur != NULL) {
-       if (cur->type == XML_ELEMENT_NODE) {
-           
-       }
-
-next_sibling:
-       if (cur->type == XML_ELEMENT_NODE) {
-           /*
-           * Leaving an element.
-           */
-           xsltCompilerNodePop(cctxt, cur);
-       }
-       if (cur == top)
-           break;
-       if (cur->next != NULL)
-           cur = cur->next;
-       else {
-           cur = cur->parent;
-           goto next_sibling;
-       }       
+    while ((cur != NULL) &&
+       xsltParseFindTopLevelElem(cctxt, cur,
+           BAD_CAST "include", XSLT_NAMESPACE, 0, &cur) == 1)
+    {
+       xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_INCLUDE);
+       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);
 }
-#endif /* XSLT_REFACTORED_PARSING */
+
+#else /* XSLT_REFACTORED */
 
 /**
  * xsltParseStylesheetTop:
@@ -2289,7 +5174,7 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
        if (cur->type == XML_TEXT_NODE) {
            if (cur->content != NULL) {
                xsltTransformError(NULL, style, cur,
-                   "misplaced text element: '%s'\n", cur->content);
+                   "misplaced text node: '%s'\n", cur->content);
            }
            if (style != NULL) style->errors++;
             cur = cur->next;
@@ -2350,6 +5235,10 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
     } 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,
@@ -2373,16 +5262,176 @@ xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top) {
 #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) == 0) {
+       /*
+       * 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);
+}
+
+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->ns = NULL;
+           ns->origNsName = NULL;          
+       }
+       ns = ns->next;
+    }
+    return(0);
+}
+
 /**
  * xsltParseStylesheetProcess:
- * @ret:  the XSLT stylesheet
+ * @style:  the XSLT stylesheet (the current stylesheet-level)
  * @doc:  and xmlDoc parsed XML
  *
- * parse an XSLT stylesheet adding the associated structures
+ * Parses an XSLT stylesheet, adding the associated structures.
+ * Called by:
+ *  xsltParseStylesheetImportedDoc() (xslt.c)
+ *  xsltParseStylesheetInclude() (imports.c)
  *
- * Returns the value of the 'ret' parameter if everything
+ * 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) {
@@ -2403,7 +5452,8 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
        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")))) {   
@@ -2420,22 +5470,8 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
        ret->literal_result = 1;
     }
     if (!ret->nopreproc) {
-#ifdef XSLT_REFACTORED
-       /*
-       * Reset the compiler context.
-       * TODO: This all looks ugly; but note that this will go
-       *   into an other function; it's just temporarily here.
-       */
-       XSLT_CCTXT(ret)->depth = -1;
-       XSLT_CCTXT(ret)->inode = NULL;
-#endif
        xsltPrecomputeStylesheet(ret, cur);
-#ifdef XSLT_REFACTORED
-       XSLT_CCTXT(ret)->depth = -1;
-       XSLT_CCTXT(ret)->inode = NULL;
-#endif
     }
-
     if (ret->literal_result == 0) {
        xsltParseStylesheetTop(ret, cur);
     } else {
@@ -2483,16 +5519,18 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
        template->elem = (xmlNodePtr) doc;
        template->content = doc->children;
        xsltAddTemplate(ret, template, NULL, NULL);
-       ret->literal_result = 1;
+       ret->literal_result = 1;        
     }
 
     return(ret);
 }
 
+#endif /* else of XSLT_REFACTORED */
+
 /**
  * xsltParseStylesheetImportedDoc:
  * @doc:  an xmlDoc parsed XML
- * @style: pointer to parent stylesheet
+ * @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.
@@ -2501,44 +5539,156 @@ xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc) {
  */
 
 xsltStylesheetPtr
-xsltParseStylesheetImportedDoc(xmlDocPtr doc, xsltStylesheetPtr style) {
-    xsltStylesheetPtr ret;
+xsltParseStylesheetImportedDoc(xmlDocPtr doc,
+                              xsltStylesheetPtr parentStyle) {
+    xsltStylesheetPtr retStyle;
 
     if (doc == NULL)
        return(NULL);
 
-    ret = xsltNewStylesheet();
-    if (ret == 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(ret->dict);
-       ret->dict = doc->dict;
+        xmlDictFree(retStyle->dict);
+       retStyle->dict = doc->dict;
 #ifdef WITH_XSLT_DEBUG
         xsltGenericDebug(xsltGenericDebugContext,
-                         "reusing dictionary from %s for stylesheet\n",
-                        doc->URL);
+           "reusing dictionary from %s for stylesheet\n",
+           doc->URL);
 #endif
-       xmlDictReference(ret->dict);
-    }
+       xmlDictReference(retStyle->dict);
+    }          
     
-    ret->doc = doc;
-    ret->parent = style;       /* needed to prevent loops */
-    xsltGatherNamespaces(ret);
-    if (xsltParseStylesheetProcess(ret, doc) == NULL) {
-       ret->doc = NULL;
-       xsltFreeStylesheet(ret);
-       ret = NULL;
+    /*
+    * 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.
+           */      
+           if (xsltCompilerCreate(retStyle) == NULL) {
+               xsltFreeStylesheet(retStyle);
+               return(NULL);
+           }
+           cctxt = XSLT_CCTXT(retStyle);
+           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) {
+               /*
+               * Restore all changes made to namespace URIs of ns-decls.
+               */
+               if (cctxt->psData->nsMap)               
+                   xsltRestoreDocumentNamespaces(cctxt->psData->nsMap, doc);
+               /*
+               * Detach the doc from the stylesheet; otherwise the doc
+               * will be freed in xsltFreeStylesheet().
+               */
+               retStyle->doc = NULL;
+               /*
+               * Cleanup the doc if its the main doc.
+               */
+               if (parentStyle == NULL)
+                   xsltCleanupStylesheetTree(doc, xmlDocGetRootElement(doc));
+
+               xsltFreeStylesheet(retStyle);
+               retStyle = NULL;
+           }
+       }
     }
-    if (ret != NULL) {
-       if (ret->errors != 0) {
-           ret->doc = NULL;
-           xsltFreeStylesheet(ret);
-           ret = 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;
        }
     }
-    
-    return(ret);
+#endif /* else of XSLT_REFACTORED */
+        
+    return(retStyle);
 }
 
 /**
@@ -2566,6 +5716,8 @@ xsltParseStylesheetDoc(xmlDocPtr doc) {
     *   xsltParseStylesheetImportedDoc().
     */
     if (ret->compCtxt != NULL) {
+       /* TEST TODO: REMOVE test output*/
+       /* printf("MAX NODE INFO: %d\n", XSLT_CCTXT(ret)->maxNodeInfos); */ 
        xsltCompilerCtxtFree(XSLT_CCTXT(ret));
        ret->compCtxt = NULL;
     }
index a79096d..7fb8940 100644 (file)
@@ -26,7 +26,6 @@
 extern "C" {
 #endif
 
-
 /**
  * XSLT_REFACTORED:
  *
@@ -35,6 +34,54 @@ extern "C" {
  */
 /* #define XSLT_REFACTORED */
 
+#ifdef XSLT_REFACTORED
+
+extern const xmlChar *xsltConstNamespaceNameXSLT;
+
+/**
+ * IS_XSLT_ELEM_FAST:
+ *
+ * Checks that the element pertains to XSLT namespace.
+ */
+#define IS_XSLT_ELEM_FAST(e) \
+    (((e) != NULL) && ((e)->type == XML_ELEMENT_NODE) && \
+     ((e)->ns != NULL) && ((e)->ns->href == xsltConstNamespaceNameXSLT))
+
+#define IS_IN_XSLT_NS(e) \
+    (((e)->ns != NULL) && ((e)->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)
+
+/**
+ * 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:
  *
@@ -110,8 +157,8 @@ struct _xsltTemplate {
     struct _xsltStylesheet *style;/* the containing stylesheet */
     xmlChar *match;    /* the matching string */
     float priority;    /* as given from the stylesheet, not computed */
-    xmlChar *name;     /* the local part of the name QName */
-    xmlChar *nameURI;  /* the URI part of the name QName */
+    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 */
@@ -236,7 +283,13 @@ typedef enum {
     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
+#endif
 } xsltStyleType;
 
 /**
@@ -258,7 +311,7 @@ typedef void (*xsltElemPreCompDeallocator) (xsltElemPreCompPtr comp);
 struct _xsltElemPreComp {
     xsltElemPreCompPtr next;           /* next item in the global chained
                                           list hold by xsltStylesheet. */
-    xsltStyleType type;                        /* type of the element */
+    xsltStyleType type;                /* type of the element */
     xsltTransformFunction func;        /* handling function */
     xmlNodePtr inst;                   /* the node in the stylesheet's tree
                                           corresponding to this item */
@@ -270,51 +323,44 @@ struct _xsltElemPreComp {
 /**
  * xsltStylePreComp:
  *
- * The abstract basic structure for items of the
- * AST of the XSLT processor.
- * The AST includes:
+ * 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;
 
-/*************************
- * Refactored structures *
- *************************/
 #ifdef XSLT_REFACTORED
 
-typedef struct _xsltNsList xsltNsList;
+/*
+* 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 _xsltNsList xsltNsList;
 typedef xsltNsList *xsltNsListPtr;
 struct _xsltNsList {
     xmlNsPtr *list;
     int number;
 };
 
-#if 0
-/*
- * TODO: xsltBasicItem is not used yet; maybe never will be used, since
- * xsltElemPreCompPtr is acting as the base type for the compiled
- * items of a stylesheet. It seems not practical to try to change
- * this type to xsltBasicItemPtr, since xsltElemPreCompPtr is
- * used already used too massively (e.g. xsltStylesheet->preComps) and
- * for extension functions.
- */
-/**
- * xsltBasicItem:
- *
- * The basic structure for all items of the AST of the XSLT processor.
- */
-typedef struct _xsltBasicItem xsltBasicItem;
-
-typedef xsltBasicItem *xsltBasicItemPtr;
-struct _xsltBasicItem {
-    xsltBasicASTItemPtr next;
-    xsltStyleType type;
-};
-#endif
-
 /**
  * XSLT_ITEM_COMPATIBILITY_FIELDS:
  * 
@@ -346,7 +392,7 @@ struct _xsltBasicItem {
  *
  * The in-scope namespaces.
  */
-#define XSLT_ITEM_NSINSCOPE_FIELDS xsltNsListPtr inScopeNS;
+#define XSLT_ITEM_NSINSCOPE_FIELDS xsltNsListPtr inScopeNs;
 
 /**
  * XSLT_ITEM_COMMON_FIELDS:
@@ -378,8 +424,8 @@ struct _xsltStylePreComp {
     xsltTransformFunction func; /* handling function */
     xmlNodePtr inst;           /* the node in the stylesheet's tree
                                   corresponding to this item. */
-    /* Currenlty to navigational fields. */
-    xsltNsListPtr inScopeNS;
+    /* Currently no navigational fields. */
+    xsltNsListPtr inScopeNs;
 };
 
 /**
@@ -868,14 +914,72 @@ struct _xsltStyleItemOtherwise {
     XSLT_ITEM_COMMON_FIELDS
 };
 
+typedef struct _xsltStyleItemInclude xsltStyleItemInclude;
+typedef xsltStyleItemInclude *xsltStyleItemIncludePtr;
+
+struct _xsltStyleItemInclude {
+    XSLT_ITEM_COMMON_FIELDS
+    xsltDocumentPtr include;
+};
+
+/************************************************************************
+ *                                                                     *
+ *  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                                             *
+ *                                                                     *
+ ************************************************************************/
+
 /*
  * Literal result elements.
- * TODO: Not used yet.
  */
-typedef struct _xsltStyleItemLRE xsltStyleItemLRE;
-typedef xsltStyleItemLRE *xsltStyleItemLREPtr;
-struct _xsltStyleItemLRE {
+typedef struct _xsltStyleItemLRElement xsltStyleItemLRElement;
+typedef xsltStyleItemLRElement *xsltStyleItemLRElementPtr;
+struct _xsltStyleItemLRElement {
     XSLT_ITEM_COMMON_FIELDS
+    xsltPointerListPtr exclResultNs;
+};
+
+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 */    
 };
 
 /************************************************************************
@@ -884,6 +988,13 @@ struct _xsltStyleItemLRE {
  *                                                                     *
  ************************************************************************/
 
+typedef struct _xsltPrincipalStylesheetData xsltPrincipalStylesheetData;
+typedef xsltPrincipalStylesheetData *xsltPrincipalStylesheetDataPtr;
+
+#define XSLT_ELEMENT_CATEGORY_XSLT 0
+#define XSLT_ELEMENT_CATEGORY_EXTENSION 1
+#define XSLT_ELEMENT_CATEGORY_LR 2
+
 /**
  * xsltCompilerNodeInfo:
  *
@@ -896,29 +1007,68 @@ struct _xsltCompilerNodeInfo {
     xsltCompilerNodeInfoPtr prev;
     xmlNodePtr node;
     int depth;
-    xsltNsListPtr inScopeNS; /* The in-scope namespaces for the current
-                                position in the node-tree */
     xsltTemplatePtr templ;   /* The owning template */
+    int category;           /* XSLT element, LR-element or
+                                extension element */
+    xsltStyleType type;
     xsltElemPreCompPtr item; /* The compiled information */
+    xsltNsListPtr inScopeNs; /* The in-scope namespaces for the current
+                                position in the node-tree */
+    xsltPointerListPtr exclResultNs; /* The current excluded
+                                     result namespaces */
+    xsltPointerListPtr extElemNs;
+    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)
+#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 */
+    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 */
-    xsltStylesheetPtr sheet;
+    xmlDictPtr dict;
+    xsltStylesheetPtr style;
+    int simplified; /* whether this is a simplified stylesheet */
     /* TODO: structured/unstructured error contexts. */
-    int depth; /* TODO: current depth in the stylesheets node-tree */
+    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; /* 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;    
 };   
 
 #else /* XSLT_REFACTORED */
@@ -1002,10 +1152,39 @@ struct _xsltStackElem {
     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.
+    */
+    void *inScopeNamespaces;
+    /*
+    * Global list of information for [xsl:]excluded-result-prefixes.
+    */
+    void *exclResultNamespaces;
+    /*
+    * Global list of information for [xsl:]extension-element-prefixes.
+    */
+    void *extElemNamespaces;
+    /*
+    * Namespace name map to get rid of string comparison of namespace names.
+    */
+    xsltNsMapPtr nsMap;
+};
+
+    
+#endif
 /*
- * TODO: We need a 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.
+ * 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 {
     /*
@@ -1059,13 +1238,22 @@ struct _xsltStylesheet {
     /*
      * Namespaces.
      */
-    xmlHashTablePtr nsHash;     /* the set of namespaces in use */
-    void           *nsDefs;     /* the namespaces defined */
+    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 */
+    void *keys;                        /* key definitions */
 
     /*
      * Output related stuff.
@@ -1112,7 +1300,7 @@ struct _xsltStylesheet {
     xsltDocumentPtr includes;  /* points to last nested include */
 
     /*
-     * dictionnary: shared between stylesheet, context and documents.
+     * dictionary: shared between stylesheet, context and documents.
      */
     xmlDictPtr dict;
     /*
@@ -1135,16 +1323,18 @@ struct _xsltStylesheet {
      * Literal Result Element as Stylesheet c.f. section 2.3
      */
     int literal_result;
-#ifdef XSLT_REFACTORED
     /*
-    * Compilation context used during compile-time.
+    * The principal stylesheet
     */
-    void * compCtxt;
+    xsltStylesheetPtr principal;
+#ifdef XSLT_REFACTORED
     /*
-    * Namespace lists.
+    * Compilation context used during compile-time.
     */
-    void *inScopeNamespaces;    
-#endif    
+    xsltCompilerCtxtPtr compCtxt; /* TODO: Change this to (void *). */
+
+    xsltPrincipalStylesheetDataPtr principalData;    
+#endif
 };
 
 /*
@@ -1323,13 +1513,13 @@ XSLTPUBFUN xsltStylesheetPtr XSLTCALL
 XSLTPUBFUN xsltStylesheetPtr XSLTCALL  
                        xsltParseStylesheetFile (const xmlChar* filename);
 XSLTPUBFUN void XSLTCALL                       
-                       xsltFreeStylesheet      (xsltStylesheetPtr sheet);
+                       xsltFreeStylesheet      (xsltStylesheetPtr style);
 XSLTPUBFUN int XSLTCALL                        
                        xsltIsBlank             (xmlChar *str);
 XSLTPUBFUN void XSLTCALL                       
                        xsltFreeStackElemList   (xsltStackElemPtr elem);
 XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL       
-                       xsltDecimalFormatGetByName(xsltStylesheetPtr sheet,
+                       xsltDecimalFormatGetByName(xsltStylesheetPtr style,
                                                 xmlChar *name);
 
 XSLTPUBFUN xsltStylesheetPtr XSLTCALL  
@@ -1389,23 +1579,32 @@ XSLTPUBFUN xmlChar * XSLTCALL
 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 xsltNsListPtr XSLTCALL
-                       xsltCompilerGetInScopeNSInfo(xsltCompilerCtxtPtr cctxt,
-                                                    xmlNodePtr node);
-#endif /* XSLT_REFACTORED */
-/*
- * Extra function for successful xsltCleanupGlobals / xsltInit sequence.
- */
-
+#ifdef XSLT_REFACTORED  
 XSLTPUBFUN void XSLTCALL
-                       xsltUninit              (void);
+                       xsltParseSequenceConstructor(
+                                                xsltCompilerCtxtPtr cctxt,
+                                                xmlNodePtr start);
+XSLTPUBFUN int XSLTCALL
+                       xsltParseAnyXSLTElem    (xsltCompilerCtxtPtr cctxt,
+                                                xmlNodePtr elem);
+XSLTPUBFUN int XSLTCALL
+                       xsltRestoreDocumentNamespaces(
+                                                xsltNsMapPtr ns,
+                                                xmlDocPtr doc);
+#endif /* XSLT_REFACTORED */
 
 #ifdef __cplusplus
 }
index f7ee731..723962f 100644 (file)
@@ -303,6 +303,49 @@ error:
 #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.
@@ -310,7 +353,7 @@ error:
  * Returns a xsltPointerList structure or NULL in case of an error.
  */
 xsltPointerListPtr
-xsltPointerListCreate(void)
+xsltPointerListCreate(int initialSize)
 {
     xsltPointerListPtr ret;
 
@@ -321,6 +364,10 @@ xsltPointerListCreate(void)
        return (NULL);
     }
     memset(ret, 0, sizeof(xsltPointerList));
+    if (initialSize > 0) {
+       xsltPointerListAddSize(ret, NULL, initialSize);
+       ret->number = 0;
+    }
     return (ret);
 }
 
@@ -357,76 +404,6 @@ xsltPointerListClear(xsltPointerListPtr list)
     list->size = 0;
 }
 
-/**
- * xsltPointerListAdd:
- *
- * Adds an item to the list.
- *
- * Returns the position of the added item in the list or
- *         -1 in case of an error.
- */
-int
-xsltPointerListAdd(xsltPointerListPtr list, void *item)
-{
-    if (list->items == NULL) {
-       list->items = (void **) xmlMalloc(
-           20 * sizeof(void *));
-       if (list->items == NULL) {
-           xsltGenericError(xsltGenericErrorContext,
-            "xsltPointerListAdd: memory allocation failure.\n");
-           return(-1);
-       }
-       list->number = 0;
-       list->size = 20;
-    } 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,
-            "xsltPointerListAdd: memory re-allocation failure.\n");
-           list->size = 0;
-           return(-1);
-       }
-    }
-    list->items[list->number++] = item;
-    return(0);
-}
-
-#if 0 /* TODO: Not used yet. Enable if ever needed. */
-static int
-xsltPointerListAddSize(xsltPointerListPtr list,
-                      int initialSize,
-                      void *item)
-{
-    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);
-}
-#endif
-
 #endif /* XSLT_REFACTORED */
 
 /************************************************************************
@@ -650,8 +627,16 @@ xsltPrintErrorContext(xsltTransformContextPtr ctxt,
     
     if (ctxt != NULL)
        type = "runtime error";
-    else if (style != NULL)
+    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",
@@ -1008,9 +993,9 @@ xsltComputeSortResult(xsltTransformContextPtr ctxt, xmlNodePtr sort) {
        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->number;
+       if (comp->inScopeNs != NULL) {
+           ctxt->xpathCtxt->namespaces = comp->inScopeNs->list;
+           ctxt->xpathCtxt->nsNr = comp->inScopeNs->number;
        } else {
            ctxt->xpathCtxt->namespaces = NULL;
            ctxt->xpathCtxt->nsNr = 0;
index c4e3ae9..058d143 100644 (file)
@@ -298,31 +298,6 @@ XSLTPUBFUN int XSLTCALL
 XSLTPUBFUN void XSLTCALL               
                xslDropCall                     (void);
 
-#ifdef XSLT_REFACTORED
-/**
- * xsltPointerList:
- *
- * Pointer-list for various purposes.
- */
-typedef struct _xsltPointerList xsltPointerList;
-typedef xsltPointerList *xsltPointerListPtr;
-struct _xsltPointerList {
-    void **items;
-    int number;
-    int size;
-};
-
-XSLTPUBFUN xsltPointerListPtr XSLTCALL
-               xsltPointerListCreate           (void);
-XSLTPUBFUN void XSLTCALL
-               xsltPointerListFree             (xsltPointerListPtr list);
-XSLTPUBFUN void XSLTCALL
-               xsltPointerListClear            (xsltPointerListPtr list);
-XSLTPUBFUN int XSLTCALL
-               xsltPointerListAdd              (xsltPointerListPtr list,
-                                                void *item);
-#endif /* XSLT_REFACTOR */
-
 #ifdef __cplusplus
 }
 #endif