Next step of refactoring. For more details see bug #341588. I applied the
authorKasimier T. Buchcik <kbuchcik@src.gnome.org>
Fri, 12 May 2006 21:31:53 +0000 (21:31 +0000)
committerKasimier T. Buchcik <kbuchcik@src.gnome.org>
Fri, 12 May 2006 21:31:53 +0000 (21:31 +0000)
* libxslt/documents.c libxslt/namespaces.c
  libxslt/preproc.c libxslt/transform.c
  libxslt/xslt.c libxslt/xsltInternals.h libxslt/xsltutils.c:
  Next step of refactoring. For more details see bug #341588.
  I applied the suggestion of Jerome Pesenti to the refactored
  (still IDFEDed out with XSLT_REFACTORED) code: The XPath
  compilation context (accessible via the compilation context)
  is now reused for compilation of expressions at
  compilation-time; this should reduce compilation time to 50%
  for avarage stylesheets.

ChangeLog
libxslt/documents.c
libxslt/namespaces.c
libxslt/preproc.c
libxslt/transform.c
libxslt/xslt.c
libxslt/xsltInternals.h
libxslt/xsltutils.c

index fb74489..ea37ba9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Fri May 12 23:23:06 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
+
+       * libxslt/documents.c libxslt/namespaces.c
+         libxslt/preproc.c libxslt/transform.c
+         libxslt/xslt.c libxslt/xsltInternals.h libxslt/xsltutils.c:
+         Next step of refactoring. For more details see bug #341588.
+         I applied the suggestion of Jerome Pesenti to the refactored
+         (still IDFEDed out with XSLT_REFACTORED) code: The XPath
+         compilation context (accessible via the compilation context)
+         is now reused for compilation of expressions at
+         compilation-time; this should reduce compilation time to 50%
+         for avarage stylesheets.
+
 Thu May 11 22:12:22 CEST 2006 Kasimier Buchcik <libxml2-cvs@cazic.net>
 
        * libxslt/extensions.c: Changed a comment to indicate that a
index 0963e1c..f762185 100644 (file)
@@ -201,33 +201,31 @@ xsltNewStyleDocument(xsltStylesheetPtr style, xmlDocPtr doc) {
 void   
 xsltFreeStyleDocuments(xsltStylesheetPtr style) {
     xsltDocumentPtr doc, cur;
-#ifdef XSLT_REFACTORED
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
     xsltNsMapPtr nsMap;
 #endif
     
     if (style == NULL)
        return;
 
-#ifdef XSLT_REFACTORED
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
     if (XSLT_HAS_INTERNAL_NSMAP(style))
        nsMap = XSLT_GET_INTERNAL_NSMAP(style);
     else
        nsMap = NULL;    
-#endif
+#endif   
 
     cur = style->docList;
     while (cur != NULL) {
        doc = cur;
        cur = cur->next;
-
-#ifdef XSLT_REFACTORED
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
        /*
        * Restore all changed namespace URIs of ns-decls.
        */
        if (nsMap)
            xsltRestoreDocumentNamespaces(nsMap, doc->doc);
 #endif
-
        xsltFreeDocumentKeys(doc);
        if (!doc->main)
            xmlFreeDoc(doc->doc);
index 063741b..b9bedc2 100644 (file)
  *                                                                     *
  ************************************************************************/
 
+#ifdef XSLT_REFACTORED  
+static xsltNsAliasPtr
+xsltNewNsAlias(xsltCompilerCtxtPtr cctxt)
+{
+    xsltNsAliasPtr ret;
+
+    if (cctxt == NULL)
+       return(NULL);
+
+    ret = (xsltNsAliasPtr) xmlMalloc(sizeof(xsltNsAlias));
+    if (ret == NULL) {
+       xsltTransformError(NULL, cctxt->style, NULL,
+           "Internal error in xsltNewNsAlias(): Memory allocation failed.\n");
+       cctxt->style->errors++;
+       return(NULL);
+    }
+    memset(ret, 0, sizeof(xsltNsAlias));    
+    /*
+    * TODO: Store the item at current stylesheet-level.
+    */
+    ret->next = cctxt->nsAliases;
+    cctxt->nsAliases = ret;       
+
+    return(ret);
+}
+#endif /* XSLT_REFACTORED */
 /**
  * xsltNamespaceAlias:
  * @style:  the XSLT stylesheet
  * them as well as the corresponding namespace.
  */
 void
-xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node) {
-    xmlChar *sprefix;
-    xmlNsPtr sNs;
-    const xmlChar *shref;
-    xmlChar *rprefix;
-    xmlNsPtr rNs;
-    const xmlChar *rhref;
-
-    sprefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL);
-    if (sprefix == NULL) {
+xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node)
+{
+    xmlChar *resultPrefix = NULL;
+    xmlChar *stylePrefix = NULL;
+    xmlNsPtr literalNs = NULL;
+    xmlNsPtr targetNs = NULL;
+#ifdef XSLT_REFACTORED 
+    xsltNsAliasPtr alias;
+
+    if ((style == NULL) || (node == NULL))
+       return;
+
+    /*
+    * SPEC XSLT 1.0:
+    *  "If a namespace URI is declared to be an alias for multiple
+    *  different namespace URIs, then the declaration with the highest
+    *  import precedence is used. It is an error if there is more than
+    *  one such declaration. An XSLT processor may signal the error;
+    *  if it does not signal the error, it must recover by choosing,
+    *  from amongst the declarations with the highest import precedence,
+    *  the one that occurs last in the stylesheet."
+    *
+    * SPEC TODO: Check for the errors mentioned above.
+    */
+    /*
+    * NOTE that the XSLT 2.0 also *does* use the NULL namespace if
+    *  "#default" is used and there's no default namespace is scope.
+    *  I.e., this is *not* an error. 
+    *  Most XSLT 1.0 implementations work this way.
+    *  The XSLT 1.0 spec has nothing to say on the subject. 
+    */
+    /*
+    * Attribute "stylesheet-prefix".
+    */
+    stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL);
+    if (stylePrefix == NULL) {
+       xsltTransformError(NULL, style, node,
+           "The attribute 'stylesheet-prefix' is missing.\n");
+       return;
+    }
+    if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default"))
+       literalNs = xmlSearchNs(node->doc, node, NULL); 
+    else {
+       literalNs = xmlSearchNs(node->doc, node, stylePrefix);
+       if (literalNs == NULL) {
+           xsltTransformError(NULL, style, node,
+               "Attribute 'stylesheet-prefix': There's no namespace "
+               "declaration in scope for the prefix '%s'.\n",
+                   stylePrefix);
+           goto error;
+       }
+    }
+    /*
+    * Attribute "result-prefix".
+    */
+    resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL);
+    if (resultPrefix == NULL) {
+       xsltTransformError(NULL, style, node,
+           "The attribute 'result-prefix' is missing.\n");
+       goto error;
+    }        
+    if (xmlStrEqual(resultPrefix, (const xmlChar *)"#default"))
+       targetNs = xmlSearchNs(node->doc, node, NULL);
+    else {
+       targetNs = xmlSearchNs(node->doc, node, resultPrefix);
+
+        if (targetNs == NULL) {
+          xsltTransformError(NULL, style, node,
+               "Attribute 'result-prefix': There's no namespace "
+               "declaration in scope for the prefix '%s'.\n",
+                   stylePrefix);
+           goto error;
+       }
+    }
+    /*
+     *
+     * Same alias for multiple different target namespace URIs:
+     *  TODO: The one with the highest import precedence is used.
+     *  Example:
+     *  <xsl:namespace-alias stylesheet-prefix="foo"
+     *                       result-prefix="bar"/>
+     *
+     *  <xsl:namespace-alias stylesheet-prefix="foo"
+     *                       result-prefix="zar"/>
+     *
+     * Same target namespace URI for multiple different aliases:
+     *  All alias-definitions will be used.
+     *  Example:
+     *  <xsl:namespace-alias stylesheet-prefix="bar"
+     *                       result-prefix="foo"/>
+     *
+     *  <xsl:namespace-alias stylesheet-prefix="zar"
+     *                       result-prefix="foo"/>
+     * Cases using #default:
+     *  <xsl:namespace-alias stylesheet-prefix="#default"
+     *                       result-prefix="#default"/>
+     *  TODO: Has this an effect at all?
+     *
+     *  <xsl:namespace-alias stylesheet-prefix="foo"
+     *                       result-prefix="#default"/>
+     *  From namespace to no namespace.
+     *
+     *  <xsl:namespace-alias stylesheet-prefix="#default"
+     *                       result-prefix="foo"/>
+     *  From no namespace to namespace.
+     */
+    
+       
+       /*
+       * Store the ns-node in the alias-object.
+       */
+       alias = xsltNewNsAlias(XSLT_CCTXT(style));
+       if (alias == NULL)
+           return;
+       alias->literalNs = literalNs;
+       alias->targetNs = targetNs;
+       XSLT_CCTXT(style)->hasNsAliases = 1;
+
+
+#else /* XSLT_REFACTORED */
+    const xmlChar *literalNsName;
+    const xmlChar *targetNsName;
+    
+
+    if ((style == NULL) || (node == NULL))
+       return;
+
+    stylePrefix = xmlGetNsProp(node, (const xmlChar *)"stylesheet-prefix", NULL);
+    if (stylePrefix == NULL) {
        xsltTransformError(NULL, style, node,
            "namespace-alias: stylesheet-prefix attribute missing\n");
        return;
     }
-    rprefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL);
-    if (rprefix == NULL) {
+    resultPrefix = xmlGetNsProp(node, (const xmlChar *)"result-prefix", NULL);
+    if (resultPrefix == NULL) {
        xsltTransformError(NULL, style, node,
            "namespace-alias: result-prefix attribute missing\n");
        goto error;
     }
     
-    if (xmlStrEqual(sprefix, (const xmlChar *)"#default")) {
-        /*
-        * Do we have a default namespace previously declared?
-        */
-       sNs = xmlSearchNs(node->doc, node, NULL);
-       if (sNs == NULL)
-           shref = NULL;       /* No - set NULL */
-       else
-           shref = sNs->href;  /* Yes - set for nsAlias table */
+    if (xmlStrEqual(stylePrefix, (const xmlChar *)"#default")) {
+       literalNs = xmlSearchNs(node->doc, node, NULL);
+       if (literalNs == NULL) {
+           literalNsName = NULL;
+       } else
+           literalNsName = literalNs->href; /* Yes - set for nsAlias table */
     } else {
-       sNs = xmlSearchNs(node->doc, node, sprefix);
+       literalNs = xmlSearchNs(node->doc, node, stylePrefix);
  
-       if ((sNs == NULL) || (sNs->href == NULL)) {
+       if ((literalNs == NULL) || (literalNs->href == NULL)) {
            xsltTransformError(NULL, style, node,
                "namespace-alias: prefix %s not bound to any namespace\n",
-                                       sprefix);
+                                       stylePrefix);
            goto error;
        } else
-           shref = sNs->href;
+           literalNsName = literalNs->href;
     }
 
     /*
@@ -108,30 +251,43 @@ xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node) {
      * been explicitly declared the special value UNDEFINED_DEFAULT_NS is
      * put into the nsAliases table
      */
-    if (xmlStrEqual(rprefix, (const xmlChar *)"#default")) {
-       rNs = xmlSearchNs(node->doc, node, NULL);
-       if (rNs == NULL)
-           rhref = UNDEFINED_DEFAULT_NS;
-       else
-           rhref = rNs->href;
+    if (xmlStrEqual(resultPrefix, (const xmlChar *)"#default")) {
+       targetNs = xmlSearchNs(node->doc, node, NULL);
+       if (targetNs == NULL) {
+           targetNsName = UNDEFINED_DEFAULT_NS;
+       else
+           targetNsName = targetNs->href;
     } else {
-       rNs = xmlSearchNs(node->doc, node, rprefix);
+       targetNs = xmlSearchNs(node->doc, node, resultPrefix);
 
-        if ((rNs == NULL) || (rNs->href == NULL)) {
+        if ((targetNs == NULL) || (targetNs->href == NULL)) {
            xsltTransformError(NULL, style, node,
                "namespace-alias: prefix %s not bound to any namespace\n",
-                                       rprefix);
+                                       resultPrefix);
            goto error;
        } else
-           rhref = rNs->href;
+           targetNsName = targetNs->href;
     }
     /*
-     * Special case if #default is used for stylesheet and no default has
-     * been explicitly declared.  We use style->defaultAlias for this
-     */
-    if (shref == NULL) {
-        if (rNs != NULL)
-            style->defaultAlias = rNs->href;
+     * Special case: if #default is used for
+     *  the stylesheet-prefix (literal namespace) and there's no default
+     *  namespace in scope, we'll use style->defaultAlias for this.
+     */   
+    if (literalNsName == NULL) {
+        if (targetNs != NULL) {
+           /*
+           * BUG TODO: Is it not sufficient to have only 1 field for
+           *  this, since subsequently alias declarations will
+           *  overwrite this.      
+           *  Example:
+           *   <xsl:namespace-alias result-prefix="foo"
+           *                        stylesheet-prefix="#default"/>
+           *   <xsl:namespace-alias result-prefix="bar"
+           *                        stylesheet-prefix="#default"/>
+           *  The mapping for "foo" won't be visible anymore.
+           */
+            style->defaultAlias = targetNs->href;
+       }
     } else {
         if (style->nsAliases == NULL)
            style->nsAliases = xmlHashCreate(10);
@@ -140,15 +296,16 @@ xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node) {
                "namespace-alias: cannot create hash table\n");
            goto error;
         }
-        xmlHashAddEntry((xmlHashTablePtr) style->nsAliases,
-                   shref, (void *) rhref);
+       xmlHashAddEntry((xmlHashTablePtr) style->nsAliases,
+           literalNsName, (void *) targetNsName);
     }
+#endif /* else of XSLT_REFACTORED */
 
 error:
-    if (sprefix != NULL)
-       xmlFree(sprefix);
-    if (rprefix != NULL)
-       xmlFree(rprefix);
+    if (stylePrefix != NULL)
+       xmlFree(stylePrefix);
+    if (resultPrefix != NULL)
+       xmlFree(resultPrefix);
 }
 
 /**
@@ -255,27 +412,39 @@ xsltSearchPlainNsByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href)
  * and add a new namespace decalaration on the node
  * Handle namespace aliases and make sure the prefix is not NULL, this
  * is needed for attributes.
+ * Called from:
+ *   xsltAttrTemplateProcess() (templates.c)
+ *   xsltCopyProp() (transform.c)
  *
  * Returns the namespace node to use or NULL
  */
 xmlNsPtr
 xsltGetPlainNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur,
-                      xmlNsPtr ns, xmlNodePtr out) {
-    xsltStylesheetPtr style;
+                      xmlNsPtr ns, xmlNodePtr out) {    
     xmlNsPtr ret;
     const xmlChar *URI = NULL; /* the replacement URI */
 
     if ((ctxt == NULL) || (cur == NULL) || (out == NULL) || (ns == NULL))
        return(NULL);
 
-    style = ctxt->style;
-    while (style != NULL) {
-       if (style->nsAliases != NULL)
-           URI = (const xmlChar *) xmlHashLookup(style->nsAliases, ns->href);
-       if (URI != NULL)
-           break;
-
-       style = xsltNextImport(style);
+#ifdef XSLT_REFACTORED
+    /*
+    * Namespace exclusion and ns-aliasing is performed at
+    * compilation-time in the refactored code.
+    */
+    URI = ns->href;
+#else
+    {
+       xsltStylesheetPtr style;
+       style = ctxt->style;
+       while (style != NULL) {
+           if (style->nsAliases != NULL)
+               URI = (const xmlChar *) xmlHashLookup(style->nsAliases, ns->href);
+           if (URI != NULL)
+               break;
+           
+           style = xsltNextImport(style);
+       }
     }
 
     if (URI == UNDEFINED_DEFAULT_NS) {
@@ -289,6 +458,7 @@ xsltGetPlainNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur,
 
     if (URI == NULL)
        URI = ns->href;
+#endif
 
     if ((out->parent != NULL) &&
        (out->parent->type == XML_ELEMENT_NODE) &&
@@ -351,8 +521,9 @@ xsltGetSpecialNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur,
        (out->parent->type == XML_ELEMENT_NODE) &&
        (out->parent->ns != NULL) &&
        (xmlStrEqual(out->parent->ns->href, URI)))
+    {
        ret = out->parent->ns;
-    else 
+    else 
        ret = xmlSearchNsByHref(out->doc, out, URI);
 
     if ((ret == NULL) || (ret->prefix == NULL)) {
@@ -381,6 +552,9 @@ xsltGetSpecialNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur,
  * @ns:  the namespace
  * @out:  the output node (or its parent)
  *
+ * REFACTORED NOTE: Won't be used anymore in the refactored code
+ *  for literal result elements/attributes.
+ *
  * Find the right namespace value for this prefix, if needed create
  * and add a new namespace decalaration on the node
  * Handle namespace aliases
@@ -389,27 +563,38 @@ xsltGetSpecialNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur,
  */
 xmlNsPtr
 xsltGetNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns,
-                xmlNodePtr out) {
-    xsltStylesheetPtr style;
+                xmlNodePtr out) {    
     xmlNsPtr ret;
     const xmlChar *URI = NULL; /* the replacement URI */
 
     if ((ctxt == NULL) || (cur == NULL) || (out == NULL) || (ns == NULL))
        return(NULL);
-
-    style = ctxt->style;
-    while (style != NULL) {
-       if (style->nsAliases != NULL)
-           URI = (const xmlChar *) 
+    
+#ifdef XSLT_REFACTORED
+    /*
+    * Namespace exclusion and ns-aliasing is performed at
+    * compilation-time in the refactored code.    
+    */
+    URI = ns->href;
+#else
+    {
+       xsltStylesheetPtr style;
+       style = ctxt->style;
+       while (style != NULL) {
+           if (style->nsAliases != NULL)
+               URI = (const xmlChar *) 
                xmlHashLookup(style->nsAliases, ns->href);
-       if (URI != NULL)
-           break;
-
-       style = xsltNextImport(style);
+           if (URI != NULL)
+               break;
+           
+           style = xsltNextImport(style);
+       }
     }
 
     if (URI == UNDEFINED_DEFAULT_NS) {
         xmlNsPtr dflt;
+       /*
+       */
        dflt = xmlSearchNs(cur->doc, cur, NULL);
        if (dflt != NULL)
            URI = dflt->href;
@@ -417,7 +602,7 @@ xsltGetNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns,
            return NULL;
     } else if (URI == NULL)
        URI = ns->href;
-
+#endif
     /*
      * If the parent is an XML_ELEMENT_NODE, and has the "equivalent"
      * namespace as ns (either both default, or both with a prefix
@@ -468,7 +653,14 @@ xsltGetNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns,
  *
  * Do a copy of an namespace list. If @node is non-NULL the
  * new namespaces are added automatically. This handles namespaces
- * aliases
+ * aliases.
+ * This function is intended only for *internal* use at
+ * transformation-time. Use it *only* for copying ns-decls of
+ * literal result elements.
+ * 
+ * Called by:
+ *   xsltCopyTree() (transform.c)
+ *   xsltCopyNode() (transform.c)
  *
  * Returns: a new xmlNsPtr, or NULL in case of error.
  */
@@ -476,8 +668,7 @@ xmlNsPtr
 xsltCopyNamespaceList(xsltTransformContextPtr ctxt, xmlNodePtr node,
                      xmlNsPtr cur) {
     xmlNsPtr ret = NULL, tmp;
-    xmlNsPtr p = NULL,q;
-    const xmlChar *URI;
+    xmlNsPtr p = NULL,q;    
 
     if (cur == NULL)
        return(NULL);
@@ -495,12 +686,13 @@ xsltCopyNamespaceList(xsltTransformContextPtr ctxt, xmlNodePtr node,
            break;
 
        /*
-        * Avoid duplicating namespace declrations on the tree
+        * Avoid duplicating namespace declarations in the tree if
+        * a matching declaration is in scope.
         */
        if (node != NULL) {
            if ((node->ns != NULL) &&
-               (xmlStrEqual(node->ns->href, cur->href)) &&
-               (xmlStrEqual(node->ns->prefix, cur->prefix))) {
+               (xmlStrEqual(node->ns->prefix, cur->prefix)) &&
+               (xmlStrEqual(node->ns->href, cur->href))) {
                cur = cur->next;
                continue;
            }
@@ -510,8 +702,21 @@ xsltCopyNamespaceList(xsltTransformContextPtr ctxt, xmlNodePtr node,
                continue;
            }
        }
-       
+#ifdef XSLT_REFACTORED
+       /*
+       * Namespace exclusion and ns-aliasing is performed at
+       * compilation-time in the refactored code.
+       */
+       q = xmlNewNs(node, cur->href, cur->prefix);
+       if (p == NULL) {
+           ret = p = q;
+       } else {
+           p->next = q;
+           p = q;
+       }
+#else
        if (!xmlStrEqual(cur->href, XSLT_NAMESPACE)) {
+           const xmlChar *URI;
            /* TODO apply cascading */
            URI = (const xmlChar *) xmlHashLookup(ctxt->style->nsAliases,
                                                  cur->href);
@@ -529,6 +734,7 @@ xsltCopyNamespaceList(xsltTransformContextPtr ctxt, xmlNodePtr node,
                p = q;
            }
        }
+#endif
        cur = cur->next;
     }
     return(ret);
@@ -550,8 +756,7 @@ xmlNsPtr
 xsltCopyNamespace(xsltTransformContextPtr ctxt, xmlNodePtr node,
                  xmlNsPtr cur) {
     xmlNsPtr ret = NULL;
-    const xmlChar *URI;
-
+    
     if (cur == NULL)
        return(NULL);
     if (cur->type != XML_NAMESPACE_DECL)
@@ -563,7 +768,16 @@ xsltCopyNamespace(xsltTransformContextPtr ctxt, xmlNodePtr node,
     if ((node != NULL) && (node->type != XML_ELEMENT_NODE))
        node = NULL;
 
+#ifdef XSLT_REFACTORED
+    /*
+    * Namespace exclusion and ns-aliasing is performed at
+    * compilation-time in the refactored code.
+    */
+    ret = xmlNewNs(node, cur->href, cur->prefix);      
+#else
     if (!xmlStrEqual(cur->href, XSLT_NAMESPACE)) {
+       const xmlChar *URI;
+
        URI = (const xmlChar *) xmlHashLookup(ctxt->style->nsAliases,
                                              cur->href);
        if (URI == UNDEFINED_DEFAULT_NS)
@@ -574,6 +788,7 @@ xsltCopyNamespace(xsltTransformContextPtr ctxt, xmlNodePtr node,
            ret = xmlNewNs(node, cur->href, cur->prefix);
        }
     }
+#endif
     return(ret);
 }
 
index 3e2d70c..6e8bf03 100644 (file)
@@ -370,6 +370,20 @@ xsltNewStylePreComp(xsltStylesheetPtr style, xsltStyleType type) {
     return(cur);
 }
 
+#ifdef XSLT_REFACTORED
+static void
+xsltLREEffectiveNsNodesFree(xsltEffectiveNsPtr first)
+{
+    xsltEffectiveNsPtr tmp;
+
+    while (first != NULL) {
+       tmp = first;
+       first = first->next;
+       xmlFree(tmp);
+    }
+}
+#endif
+
 /**
  * xsltFreeStylePreComp:
  * @comp:  an XSLT Style precomputed block
@@ -385,6 +399,13 @@ xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
     * URGENT TODO: Implement destructors.
     */
     switch (comp->type) {
+       case XSLT_FUNC_LITERAL_RESULT_ELEMENT: {
+               xsltStyleItemLRElementInfoPtr item =
+                   (xsltStyleItemLRElementInfoPtr) comp;
+               if (item->effectiveNs)
+                   xsltLREEffectiveNsNodesFree(item->effectiveNs);
+           }
+           break;
        case XSLT_FUNC_COPY:
             break;
         case XSLT_FUNC_SORT: {
@@ -473,7 +494,12 @@ xsltFreeStylePreComp(xsltStylePreCompPtr comp) {
                    xmlXPathFreeCompExpr(item->comp);
            }
            break;
-       case XSLT_FUNC_OTHERWISE:
+       case XSLT_FUNC_OTHERWISE:           
+       case XSLT_FUNC_FALLBACK:
+       case XSLT_FUNC_MESSAGE:
+       case XSLT_FUNC_INCLUDE:
+       case XSLT_FUNC_ATTRSET:
+       
            break;
        default:
            /* TODO: Raise error. */
index ae66aa0..0c94128 100644 (file)
@@ -851,6 +851,11 @@ xsltCopyPropList(xsltTransformContextPtr ctxt, xmlNodePtr target,
  *
  * Make a copy of the element node @node
  * and insert it as last child of @insert
+ * Intended *only* for copying literal result elements and
+ * text-nodes.
+ * Called from:
+ *   xsltApplyOneTemplateInt()
+ *   xsltCopy()
  *
  * Returns a pointer to the new node, or NULL in case of error
  */
@@ -933,6 +938,11 @@ xsltCopyTreeList(xsltTransformContextPtr ctxt, xmlNodePtr list,
  *
  * Do a copy of a namespace list. If @node is non-NULL the
  * new namespaces are added automatically.
+ * Called by:
+ *   xsltCopyTree()
+ *
+ * TODO: What is the exact difference between this function
+ *  and xsltCopyNamespaceList() in "namespaces.c"?
  *
  * Returns: a new xmlNsPtr, or NULL in case of error.
  */
@@ -1064,6 +1074,12 @@ xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr node,
            xmlNsPtr *nsList, *cur, ns;
            /*
             * must add in any new namespaces in scope for the node
+            * REVISIT:
+            *   Question: Do we really have to add every namespace in scope?
+            *   Answer: I think yes, since if we are only adding the
+            *     ns-decls which are declared on this element and actually
+            *     referenced by this element/attribute, then we would miss
+            *     ns-decls for QName in element/attribute content.
             */
            nsList = xmlGetNsList(node->doc, node);
            if (nsList != NULL) {
@@ -1127,8 +1143,9 @@ xsltApplyFallbacks(xsltTransformContextPtr ctxt, xmlNodePtr node,
     xmlNodePtr child;
     int ret = 0;
     
-    if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
-       return(ret);
+    if ((ctxt == NULL) || (node == NULL) || (inst == NULL) ||
+       (inst->children == NULL))
+       return(0);
 
     child = inst->children;
     while (child != NULL) {
@@ -1465,6 +1482,186 @@ xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node,
     }
 }
 
+/**
+* xsltTransLREAcquireInScopeNs:
+* @ctxt:  the transformation context
+* @cur:  the literal result element
+* @ns:  the namespace
+* @out:  the output node (or its parent)
+*
+*
+* Find a matching (prefix and ns-name) ns-declaration
+*  for the given @ns in the result tree.
+* If none is found then a new ns-declaration will be
+*  added to @out. If, in this case, the given prefix is already
+*  in use, then a ns-declaration with a modified ns-prefix
+*  be we created.
+*
+* Returns the acquired ns-declaration
+*         or NULL in case of an API or internal error.
+*/
+xmlNsPtr
+xsltTransLREAcquireInScopeNs(xsltTransformContextPtr ctxt,                          
+                            xmlNodePtr cur, xmlNsPtr literalNs,
+                            xmlNodePtr resultElem)
+{    
+    xmlNsPtr ns;
+    int prefixOccupied = 0;
+
+    if ((ctxt == NULL) || (cur == NULL) ||
+       (resultElem == NULL) || (literalNs == NULL))
+       return(NULL);
+    
+    /*
+    * OPTIMIZE TODO: This all could be optimized by keeping track of
+    *  the ns-decls currently in-scope via a specialized context.
+    */
+    /*
+    * NOTE: Namespace exclusion and ns-aliasing is performed at
+    * compilation-time in the refactored code; so this need not be done
+    * here.
+    */
+    /*
+    * First: search on the result element itself.
+    */
+    if (resultElem->nsDef != NULL) {
+       ns = resultElem->nsDef;
+       do {
+           if ((ns->prefix == NULL) == (literalNs->prefix == NULL)) {
+               if (literalNs->prefix == NULL) {
+                   if (xmlStrEqual(ns->href, literalNs->href))
+                       return(ns);
+                   prefixOccupied = 1;
+                   break;
+               } else if ((ns->prefix[0] == literalNs->prefix[0]) &&
+                    xmlStrEqual(ns->prefix, literalNs->prefix))
+               {
+                   if (xmlStrEqual(ns->href, literalNs->href))
+                       return(ns);
+                   prefixOccupied = 1;
+                   break;
+               }
+           }
+           ns = ns->next;
+       } while (ns != NULL);
+    }
+    if (prefixOccupied) {
+       /*
+       * If the ns-prefix is occupied by an other ns-decl on the
+       * result element, then this means:
+       * 1) The desired prefix is shadowed
+       * 2) There's no way around changing the prefix  
+       *
+       * Try a desperate search for an in-scope ns-decl
+       * with a matching ns-name before we use the last option,
+       * which is to recreate the ns-decl with a modified prefix.
+       */
+       ns = xmlSearchNsByHref(resultElem->doc, resultElem, literalNs->href);
+       if (ns != NULL)
+           return(ns);
+
+       /*
+       * Fallback to changing the prefix.
+       */    
+    } else if ((resultElem->parent != NULL) &&
+       (resultElem->parent->type == XML_ELEMENT_NODE)) {
+       /*
+       * Try to find a matching ns-decl in the ancestor-axis.
+       *
+       * Check the common case: The parent element of the current
+       * result element is in the same namespace (with an equal ns-prefix).
+       */     
+       if ((resultElem->parent->ns != NULL) &&
+           ((resultElem->parent->ns->prefix == NULL) ==
+            (literalNs->prefix == NULL)))
+       {
+           ns = resultElem->parent->ns;
+           
+           if (literalNs->prefix == NULL) {
+               if (xmlStrEqual(ns->href, literalNs->href))
+                   return(ns);
+           } else if ((ns->prefix[0] == literalNs->prefix[0]) &&
+               xmlStrEqual(ns->prefix, literalNs->prefix) &&
+               xmlStrEqual(ns->href, literalNs->href))
+           {
+               return(ns);
+           }
+       }
+       /*
+       * Lookup the remaining in-scope namespaces.
+       */    
+       ns = xmlSearchNs(resultElem->doc, resultElem->parent,
+           literalNs->prefix);
+       if ((ns != NULL) && xmlStrEqual(ns->href, literalNs->href))
+           return(ns);
+       ns = NULL;
+       /*
+       * Either no matching ns-prefix was found or the namespace is
+       * shadowed.
+       * Create a new ns-decl on the current result element.
+       *
+       * SPEC TODO: Hmm, we could also try to reuse an in-scope
+       *  namespace with a matching ns-name but a different
+       *  ns-prefix.
+       *  What has higher precedence? 
+       *  1) If keeping the prefix: create a new ns-decl.
+       *  2) If reusal: first lookup ns-names; then fallback
+       *     to creation of a new ns-decl.
+       */
+#if 0
+       ns = xmlSearchNsByHref(resultElem->doc, resultElem,
+           literalNs->href);
+       if (ns != NULL)
+           return(ns);
+#endif
+       /*
+       * Create the ns-decl on the current result element.
+       */
+       ns = xmlNewNs(resultElem, literalNs->href, literalNs->prefix);
+       /* TODO: check errors */
+       return(ns);
+    } else if ((resultElem->parent == NULL) ||
+       (resultElem->parent->type != XML_ELEMENT_NODE))
+    {
+       /*
+       * This is the root of the tree.
+       */
+       ns = xmlNewNs(resultElem, literalNs->href, literalNs->prefix);
+       /* TODO: Check result */
+       return(ns);
+    }
+    /*
+    * Fallback: we need to generate a new prefix and declare the namespace
+    * on the result element.
+    */
+    {
+       xmlChar prefix[30];
+       int counter = 0;
+       
+       /*
+       * Comment copied from xslGetNamespace():
+       *  "For an element node, if we don't find it, or it's the default
+       *  and this element already defines a default (bug 165560), we
+       *  need to create it."
+       */              
+       do {
+           snprintf((char *) prefix, 30, "%s_%d",
+               literalNs->prefix, counter++);
+           ns = xmlSearchNs(resultElem->doc, resultElem, BAD_CAST prefix);
+           if (counter > 1000) {
+               xsltTransformError(ctxt, NULL, cur,
+                   "Internal error in xsltTransLREAcquireInScopeNs(): "                    
+                   "Failed to compute a unique ns-prefix for the "
+                   "result element");
+               return(NULL);
+           }
+       } while (ns != NULL);
+       ns = xmlNewNs(resultElem, literalNs->href, BAD_CAST prefix);
+       /* TODO: Check result */
+       return(ns);
+    }
+    return(NULL);    
+}
 
 /**
  * xsltApplyOneTemplate:
@@ -1513,6 +1710,9 @@ xsltApplyOneTemplateInt(xsltTransformContextPtr ctxt, xmlNodePtr node,
     xmlNodePtr oldInst = NULL;
     int oldBase;
     xmlDocPtr tmpRVT = NULL;
+#ifdef XSLT_REFACTORED
+    xsltStylePreCompPtr info;
+#endif
 
     int level = 0;
 
@@ -1615,7 +1815,7 @@ xsltApplyOneTemplateInt(xsltTransformContextPtr ctxt, xmlNodePtr node,
         if (insert == NULL) {
 #ifdef WITH_XSLT_DEBUG_PROCESS
             XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
-                             "xsltApplyOneTemplate: insert == NULL !\n"));
+                             "xsltApplyOneTemplateInt: insert == NULL !\n"));
 #endif
             goto error;
         }
@@ -1625,10 +1825,403 @@ xsltApplyOneTemplateInt(xsltTransformContextPtr ctxt, xmlNodePtr node,
 #endif
 
 #ifdef XSLT_REFACTORED
-       if (IS_XSLT_ELEM_FAST(cur)) {
-#else
-        if (IS_XSLT_ELEM(cur)) {
+       if (cur->type == XML_ELEMENT_NODE) {
+           info = (xsltStylePreCompPtr) cur->psvi;
+           /*
+           * We expect a compiled representation on:
+           * 1) XSLT instructions of this XSLT version (1.0)
+           *    (with a few exceptions)
+           * 2) Literal result elements
+           * 3) Extension instructions
+           * 4) XSLT instructions of future XSLT versions
+           *    (forwards-compatible mode).
+           */
+           if (info == NULL) {
+               /*
+               * Handle the rare cases where we don't expect a compiled
+               * representation on an XSLT element.
+               */
+               if (IS_XSLT_ELEM_FAST(cur) && IS_XSLT_NAME(cur, "message")) {
+                   xsltMessage(ctxt, node, cur);
+                   goto skip_children;
+               }                                
+               /*
+               * Something really went wrong:
+               */
+               xsltTransformError(ctxt, NULL, cur,
+                   "Internal error in xsltApplyOneTemplateInt(): "
+                   "The element '%s' in the stylesheet has no compiled "
+                   "representation.\n",
+                   cur->name);
+                goto skip_children;
+            }
+
+           if (info->type == XSLT_FUNC_LITERAL_RESULT_ELEMENT) {
+               xsltStyleItemLRElementInfoPtr lrInfo =
+                   (xsltStyleItemLRElementInfoPtr) info;
+               /*
+               * Literal result elements
+               * --------------------------------------------------------
+               */
+#ifdef WITH_XSLT_DEBUG_PROCESS
+               XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,
+                   xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltApplyOneTemplateInt: copy literal result "
+                   "element '%s'\n", cur->name));
 #endif
+               /*
+               * Copy the raw element-node.
+               * OLD: if ((copy = xsltCopyNode(ctxt, cur, insert)) == NULL)
+               *   goto error;
+               */              
+               copy = xmlDocCopyNode(cur, insert->doc, 0);
+               if (copy == NULL) {
+                   xsltTransformError(ctxt, NULL, cur,
+                       "Internal error in xsltApplyOneTemplateInt(): "
+                       "Failed to copy literal result element '%s'.\n",
+                       cur->name);
+                   goto error;
+               } else {
+                   /*
+                   * Add the element-node to the result tree.
+                   */
+                   copy->doc = ctxt->output;
+                   xmlAddChild(insert, copy);
+                   /*
+                   * Create effective namespaces declarations.
+                   * OLD: xsltCopyNamespaceList(ctxt, copy, cur->nsDef);
+                   */
+                   if (lrInfo->effectiveNs != NULL) {
+                       xsltEffectiveNsPtr effNs = lrInfo->effectiveNs;
+                       xmlNsPtr ns, lastns = NULL;
+
+                       while (effNs != NULL) {
+                           /*
+                           * Avoid generating redundant namespace
+                           * declarations; thus lookup if there is already
+                           * such a ns-decl in the result.
+                           */                      
+                           ns = xmlSearchNs(copy->doc, copy,
+                               effNs->prefix);
+                           if ((ns != NULL) &&
+                               (xmlStrEqual(ns->href, effNs->nsName)))
+                           {
+                               effNs = effNs->next;
+                               continue;                           
+                           }
+                           ns = xmlNewNs(copy, effNs->nsName,
+                               effNs->prefix);
+                           if (ns == NULL) {
+                               xsltTransformError(ctxt, NULL, cur,
+                                   "Internal error in xsltApplyOneTemplateInt(): "
+                                   "Failed to copy a namespace declaration.\n");
+                               goto error;
+                           }
+                                                               
+                           if (lastns == NULL)
+                               copy->nsDef = ns;
+                           else
+                               lastns->next =ns;
+                           lastns = ns;
+
+                           effNs = effNs->next;
+                       }
+                       
+                   }
+                   /*
+                   * NOTE that we don't need to apply ns-alising: this was
+                   *  already done at compile-time.
+                   */
+                   if (cur->ns != NULL) {
+                       /*
+                       * If there's no such ns-decl in the result tree,
+                       * then xsltGetNamespace() will create a ns-decl
+                       * on the copied node.
+                       */
+                       /*
+                       * REVISIT TODO: Changed to use
+                       *  xsltTransLREAcquireInScopeNs() instead of
+                       *  xsltGetNamespace().
+                       *  OLD: copy->ns = xsltGetNamespace(ctxt, cur,
+                       *                     cur->ns, copy);
+                       */
+                       copy->ns = xsltTransLREAcquireInScopeNs(ctxt,
+                           cur, cur->ns, copy);                                                
+                   } else if ((insert->type == XML_ELEMENT_NODE) &&
+                       (insert->ns != NULL))
+                   {
+                       xmlNsPtr defaultNs;
+
+                       /*
+                       * Undeclare the default namespace if needed.
+                       * REVISIT TODO: This might result in massive
+                       *  generation of ns-decls if nodes in a default
+                       *  namespaces are mixed with nodes in no namespace.
+                       *  
+                       */                      
+                       defaultNs = xmlSearchNs(insert->doc, insert, NULL);
+                       if ((defaultNs != NULL) && (defaultNs->href != NULL))
+                           xmlNewNs(copy, BAD_CAST "", NULL);
+                   }
+               }
+               /*
+               * SPEC XSLT 2.0 "Each attribute of the literal result
+               *  element, other than an attribute in the XSLT namespace,
+               *  is processed to produce an attribute for the element in
+               *  the result tree."
+               * TODO: Refactor this, since it still uses ns-aliasing.
+               */
+               if (cur->properties != NULL) {
+                   xsltAttrListTemplateProcess(ctxt, copy, cur->properties);
+               }
+               /*
+               * OLD-COMMENT: "Add extra namespaces inherited from the
+               *   current template if we are in the first level children
+               *   and this is a "real" template.
+               *
+               * SPEC XSLT 2.0:
+               *  "The following namespaces are designated as excluded
+               *   namespaces:
+               *  - The XSLT namespace URI
+               *      (http://www.w3.org/1999/XSL/Transform)
+               *  - A namespace URI declared as an extension namespace
+               *  - A namespace URI designated by using an
+               *      [xsl:]exclude-result-prefixes
+               *
+               * TODO:
+               *  XSLT 1.0
+               *   1) Supply all in-scope namespaces
+               *   2) Skip excluded namespaces (see above)
+               *   3) Apply namespace aliasing
+               *
+               *  XSLT 2.0 (will generate
+               *            redundant namespaces in some cases):
+               *   1) Supply all in-scope namespaces
+               *   2) Skip excluded namespaces if *not* target-namespace
+               *      of an namespace alias
+               *   3) Apply namespace aliasing
+               *
+               * NOTE: See bug #341325.
+               */
+#if 0          
+               if ((templ != NULL) && (oldInsert == insert) &&
+                   (ctxt->templ != NULL) &&
+                   (ctxt->templ->inheritedNs != NULL)) {
+                   int i;
+                   xmlNsPtr ns, ret;
+                   
+                   for (i = 0; i < ctxt->templ->inheritedNsNr; i++) {
+                       const xmlChar *URI = NULL;
+                       xsltStylesheetPtr style;
+
+                       ns = ctxt->templ->inheritedNs[i];
+                       /*
+                       * Apply namespace aliasing.
+                       *
+                       * TODO: Compute the effective value of namespace
+                       *  aliases at compilation-time in order to avoid
+                       *  the lookup in the import-tree here.
+                       */
+                       style = ctxt->style;
+                       while (style != NULL) {
+                           if (style->nsAliases != NULL)
+                               URI = (const xmlChar *) 
+                                   xmlHashLookup(style->nsAliases, ns->href);
+                           if (URI != NULL)
+                               break;
+                           
+                           style = xsltNextImport(style);
+                       }
+                       if (URI == UNDEFINED_DEFAULT_NS) {
+                           xmlNsPtr defaultNs;
+
+                           defaultNs = xmlSearchNs(cur->doc, cur, NULL);
+                           if (defaultNs == NULL) {
+                               /*
+                               * TODO: Should not happen; i.e., it is
+                               *  an error at compilation-time if there's
+                               *  no default namespace in scope if
+                               *  "#default" is used.
+                               */
+                               continue;
+                           } else
+                               URI = defaultNs->href;
+                       }
+                       
+                       if (URI == NULL) {
+                           /*
+                           * There was no matching namespace-alias, so
+                           * just create a matching ns-decl if not
+                           * already in scope.
+                           */
+                           ret = xmlSearchNs(copy->doc, copy, ns->prefix);
+                           if ((ret == NULL) ||
+                               (!xmlStrEqual(ret->href, ns->href)))
+                               xmlNewNs(copy, ns->href, ns->prefix);
+                       } else if (!xmlStrEqual(URI, XSLT_NAMESPACE)) {
+                           ret = xmlSearchNs(copy->doc, copy, ns->prefix);
+                           if ((ret == NULL) ||
+                               (!xmlStrEqual(ret->href, URI))) {
+                               /*
+                               * Here we create a namespace
+                               * declaration with the literal namespace
+                               * prefix and with the target namespace name.
+                               * TODO: We should consider to fix this and
+                               *  use the *target* namespace prefix, not the
+                               *  literal one (see bug #341325).
+                               */
+                               xmlNewNs(copy, URI, ns->prefix);
+                           }
+                       }
+                   }
+                   if (copy->ns != NULL) {
+                       /*
+                       * Fix the node namespace if needed
+                       */
+                       copy->ns = xsltGetNamespace(ctxt, copy, copy->ns, copy);
+                   }
+               }
+#endif
+           } else if (IS_XSLT_ELEM_FAST(cur)) {
+               /*
+               * XSLT instructions
+               * --------------------------------------------------------
+               */
+               if (info->type == XSLT_FUNC_UNKOWN_FORWARDS_COMPAT) {
+                   /*
+                   * We hit an unknown XSLT element.
+                   * Try to apply one of the fallback cases.
+                   */          
+                   ctxt->insert = insert;
+                   if (!xsltApplyFallbacks(ctxt, node, cur)) {
+                       xsltTransformError(ctxt, NULL, cur,
+                           "The is no fallback behaviour defined for "
+                           "the unknown XSLT element '%s'.\n",
+                           cur->name);
+                   }                   
+                   ctxt->insert = oldInsert;
+                   goto skip_children;
+               }
+               /*
+               * Execute the XSLT instruction.
+               */
+               if (info->func != NULL) {
+                   ctxt->insert = insert;
+                   info->func(ctxt, node, cur, (xsltElemPreCompPtr) info);
+                   ctxt->insert = oldInsert;
+                   goto skip_children;
+               }
+               /*
+               * Some XSLT instructions need custom execution.
+               */               
+               if (info->type == XSLT_FUNC_VARIABLE) {
+                   if (level != 0) {
+                       /*
+                       * Build a new subframe and skip all the nodes
+                       * at that level.
+                       */
+                       ctxt->insert = insert;
+                       xsltApplyOneTemplateInt(ctxt, node, cur, NULL, NULL, 0);
+                       while (cur->next != NULL)
+                           cur = cur->next;
+                       ctxt->insert = oldInsert;
+                   } else {
+                       xsltParseStylesheetVariable(ctxt, cur);
+                   }
+               } else if (info->type == XSLT_FUNC_PARAM) {
+                   xsltParseStylesheetParam(ctxt, cur);
+               } else if (info->type == XSLT_FUNC_MESSAGE) {
+                   /*
+                   * TODO: Won't be hit, since we don't compile xsl:message.
+                   */
+                   xsltMessage(ctxt, node, cur);
+               } else {
+                   xsltGenericError(xsltGenericErrorContext,
+                       "Internal error in xsltApplyOneTemplateInt(): "
+                       "Don't know how to process the XSLT element "
+                       "'%s'.\n", cur->name);                  
+               }
+               goto skip_children;
+
+           } else {
+               xsltTransformFunction func;
+               /*
+               * Extension intructions (elements)
+               * --------------------------------------------------------
+               */                              
+               if (cur->psvi == xsltExtMarker) {
+                   /*
+                   * The xsltExtMarker was set during the compilation
+                   * of extension instructions if there was no registered
+                   * handler for this specific extension function at
+                   * compile-time.
+                   * Libxslt will now lookup if a handler is
+                   * registered in the context of this transformation.
+                   */
+                   func = (xsltTransformFunction)
+                       xsltExtElementLookup(ctxt, cur->name, cur->ns->href);
+               } else
+                   func = ((xsltElemPreCompPtr) cur->psvi)->func;
+               
+               if (func == NULL) {
+                   /*
+                   * No handler available.
+                   * Try to execute fallback behaviour via xsl:fallback.
+                   */
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,
+                       xsltGenericDebug(xsltGenericDebugContext,
+                           "xsltApplyOneTemplate: unknown extension %s\n",
+                           cur->name));
+#endif
+                   ctxt->insert = insert;
+                   if (!xsltApplyFallbacks(ctxt, node, cur)) {
+                       xsltTransformError(ctxt, NULL, cur,
+                           "Unknown extension instruction '{%s}%s'.\n",
+                           cur->ns->href, cur->name);
+                   }                   
+                   ctxt->insert = oldInsert;               
+               } else {
+                   /*
+                   * Execute the handler-callback.
+                   */
+#ifdef WITH_XSLT_DEBUG_PROCESS
+                   XSLT_TRACE(ctxt,XSLT_TRACE_APPLY_TEMPLATE,xsltGenericDebug(xsltGenericDebugContext,
+                       "xsltApplyOneTemplate: extension construct %s\n",
+                       cur->name));
+#endif             
+                   ctxt->insert = insert;
+                   func(ctxt, node, cur, cur->psvi);
+                   ctxt->insert = oldInsert;
+               }
+               goto skip_children;
+           }
+
+       } else if (XSLT_IS_TEXT_NODE(cur)) {
+           /*
+           * Text
+           * ------------------------------------------------------------
+           */
+#ifdef WITH_XSLT_DEBUG_PROCESS
+            if (cur->name == xmlStringTextNoenc) {
+                XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,
+                   xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltApplyOneTemplateInt: copy unescaped text '%s'\n",
+                   cur->content));
+            } else {
+                XSLT_TRACE(ctxt, XSLT_TRACE_APPLY_TEMPLATE,
+                   xsltGenericDebug(xsltGenericDebugContext,
+                   "xsltApplyOneTemplateInt: copy text '%s'\n",
+                   cur->content));
+            }
+#endif
+            if (xsltCopyText(ctxt, insert, cur, ctxt->internalized) == NULL)
+               goto error;         
+       }
+
+#else /* XSLT_REFACTORED */
+
+        if (IS_XSLT_ELEM(cur)) {
             /*
              * This is an XSLT node
              */
@@ -1685,6 +2278,7 @@ xsltApplyOneTemplateInt(xsltTransformContextPtr ctxt, xmlNodePtr node,
             goto skip_children;
         } else if ((cur->type == XML_TEXT_NODE) ||
                    (cur->type == XML_CDATA_SECTION_NODE)) {
+
             /*
              * This text comes from the stylesheet
              * For stylesheets, the set of whitespace-preserving
@@ -1778,7 +2372,7 @@ xsltApplyOneTemplateInt(xsltTransformContextPtr ctxt, xmlNodePtr node,
             /*
              * Add extra namespaces inherited from the current template
              * if we are in the first level children and this is a
-            * "real" template.
+            * "real" template.      
              */
             if ((templ != NULL) && (oldInsert == insert) &&
                 (ctxt->templ != NULL) && (ctxt->templ->inheritedNs != NULL)) {
@@ -1799,7 +2393,7 @@ xsltApplyOneTemplateInt(xsltTransformContextPtr ctxt, xmlNodePtr node,
                      
                      style = xsltNextImport(style);
                    }
-
+                                   
                    if (URI == UNDEFINED_DEFAULT_NS) {
                      xmlNsPtr dflt;
                      dflt = xmlSearchNs(cur->doc, cur, NULL);
@@ -1829,9 +2423,10 @@ xsltApplyOneTemplateInt(xsltTransformContextPtr ctxt, xmlNodePtr node,
                }
             }
         }
+#endif /* else of XSLT_REFACTORED */
 
         /*
-         * Skip to next node, in document order.
+         * Descend into content in document order.
          */
         if (cur->children != NULL) {
             if (cur->children->type != XML_ENTITY_DECL) {
@@ -1842,10 +2437,13 @@ xsltApplyOneTemplateInt(xsltTransformContextPtr ctxt, xmlNodePtr node,
                 continue;
             }
         }
-      skip_children:
+
+skip_children:
        /*
-       If xslt:message just processed, might have terminate='yes'
-       If so, break out of while to clean up processing.
+       * If xslt:message was just processed, we might have hit a
+       * terminate='yes'; if so, then break the loop and clean up.
+       * TODO: Do we need to check this also before trying to descend
+       *  into the content?
        */
        if (ctxt->state == XSLT_STATE_STOPPED)
            break;
@@ -2466,7 +3064,7 @@ xsltSort(xsltTransformContextPtr ctxt,
  * @inst:  the xslt copy node
  * @comp:  precomputed information
  *
- * Process the xslt copy node on the source node
+ * Execute the xsl:copy instruction on the source node.
  */
 void
 xsltCopy(xsltTransformContextPtr ctxt, xmlNodePtr node,
index 8d1dd03..ce31817 100644 (file)
@@ -27,6 +27,7 @@
 #include <libxml/xmlerror.h>
 #include <libxml/parserInternals.h>
 #include <libxml/xpathInternals.h>
+#include <libxml/xpath.h>
 #include "xslt.h"
 #include "xsltInternals.h"
 #include "pattern.h"
@@ -55,15 +56,6 @@ const int xsltLibxmlVersion = LIBXML_VERSION;
 
 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
@@ -426,60 +418,21 @@ xsltFreeTemplateList(xsltTemplatePtr template) {
 }
 
 #ifdef XSLT_REFACTORED
-/**
- * xsltCompilerCreate:
- *
- * Create an XSLT compiler context.
- *
- * Returns the allocated xsltCompilerCtxtPtr or NULL in case of error.
- */
-static xsltCompilerCtxtPtr
-xsltCompilerCreate(xsltStylesheetPtr style) {
-    xsltCompilerCtxtPtr ret;
-
-    ret = (xsltCompilerCtxtPtr) xmlMalloc(sizeof(xsltCompilerCtxt));
-    if (ret == NULL) {
-       xsltTransformError(NULL, style, NULL,
-           "xsltCompilerCreate: allocation of compiler "
-           "context failed.\n");
-       return(NULL);
-    }
-    memset(ret, 0, sizeof(xsltCompilerCtxt));
-
-    ret->errSeverity = XSLT_ERROR_SEVERITY_ERROR;
-
-    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;
-    /*
-    * Free node-infos.
-    */
-    if (cctxt->inodeList != NULL) {
-       xsltCompilerNodeInfoPtr tmp, cur = cctxt->inodeList;
-       while (cur != NULL) {
-           tmp = cur;
-           cur = cur->next;
-           xmlFree(tmp);
-       }
-    }
-    if (cctxt->tmpList != NULL)
-       xsltPointerListFree(cctxt->tmpList);
-    xmlFree(cctxt);
+xsltFreeNsAliasList(xsltNsAliasPtr item)
+{
+    xsltNsAliasPtr tmp;
+    
+    while (item) {
+       tmp = item;
+       item = item->next;
+       xmlFree(tmp);
+    } 
+    return;
 }
 
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
 static void
 xsltFreeNamespaceMap(xsltNsMapPtr item)
 {
@@ -525,6 +478,80 @@ xsltNewNamespaceMapItem(xsltCompilerCtxtPtr cctxt,
 
     return(ret);
 }
+#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
+
+/**
+ * xsltCompilerCtxtFree:
+ *
+ * Free an XSLT compiler context. 
+ */
+static void
+xsltCompilationCtxtFree(xsltCompilerCtxtPtr cctxt)
+{    
+    if (cctxt == NULL)
+       return;
+    /*
+    * Free node-infos.
+    */
+    if (cctxt->inodeList != NULL) {
+       xsltCompilerNodeInfoPtr tmp, cur = cctxt->inodeList;
+       while (cur != NULL) {
+           tmp = cur;
+           cur = cur->next;
+           xmlFree(tmp);
+       }
+    }
+    if (cctxt->tmpList != NULL)
+       xsltPointerListFree(cctxt->tmpList);
+    if (cctxt->xpathCtxt != NULL)
+       xmlXPathFreeContext(cctxt->xpathCtxt);
+    if (cctxt->nsAliases != NULL)
+       xsltFreeNsAliasList(cctxt->nsAliases);
+
+    xmlFree(cctxt);
+}
+
+/**
+ * xsltCompilerCreate:
+ *
+ * Creates an XSLT compiler context.
+ *
+ * Returns the pointer to the created xsltCompilerCtxt or
+ *         NULL in case of an internal error.
+ */
+static xsltCompilerCtxtPtr
+xsltCompilationCtxtCreate(xsltStylesheetPtr style) {
+    xsltCompilerCtxtPtr ret;
+
+    ret = (xsltCompilerCtxtPtr) xmlMalloc(sizeof(xsltCompilerCtxt));
+    if (ret == NULL) {
+       xsltTransformError(NULL, style, NULL,
+           "xsltCompilerCreate: allocation of compiler "
+           "context failed.\n");
+       return(NULL);
+    }
+    memset(ret, 0, sizeof(xsltCompilerCtxt));
+
+    ret->errSeverity = XSLT_ERROR_SEVERITY_ERROR;
+    ret->tmpList = xsltPointerListCreate(20);
+    if (ret->tmpList == NULL) {
+       goto internal_err;
+    }
+    /*
+    * Create the XPath compilation context in order
+    * to speed up precompilation of XPath expressions.
+    */
+    ret->xpathCtxt = xmlXPathNewContext(NULL);
+    if (ret->xpathCtxt == NULL)
+       goto internal_err;
+    
+    return(ret);
+
+internal_err:
+    xsltCompilationCtxtFree(ret);
+    return(NULL);
+}
+
 
 static void
 xsltFreePrincipalStylesheetData(xsltPrincipalStylesheetDataPtr data)
@@ -534,7 +561,7 @@ xsltFreePrincipalStylesheetData(xsltPrincipalStylesheetDataPtr data)
 
     if (data->inScopeNamespaces != NULL) {
        int i;
-       xsltNsListPtr nsi;
+       xsltNsListContainerPtr nsi;
        xsltPointerListPtr list =
            (xsltPointerListPtr) data->inScopeNamespaces;
 
@@ -542,7 +569,7 @@ xsltFreePrincipalStylesheetData(xsltPrincipalStylesheetDataPtr data)
            /*
            * REVISIT TODO: Free info of in-scope namespaces.
            */
-           nsi = (xsltNsListPtr) list->items[i];
+           nsi = (xsltNsListContainerPtr) list->items[i];
            if (nsi->list != NULL)
                xmlFree(nsi->list);
            xmlFree(nsi);
@@ -574,7 +601,9 @@ xsltFreePrincipalStylesheetData(xsltPrincipalStylesheetDataPtr data)
        xsltPointerListFree(list);
        data->extElemNamespaces = NULL;
     }
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
     xsltFreeNamespaceMap(data->nsMap);
+#endif
     xmlFree(data);
 }
 
@@ -600,12 +629,12 @@ xsltNewPrincipalStylesheetData(void)
        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.
+    * Global list of extension instruction namespace names.
     */    
     ret->extElemNamespaces = xsltPointerListCreate(-1);
     if (ret->extElemNamespaces == NULL)
@@ -767,7 +796,8 @@ xsltFreeStylesheetList(xsltStylesheetPtr style) {
  */
 static int
 xsltCleanupStylesheetTree(xmlDocPtr doc, xmlNodePtr rootElem)
-{
+{    
+#if 0 /* TODO: Currently disabled, since probably not needed. */
     xmlNodePtr cur;
 
     if ((doc == NULL) || (rootElem == NULL) ||
@@ -808,6 +838,7 @@ leave_node:
            goto leave_node;
        }
     }
+#endif /* #if 0 */
     return(0);
 }
 
@@ -830,6 +861,7 @@ xsltFreeStylesheet(xsltStylesheetPtr style)
     if ((style->principal == style) && (style->doc))
        xsltCleanupStylesheetTree(style->doc,
            xmlDocGetRootElement(style->doc));
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
     /*
     * Restore changed ns-decls before freeing the document.
     */
@@ -839,6 +871,7 @@ xsltFreeStylesheet(xsltStylesheetPtr style)
        xsltRestoreDocumentNamespaces(XSLT_GET_INTERNAL_NSMAP(style),
            style->doc);        
     }
+#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
 #else
     /*
     * Start with a cleanup of the main stylesheet's doc.
@@ -846,7 +879,7 @@ xsltFreeStylesheet(xsltStylesheetPtr style)
     if ((style->parent == NULL) && (style->doc))
        xsltCleanupStylesheetTree(style->doc,
            xmlDocGetRootElement(style->doc));
-#endif
+#endif /* XSLT_REFACTORED */
 
     xsltFreeKeys(style);
     xsltFreeExts(style);
@@ -1434,13 +1467,13 @@ xsltParseStylesheetPreserveSpace(xsltStylesheetPtr style, xmlNodePtr cur) {
  * @template:  the "extension-element-prefixes" prefix
  *
  * parse an XSLT stylesheet's "extension-element-prefix" attribute value
- * and register the namespaces of extension elements.
+ * and register the namespaces of extension instruction.
  * SPEC "A namespace is designated as an extension namespace by using
  *   an extension-element-prefixes attribute on:
  *   1) an xsl:stylesheet element
- *   2) TODO: an xsl:extension-element-prefixes attribute on a
+ *   2) an xsl:extension-element-prefixes attribute on a
  *      literal result element 
- *   3) TODO: an extension element."
+ *   3) an extension instruction."
  */
 static void
 xsltParseStylesheetExtPrefix(xsltStylesheetPtr style, xmlNodePtr cur,
@@ -1456,7 +1489,7 @@ xsltParseStylesheetExtPrefix(xsltStylesheetPtr style, xmlNodePtr cur,
        prefixes = xmlGetNsProp(cur,
            (const xmlChar *)"extension-element-prefixes", NULL);
     } else {
-       /* For literal result elements and extension elements. */
+       /* For literal result elements and extension instructions. */
        prefixes = xmlGetNsProp(cur,
            (const xmlChar *)"extension-element-prefixes", XSLT_NAMESPACE);
     }
@@ -1637,6 +1670,423 @@ xsltParseStylesheetExcludePrefix(xsltStylesheetPtr style, xmlNodePtr cur,
 #ifdef XSLT_REFACTORED
 
 /*
+* xsltTreeEnsureXMLDecl:
+* @doc: the doc
+* 
+* BIG NOTE:
+*  This was copy&pasted from Libxml2's xmlTreeEnsureXMLDecl() in "tree.c".
+* Ensures that there is an XML namespace declaration on the doc.
+* 
+* Returns the XML ns-struct or NULL on API and internal errors.
+*/
+static xmlNsPtr
+xsltTreeEnsureXMLDecl(xmlDocPtr doc)
+{
+    if (doc == NULL)
+       return (NULL);
+    if (doc->oldNs != NULL)
+       return (doc->oldNs);
+    {
+       xmlNsPtr ns;
+       ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
+       if (ns == NULL) {
+           xmlGenericError(xmlGenericErrorContext,
+               "xsltTreeEnsureXMLDecl: Failed to allocate "
+               "the XML namespace.\n");        
+           return (NULL);
+       }
+       memset(ns, 0, sizeof(xmlNs));
+       ns->type = XML_LOCAL_NAMESPACE;
+       ns->href = xmlStrdup(XML_XML_NAMESPACE); 
+       ns->prefix = xmlStrdup((const xmlChar *)"xml");
+       doc->oldNs = ns;
+       return (ns);
+    }
+}
+
+/*
+* xsltTreeAcquireStoredNs:
+* @doc: the doc
+* @nsName: the namespace name
+* @prefix: the prefix
+* 
+* BIG NOTE:
+*  This was copy&pasted from Libxml2's xmlDOMWrapStoreNs() in "tree.c".
+* Creates or reuses an xmlNs struct on doc->oldNs with
+* the given prefix and namespace name.
+* 
+* Returns the aquired ns struct or NULL in case of an API
+*         or internal error.
+*/
+static xmlNsPtr
+xsltTreeAcquireStoredNs(xmlDocPtr doc,
+                       const xmlChar *nsName,
+                       const xmlChar *prefix)
+{
+    xmlNsPtr ns;
+
+    if (doc == NULL)
+       return (NULL);
+    ns = xsltTreeEnsureXMLDecl(doc);
+    if (ns == NULL)
+       return (NULL);
+    if (ns->next != NULL) {
+       /* Reuse. */
+       ns = ns->next;
+       while (ns != NULL) {
+           if ((ns->prefix == NULL) != (prefix == NULL)) {
+               /* NOP */
+           } else if (prefix == NULL) {
+               if (xmlStrEqual(ns->href, nsName))
+                   return (ns);
+           } else {
+               if ((ns->prefix[0] == prefix[0]) &&
+                    xmlStrEqual(ns->prefix, prefix) &&
+                    xmlStrEqual(ns->href, nsName))
+                   return (ns);
+               
+           }
+           if (ns->next == NULL)
+               break;
+           ns = ns->next;
+       }
+    }
+    /* Create. */
+    ns->next = xmlNewNs(NULL, nsName, prefix);
+    return (ns->next);
+}
+
+/**
+ * xsltLREBuildEffectiveNs:
+ *
+ * Apply ns-aliasing on the namespace of the given @elem and
+ * its attributes.
+ */
+static int
+xsltLREBuildEffectiveNs(xsltCompilerCtxtPtr cctxt,
+                       xmlNodePtr elem)
+{
+    xmlNsPtr ns;
+    xsltNsAliasPtr alias;
+
+    if ((cctxt == NULL) || (elem == NULL))
+       return(-1);
+    if ((cctxt->nsAliases == NULL) || (! cctxt->hasNsAliases))
+       return(0);
+
+    alias = cctxt->nsAliases;                  
+    while (alias != NULL) {
+       if ( /* If both namespaces are NULL... */
+           ( (elem->ns == NULL) &&
+           ((alias->literalNs == NULL) ||
+           (alias->literalNs->href == NULL)) ) ||
+           /* ... or both namespace are equal */
+           ( (elem->ns != NULL) &&
+           (alias->literalNs != NULL) &&
+           xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )
+       {
+           if ((alias->targetNs != NULL) &&
+               (alias->targetNs->href != NULL))
+           {
+               /*
+               * Convert namespace.
+               */
+               if (elem->doc == alias->docOfTargetNs) {
+                   /*
+                   * This is the nice case: same docs.
+                   * This will eventually assign a ns-decl which
+                   * is shadowed, but this has no negative effect on
+                   * the generation of the result tree.
+                   */
+                   elem->ns = alias->targetNs;
+               } else {
+                   /*
+                   * This target xmlNs originates from a different
+                   * stylesheet tree. Try to locate it in the
+                   * in-scope namespaces.
+                   * OPTIMIZE TODO: Use the compiler-node-info inScopeNs.
+                   */
+                   ns = xmlSearchNs(elem->doc, elem,
+                       alias->targetNs->prefix);                   
+                   /*
+                   * If no matching ns-decl found, then assign a
+                   * ns-decl stored in xmlDoc.
+                   */
+                   if ((ns == NULL) ||
+                       (! xmlStrEqual(ns->href, alias->targetNs->href)))
+                   {
+                       /*
+                       * BIG NOTE: The use of xsltTreeAcquireStoredNs()
+                       *  is not very efficient, but currently I don't
+                       *  see an other way of *safely* changing a node's
+                       *  namespace, since the xmlNs struct in
+                       *  alias->targetNs might come from an other
+                       *  stylesheet tree. So we need to anchor it in the
+                       *  current document, without adding it to the tree,
+                       *  which would otherwise change the in-scope-ns
+                       *  semantic of the tree.
+                       */
+                       ns = xsltTreeAcquireStoredNs(elem->doc,
+                           alias->targetNs->href,
+                           alias->targetNs->prefix);
+                       
+                       if (ns == NULL) {
+                           xsltTransformError(NULL, cctxt->style, elem,
+                               "Internal error in "
+                               "xsltLREBuildEffectiveNs(): "
+                               "failed to acquire a stored "
+                               "ns-declaration.\n");
+                           cctxt->style->errors++;
+                           return(-1);
+                           
+                       }
+                   }
+                   elem->ns = ns;
+               }                  
+           } else {
+               /*
+               * Move into or leave in the NULL namespace.
+               */
+               elem->ns = NULL;
+           }
+           break;
+       }
+       alias = alias->next;
+    }
+    /*
+    * Same with attributes of literal result elements.
+    */
+    if (elem->properties != NULL) {
+       xmlAttrPtr attr = elem->properties;
+       
+       while (attr != NULL) {
+           if (attr->ns == NULL) {
+               attr = attr->next;
+               continue;
+           }
+           alias = cctxt->nsAliases;
+           while (alias != NULL) {
+               if ( /* If both namespaces are NULL... */
+                   ( (elem->ns == NULL) &&
+                   ((alias->literalNs == NULL) ||
+                   (alias->literalNs->href == NULL)) ) ||
+                   /* ... or both namespace are equal */
+                   ( (elem->ns != NULL) &&
+                   (alias->literalNs != NULL) &&
+                   xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )
+               {
+                   if ((alias->targetNs != NULL) &&
+                       (alias->targetNs->href != NULL))
+                   {               
+                       if (elem->doc == alias->docOfTargetNs) {
+                           elem->ns = alias->targetNs;
+                       } else {
+                           ns = xmlSearchNs(elem->doc, elem,
+                               alias->targetNs->prefix);
+                           if ((ns == NULL) ||
+                               (! xmlStrEqual(ns->href, alias->targetNs->href)))
+                           {
+                               ns = xsltTreeAcquireStoredNs(elem->doc,
+                                   alias->targetNs->href,
+                                   alias->targetNs->prefix);
+                               
+                               if (ns == NULL) {
+                                   xsltTransformError(NULL, cctxt->style, elem,
+                                       "Internal error in "
+                                       "xsltLREBuildEffectiveNs(): "
+                                       "failed to acquire a stored "
+                                       "ns-declaration.\n");
+                                   cctxt->style->errors++;
+                                   return(-1);
+                                   
+                               }
+                           }
+                           elem->ns = ns;
+                       }
+                   } else {
+                   /*
+                   * Move into or leave in the NULL namespace.
+                       */
+                       elem->ns = NULL;
+                   }
+                   break;
+               }
+               alias = alias->next;
+           }
+           
+           attr = attr->next;
+       }
+    }
+    return(0);
+}
+
+/**
+ * xsltLREBuildEffectiveNsNodes:
+ *
+ * Computes the effective namespaces nodes for a literal result
+ * element.
+ * @effectiveNs is the set of effective ns-nodes
+ *  on the literal result element, which will be added to the result
+ *  element if not already existing in the result tree.
+ *  This means that excluded namespaces (via exclude-result-prefixes,
+ *  extension-element-prefixes and the XSLT namespace) not added
+ *  to the set.
+ *  Namespace-aliasing was applied on the @effectiveNs.
+ */
+static int
+xsltLREBuildEffectiveNsNodes(xsltCompilerCtxtPtr cctxt,
+                            xsltStyleItemLRElementInfoPtr item,
+                            xmlNodePtr elem)
+{
+    xmlNsPtr ns;
+    xsltEffectiveNsPtr effNs, lastEffNs = NULL;
+    int i;
+    xsltPointerListPtr extElemNs = cctxt->inode->extElemNs;
+    xsltPointerListPtr exclResultNs = cctxt->inode->exclResultNs;
+
+    if ((cctxt == NULL) || (cctxt->inode == NULL) || (elem == NULL) ||
+       (item == NULL) || (item->effectiveNs != NULL))
+       return(-1);
+
+    if (elem->nsDef == NULL)
+       return(0);
+
+    extElemNs = cctxt->inode->extElemNs;
+    exclResultNs = cctxt->inode->exclResultNs;
+
+    for (ns = elem->nsDef; ns != NULL; ns = ns->next) {
+       /*
+       * Skip namespaces designated as excluded namespaces
+       * -------------------------------------------------
+       *
+       * XSLT-20 TODO: In XSLT 2.0 we need to keep namespaces
+       *  which are target namespaces of namespace-aliases
+       *  regardless if designated as excluded.
+       *
+       * Exclude the XSLT namespace.
+       */
+       if (xmlStrEqual(ns->href, XSLT_NAMESPACE))
+           goto skip_ns;
+       
+       /*
+       * Exclude excluded result namespaces.
+       */
+       if (exclResultNs) {
+           for (i = 0; i < exclResultNs->number; i++)
+               if (xmlStrEqual(ns->href, BAD_CAST exclResultNs->items[i]))
+                   goto skip_ns;
+       }
+       /*
+       * Exclude extension-element namespaces.
+       */
+       if (extElemNs) {
+           for (i = 0; i < extElemNs->number; i++)
+               if (xmlStrEqual(ns->href, BAD_CAST extElemNs->items[i]))
+                   goto skip_ns;
+       }
+       /*
+       * Apply namespace aliasing
+       * ------------------------
+       * 
+       * NOTE: The ns-aliasing machanism is non-cascading.
+       *  (checked with Saxon, Xalan and MSXML .NET).
+       * URGENT TODO: is style->nsAliases the effective list of
+       *  ns-aliases, or do we need to lookup the whole
+       *  import-tree?
+       * TODO: Get rid of import-tree lookup.
+       */
+       if (cctxt->hasNsAliases) {
+           xsltNsAliasPtr alias = cctxt->nsAliases;
+           do {
+               /*
+               * TODO: What to do with xmlns="" ?
+               */
+               if ((alias->literalNs != NULL) &&
+                   (alias->literalNs->href == ns->href))
+               {
+                   /*
+                   * Recognized as an namespace alias; convert it to
+                   * the target namespace.
+                   */
+                   ns = alias->literalNs;
+                   break;
+               }
+               alias = alias->next;
+           } while (alias != NULL);            
+       }
+       /*
+       * Add the effective namespace declaration.
+       */
+       effNs = (xsltEffectiveNsPtr) xmlMalloc(sizeof(xsltEffectiveNs));
+       if (effNs == NULL) {
+           xsltTransformError(NULL, cctxt->style, elem,
+               "Internal error in xsltLREBuildEffectiveNs(): "
+               "failed to allocate memory.\n");
+           cctxt->style->errors++;
+           return(-1);
+       }
+       effNs->next = NULL;
+       effNs->prefix = ns->prefix;
+       effNs->nsName = ns->href;
+       
+       if (lastEffNs == NULL)
+           item->effectiveNs = effNs;
+       else
+           lastEffNs->next = effNs;
+       lastEffNs = effNs;              
+       
+skip_ns:
+       {}
+    }
+    return(0);
+}
+
+
+/**
+ * xsltLREInfoCreate:
+ *
+ * Creates a new info for a literal result element.
+ */
+static int
+xsltLREInfoCreate(xsltCompilerCtxtPtr cctxt,
+                                  xmlNodePtr elem)
+{
+    xsltStyleItemLRElementInfoPtr item;
+
+    if ((cctxt == NULL) || (cctxt->inode == NULL))
+       return(-1);
+
+    item = (xsltStyleItemLRElementInfoPtr)
+       xmlMalloc(sizeof(xsltStyleItemLRElementInfo));
+    if (item == NULL) {
+       xsltTransformError(NULL, cctxt->style, NULL,
+           "Internal error in xsltLREInfoCreate(): "
+           "memory allocation failed.\n");
+       cctxt->style->errors++;
+       return(-1);
+    }
+    memset(item, 0, sizeof(xsltStyleItemLRElementInfo));
+    item->type = XSLT_FUNC_LITERAL_RESULT_ELEMENT;
+    /*
+    * Store it in the stylesheet.
+    */
+    item->next = cctxt->style->preComps;
+    cctxt->style->preComps = (xsltElemPreCompPtr) item;
+    /*
+    * @inScopeNs are used for execution of XPath expressions
+    *  in AVTs.
+    */
+    item->inScopeNs = cctxt->inode->inScopeNs;
+    
+    if (elem && (elem->nsDef != NULL)) 
+       xsltLREBuildEffectiveNsNodes(cctxt, item, elem);        
+
+    cctxt->inode->litResElemInfo = item;
+    cctxt->inode->nsChanged = 0;
+    return(0);
+}
+
+/*
 * xsltCompilerNodePush:
 *
 * @cctxt: the compilation context
@@ -1673,19 +2123,24 @@ xsltCompilerNodePush(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
            inode->prev = cctxt->inodeLast;
        }
        cctxt->inodeLast = inode;
-       cctxt->maxNodeInfos++;
-    }
-    /*
-    * REVISIT TODO: Keep the reset always complete.
-    */
+       cctxt->maxNodeInfos++;  
+       if (cctxt->inode == NULL) {
+           cctxt->inode = inode;
+           /*
+           * Create an initial literal result element info for
+           * the root of the stylesheet.
+           */
+           xsltLREInfoCreate(cctxt, NULL);
+       } 
+    }       
     cctxt->depth++;
-
+    cctxt->inode = inode;
     /*
+    * REVISIT TODO: Keep the reset always complete.    
     * NOTE: Be carefull with the @node, since it might be
     *  a doc-node.
     */
     inode->node = node;
-
     inode->depth = cctxt->depth;
     inode->templ = NULL;
     inode->category = XSLT_ELEMENT_CATEGORY_XSLT;
@@ -1695,25 +2150,33 @@ xsltCompilerNodePush(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
     inode->extContentHandled = 0;
     inode->isRoot = 0;
     
-    if (inode->prev != NULL) {
+    if (inode->prev != NULL) { 
        /*
        * Inherit the following information:
+       * ---------------------------------
+       *
+       * In-scope namespaces
        */
        inode->inScopeNs = inode->prev->inScopeNs;
        /*
-       * in-scope namespaces
+       * Info for literal result elements
+       */
+       inode->litResElemInfo = inode->prev->litResElemInfo;
+       inode->nsChanged = inode->prev->nsChanged;
+       /*
+       * Excluded result namespaces
        */
        inode->exclResultNs = inode->prev->exclResultNs;
        /*
-       * extension-element namespaces
+       * Extension instruction namespaces
        */
        inode->extElemNs = inode->prev->extElemNs;
        /*
-       * whitespace perservation
+       * Whitespace preservation
        */
        inode->preserveWhitespace = inode->prev->preserveWhitespace;
        /*
-       * forwards-compatible mode
+       * Forwards-compatible mode
        */
        inode->forwardsCompat = inode->prev->forwardsCompat;    
     } else {
@@ -1723,7 +2186,7 @@ xsltCompilerNodePush(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
        inode->preserveWhitespace = 0;
        inode->forwardsCompat = 0;
     }
-    cctxt->inode = inode;
+    
     return(inode);
 }
 
@@ -1816,10 +2279,10 @@ mismatch:
 *
 * Returns the ns-info or NULL if there are no namespaces in scope.
 */
-static xsltNsListPtr
+static xsltNsListContainerPtr
 xsltCompilerBuildInScopeNsList(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
 {
-    xsltNsListPtr nsi = NULL;
+    xsltNsListContainerPtr nsi = NULL;
     xmlNsPtr *list = NULL;
     /*
     * Create a new ns-list for this position in the node-tree.
@@ -1834,13 +2297,13 @@ xsltCompilerBuildInScopeNsList(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
     /*
     * Create the info-structure.
     */
-    nsi = (xsltNsListPtr) xmlMalloc(sizeof(xsltNsList));
+    nsi = (xsltNsListContainerPtr) xmlMalloc(sizeof(xsltNsListContainer));
     if (nsi == NULL) { 
        xsltTransformError(NULL, cctxt->style, NULL,
            "xsltCompilerBuildInScopeNsList: malloc failed.\n");
        goto internal_err;
     }
-    memset(nsi, 0, sizeof(xsltNsList));
+    memset(nsi, 0, sizeof(xsltNsListContainer));
     nsi->list = list;
     /*
     * Eval the number of ns-decls; this is used to speed up
@@ -1860,7 +2323,12 @@ xsltCompilerBuildInScopeNsList(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
        xsltTransformError(NULL, cctxt->style, NULL,
            "xsltCompilerBuildInScopeNsList: failed to add ns-info.\n");
        goto internal_err;
-    }     
+    }
+    /*
+    * Notify of change in status wrt namespaces.
+    */
+    if (cctxt->inode != NULL)
+       cctxt->inode->nsChanged = 1;
 
     return(nsi);
 
@@ -2038,7 +2506,7 @@ xsltParseExclResultPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
     if (list == NULL)
        goto exit;    
     /*
-    * Store the list in the stylesheet.
+    * Store the list in the stylesheet/compiler context.
     */
     if (xsltPointerListAddSize(
        cctxt->psData->exclResultNamespaces, list, 5) == -1)
@@ -2047,6 +2515,11 @@ xsltParseExclResultPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
        list = NULL;
        goto exit;
     }
+    /*
+    * Notify of change in status wrt namespaces.
+    */
+    if (cctxt->inode != NULL)
+       cctxt->inode->nsChanged = 1;
 
 exit:
     if (value != NULL)
@@ -2116,6 +2589,11 @@ xsltParseExtElemPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
        list = NULL;
        goto exit;
     }
+    /*
+    * Notify of change in status wrt namespaces.
+    */
+    if (cctxt->inode != NULL)
+       cctxt->inode->nsChanged = 1;
 
 exit:
     if (value != NULL)
@@ -2195,7 +2673,9 @@ xsltParsePreprocessStylesheetTree(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
     xmlChar *value;
     const xmlChar *name, *nsNameXSLT = NULL;
     int strictWhitespace, inXSLText = 0;
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
     xsltNsMapPtr nsMapItem;
+#endif
 
     if ((cctxt == NULL) || (cctxt->style == NULL) ||
        (node == NULL) || (node->type != XML_ELEMENT_NODE))
@@ -2203,7 +2683,7 @@ xsltParsePreprocessStylesheetTree(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
 
     doc = node->doc;
     if (doc == NULL)
-       return(-1);
+       goto internal_err;
 
     style = cctxt->style;
     if ((style->dict != NULL) && (doc->dict == style->dict))
@@ -2264,6 +2744,7 @@ xsltParsePreprocessStylesheetTree(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
            * TODO: I'd love to use a string pointer comparison here :-/
            */
            if (IS_XSLT_ELEM(cur)) {
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
                if (cur->ns->href != nsNameXSLT) {
                    nsMapItem = xsltNewNamespaceMapItem(cctxt,                  
                        doc, cur, cur->ns);
@@ -2271,6 +2752,7 @@ xsltParsePreprocessStylesheetTree(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
                        goto internal_err;
                    cur->ns->href = nsNameXSLT;
                }
+#endif
 
                if (cur->name == NULL)
                    goto process_attributes;
@@ -3005,10 +3487,10 @@ xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)
 
     elem->psvi = NULL;
 
-    if (! (IS_IN_XSLT_NS(elem)))
+    if (! (IS_XSLT_ELEM_FAST(elem)))
        return(-1);
     /*
-    * Detection of handled content of extension elements.
+    * Detection of handled content of extension instructions.
     */
     if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
        cctxt->inode->extContentHandled = 1;
@@ -3131,18 +3613,15 @@ apply_templates:
        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; */
+               if (IS_XSLT_ELEM_FAST(child)) {
+                   if (xmlStrEqual(child->name, BAD_CAST "with-param")) {
+                       cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;
                        xsltParseAnyXSLTElem(cctxt, child);
-                   } else {
+                   } else if (xmlStrEqual(child->name, BAD_CAST "sort")) {
+                       cctxt->inode->curChildType = XSLT_FUNC_SORT;
+                       xsltParseAnyXSLTElem(cctxt, child);
+                   } else
                        xsltParseContentError(cctxt->style, child);
-                   }
                } else
                    xsltParseContentError(cctxt->style, child);
            }
@@ -3157,7 +3636,7 @@ call_template:
        xmlNodePtr child = elem->children;
        do {
            if (child->type == XML_ELEMENT_NODE) {
-               if (IS_IN_XSLT_NS(child)) {
+               if (IS_XSLT_ELEM_FAST(child)) {
                    xsltStyleType type;
 
                    type = xsltGetXSLTElementTypeByNode(cctxt, child);
@@ -3193,9 +3672,22 @@ text:
 
 empty_content:
     if (elem->children != NULL) {
-       xsltTransformError(NULL, cctxt->style, elem,
-           "This XSLT element must have no content.\n");
-       cctxt->style->errors++;
+       xmlNodePtr child = elem->children;
+       /*
+       * Relaxed behaviour: we will allow whitespace-only text-nodes.
+       */
+       do {
+           if (((child->type != XML_TEXT_NODE) &&
+                (child->type != XML_CDATA_SECTION_NODE)) ||
+               (! IS_BLANK_NODE(child)))
+           {
+               xsltTransformError(NULL, cctxt->style, elem,
+                   "This XSLT element must have no content.\n");
+               cctxt->style->errors++;
+               break;
+           }
+           child = child->next;
+       } while (child != NULL);                
     }
     goto exit;
 
@@ -3212,7 +3704,7 @@ choose:
        int nbWhen = 0, nbOtherwise = 0, err = 0;
        do {
            if (child->type == XML_ELEMENT_NODE) {
-               if (IS_IN_XSLT_NS(child)) {
+               if (IS_XSLT_ELEM_FAST(child)) {
                    xsltStyleType type;
                
                    type = xsltGetXSLTElementTypeByNode(cctxt, child);
@@ -3278,7 +3770,7 @@ for_each:
        */
        do {        
            if ((child->type == XML_ELEMENT_NODE) &&
-               IS_IN_XSLT_NS(child))
+               IS_XSLT_ELEM_FAST(child))
            {           
                if (xsltGetXSLTElementTypeByNode(cctxt, child) ==
                    XSLT_FUNC_SORT)
@@ -3312,21 +3804,72 @@ internal_err:
     return(-1);
 }
 
+static xsltStyleItemUknownPtr
+xsltForwardsCompatUnkownItemCreate(xsltCompilerCtxtPtr cctxt)
+{
+    xsltStyleItemUknownPtr item;
+
+    item = (xsltStyleItemUknownPtr) xmlMalloc(sizeof(xsltStyleItemUknown));
+    if (item == NULL) {
+       xsltTransformError(NULL, cctxt->style, NULL,
+           "Internal error in xsltForwardsCompatUnkownItemCreate(): "
+           "Failed to allocate memory.\n");
+       cctxt->style->errors++;
+       return(NULL);
+    }
+    memset(item, 0, sizeof(xsltStyleItemUknown));
+    item->type = XSLT_FUNC_UNKOWN_FORWARDS_COMPAT;
+    /*
+    * Store it in the stylesheet.
+    */
+    item->next = cctxt->style->preComps;
+    cctxt->style->preComps = (xsltElemPreCompPtr) item;
+    return(item);
+}
+
 static int
-xsltParseForwardsCompatUnexpectedXSLTElem(xsltCompilerCtxtPtr cctxt,
-                                         xmlNodePtr node)
+xsltParseUnknownXSLTElem(xsltCompilerCtxtPtr cctxt,
+                           xmlNodePtr node)
 {
     if ((cctxt == NULL) || (node == NULL))
        return(-1);
 
     /*
-    * Detection of handled content of extension elements.
+    * Detection of handled content of extension instructions.
     */
     if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
        cctxt->inode->extContentHandled = 1;
+    }    
+    if (cctxt->inode->forwardsCompat == 0) {   
+       /*
+       * We are not in forwards-compatible mode, so raise an error.
+       */
+       xsltTransformError(NULL, cctxt->style, node,
+           "Unknown XSLT element '%s'.\n", node->name);
+       cctxt->style->errors++;
+       return(0);
     }
-
-    node->psvi = NULL;
+    /*
+    * Forwards-compatible mode.
+    * ------------------------
+    *    
+    * Parse/compile xsl:fallback elements.
+    *
+    * QUESTION: Do we have to raise an error if there's no xsl:fallback?
+    * ANSWER: No, since in the stylesheet the fallback behaviour might
+    *  also be provided by using the XSLT function "element-available".
+    */
+    if (cctxt->unknownItem == NULL) {
+       /*
+       * Create a singleton for all unknown XSLT instructions.
+       */
+       cctxt->unknownItem = xsltForwardsCompatUnkownItemCreate(cctxt);
+       if (cctxt->unknownItem == NULL) {
+           node->psvi = NULL;
+           return(-1);
+       }
+    }
+    node->psvi = cctxt->unknownItem;
     if (node->children == NULL)
        return(0);
     else {
@@ -3338,13 +3881,13 @@ xsltParseForwardsCompatUnexpectedXSLTElem(xsltCompilerCtxtPtr cctxt,
        */
        if (node->nsDef != NULL)
            cctxt->inode->inScopeNs =
-           xsltCompilerBuildInScopeNsList(cctxt, node);
+               xsltCompilerBuildInScopeNsList(cctxt, node);
        /*
        * Parse all xsl:fallback children.
        */
        do {
            if ((child->type == XML_ELEMENT_NODE) &&
-               IS_IN_XSLT_NS(child) &&
+               IS_XSLT_ELEM_FAST(child) &&
                IS_XSLT_NAME(child, "fallback"))
            {
                cctxt->inode->curChildType = XSLT_FUNC_FALLBACK;
@@ -3352,6 +3895,7 @@ xsltParseForwardsCompatUnexpectedXSLTElem(xsltCompilerCtxtPtr cctxt,
            }
            child = child->next;
        } while (child != NULL);
+       
        xsltCompilerNodePop(cctxt, node);
     }
     return(0);
@@ -3378,7 +3922,7 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
        return;
     }
     /*
-    * Detection of handled content of extension elements.
+    * Detection of handled content of extension instructions.
     */
     if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
        cctxt->inode->extContentHandled = 1;
@@ -3406,7 +3950,7 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
     *  xsl:processing-instruction, xsl:comment, xsl:element
     *  xsl:attribute. 
     * Additional allowed content:
-    * 1) extension elements
+    * 1) extension instructions
     * 2) literal result elements
     * 3) PCDATA
     *
@@ -3426,8 +3970,8 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
            
            if (cur->psvi == xsltXSLTTextMarker) {
                /*
-               * Process xsl:text elements.
-               * ==========================
+               * xsl:text elements
+               * --------------------------------------------------------
                */
                xmlNodePtr tmp;
 
@@ -3507,15 +4051,16 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
                        attr = attr->next;
                    } while (attr != NULL);
                }
-           } else if (IS_IN_XSLT_NS(cur)) { 
+           } else if (IS_XSLT_ELEM_FAST(cur)) {
                /*
                * TODO: Using the XSLT-marker is still not stable yet.
                */
                /* if (cur->psvi == xsltXSLTElemMarker) { */        
                /*
-               * This is element in the XSLT namespace.
-               * =====================================
+               * XSLT instructions
+               * --------------------------------------------------------
                */
+               cur->psvi = NULL;
                type = xsltGetXSLTElementTypeByNode(cctxt, cur);
                switch (type) {
                    case XSLT_FUNC_APPLYIMPORTS:
@@ -3536,8 +4081,7 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
                    case XSLT_FUNC_PI:
                    case XSLT_FUNC_TEXT:
                    case XSLT_FUNC_VALUEOF:
-                   case XSLT_FUNC_VARIABLE:                    
-                       /* cctxt->inode->type = type; */
+                   case XSLT_FUNC_VARIABLE:
                        /*
                        * Parse the XSLT element.
                        */
@@ -3545,33 +4089,25 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
                        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);
-                       }
+                       xsltParseUnknownXSLTElem(cctxt, cur);                   
                        cur = cur->next;
                        continue;
                }
            } else {
                /*
-               * This is a non-XSLT element.
-               * ==========================
+               * Non-XSLT elements
+               * -----------------
+               */
+               xsltCompilerNodePush(cctxt, cur);
+               /*
+               * Update the in-scope namespaces if needed.
                */
-               xsltCompilerNodePush(cctxt, cur);               
+               if (cur->nsDef != NULL)
+                   cctxt->inode->inScopeNs =
+                       xsltCompilerBuildInScopeNsList(cctxt, cur);
                /*
                * The current element is either a literal result element
-               * or an extension element.
+               * or an extension instruction.
                *
                * Process attr "xsl:extension-element-prefixes".
                * FUTURE TODO: IIRC in XSLT 2.0 this attribute must be
@@ -3601,15 +4137,15 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
                        xsltParseExtElemPrefixes(cctxt,
                            cur, cctxt->inode->extElemNs, 0);
                /*
-               * Eval if we have an extension element here.
+               * Eval if we have an extension instruction here.
                */
                if ((cur->ns != NULL) &&
                    (cctxt->inode->extElemNs != NULL) &&
                    (xsltCheckExtPrefix(cctxt->style, cur->ns->href) == 1))
                {
                    /*
-                   * This is an extension element.
-                   * ============================
+                   * Extension instructions
+                   * ----------------------------------------------------
                    * Mark the node information.
                    */
                    cctxt->inode->category = XSLT_ELEMENT_CATEGORY_EXTENSION;
@@ -3620,8 +4156,8 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
                        * TODO: Temporary sanity check.
                        */
                        xsltTransformError(NULL, cctxt->style, cur,
-                           "Internal error: (xsltParseNonXSLTElement) "
-                           " Occupied psvi field.\n");
+                           "Internal error in xsltParseSequenceConstructor(): "
+                           "Occupied PSVI field.\n");
                        cctxt->style->errors++;
                        cur = cur->next;
                        continue;
@@ -3643,7 +4179,7 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
                    /*
                    * 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
+                   *  extension instruction was processed and compiled without
                    *  the need of the extension-author to explicitely call
                    *  such a processing;.We now need to mimic this old
                    *  behaviour in order to avoid breaking old code
@@ -3673,15 +4209,16 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
                    }
                } else {
                    /*
-                   * This is a literal result element.
-                   * ================================
+                   * 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;              
+                   cur->psvi = NULL;
+                   cctxt->inode->category = XSLT_ELEMENT_CATEGORY_LR;
                    if (cur->properties != NULL) {
                        /*
                        * Attribute "xsl:exclude-result-prefixes".
@@ -3695,18 +4232,19 @@ xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
                        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?
+                   * Create/reuse info for the literal result element.
+                   */
+                   if (cctxt->inode->nsChanged)
+                       xsltLREInfoCreate(cctxt, cur);
+                   cur->psvi = cctxt->inode->litResElemInfo;
+                   /*
+                   * Apply ns-aliasing on the element and on its attributes.
+                   */
+                   if (cctxt->hasNsAliases)
+                       xsltLREBuildEffectiveNs(cctxt, cur);
+                   /*
+                   * Compile attribute value templates (AVT).
                    */
-                   if ((cur->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;
                        
@@ -3762,7 +4300,7 @@ xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
        return;
 
     /*
-    * Detection of handled content of extension elements.
+    * Detection of handled content of extension instructions.
     */
     if (XSLT_CCTXT(style)->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
        XSLT_CCTXT(style)->inode->extContentHandled = 1;
@@ -3773,11 +4311,12 @@ xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ) {
        /*
        * 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).
+       * user-defined extension instruction if needed).
        */      
        do {
            if ((child->type == XML_ELEMENT_NODE) &&
-               IS_IN_XSLT_NS(child) && IS_XSLT_NAME(child, "param"))
+               IS_XSLT_ELEM_FAST(child) &&
+               IS_XSLT_NAME(child, "param"))
            {
                XSLT_CCTXT(style)->inode->curChildType = XSLT_FUNC_PARAM;
                xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);
@@ -4136,9 +4675,9 @@ xsltParseXSLTTemplate(xsltCompilerCtxtPtr cctxt, xmlNodePtr templNode) {
     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;
+       xsltPointerListPtr extElemNs = cctxt->inode->extElemNs;
+       xsltPointerListPtr exclResultNs = cctxt->inode->exclResultNs;
+       xsltNsListContainerPtr inScopeNs = cctxt->inode->inScopeNs;
 
        for (i = 0; i < inScopeNs->number; i++) {
            ns = inScopeNs->list[i];
@@ -4150,18 +4689,17 @@ xsltParseXSLTTemplate(xsltCompilerCtxtPtr cctxt, xmlNodePtr templNode) {
            /*
            * 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;
+           if (exclResultNs) {
+               for (j = 0; j < exclResultNs->number; j++)
+                   if (xmlStrEqual(ns->href, BAD_CAST exclResultNs->items[j]))
+                       goto skip_ns;           
            }
            /*
            * Exclude extension-element namespaces.
            */
-           if (extElemList) {
-               for (j = 0; j < extElemList->number; j++)
-                   if (xmlStrEqual(ns->href, BAD_CAST extElemList->items[j]))
+           if (extElemNs) {
+               for (j = 0; j < extElemNs->number; j++)
+                   if (xmlStrEqual(ns->href, BAD_CAST extElemNs->items[j]))
                        goto skip_ns;
            }
            /*
@@ -4283,8 +4821,24 @@ skip_ns:
            curTempl = curTempl->next;
        }
     }
-    if (templNode->children != NULL)   
-       xsltParseTemplateContent(cctxt->style, templNode);
+    if (templNode->children != NULL) {
+       xsltParseTemplateContent(cctxt->style, templNode);      
+       /*
+       * MAYBE TODO: Custom behaviour: In order to stay compatible with
+       * Xalan and MSXML(.NET), we could allow whitespace
+       * to appear before an xml:param element; this whitespace
+       * will additionally become part of the "template".
+       * NOTE that this is totally deviates from the spec, but
+       * is the de facto behaviour of Xalan and MSXML(.NET).
+       * Personally I wouldn't allow this, since if we have:
+       * <xsl:template ...xml:space="preserve">
+       *   <xsl:param name="foo"/>
+       *   <xsl:param name="bar"/>
+       *   <xsl:param name="zoo"/>
+       * ... the whitespace between every xsl:param would be
+       * added to the result tree.
+       */              
+    }    
     
     templ->elem = templNode;
     templ->content = templNode->children;
@@ -4564,6 +5118,7 @@ exit:
     return(ret);
 }
 
+#if 0
 static int
 xsltParseRemoveWhitespace(xmlNodePtr node)
 {
@@ -4592,103 +5147,7 @@ xsltParseRemoveWhitespace(xmlNodePtr node)
     }
     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);
-}
+#endif
 
 static int
 xsltParseXSLTStylesheetElemCore(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
@@ -4709,7 +5168,7 @@ xsltParseXSLTStylesheetElemCore(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
     * 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"))
+    if (IS_XSLT_ELEM_FAST(node) && IS_XSLT_NAME(node, "include"))
     {
        xsltDocumentPtr include;
        /*
@@ -4740,9 +5199,14 @@ xsltParseXSLTStylesheetElemCore(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
        return(0);
     /*
     * Push the xsl:stylesheet/xsl:transform element.
-    */
+    */  
     xsltCompilerNodePush(cctxt, node);
     cctxt->inode->isRoot = 1;
+    cctxt->inode->nsChanged = 0;
+    /*
+    * Start with the dummy info for literal result elements.
+    */
+    cctxt->inode->litResElemInfo = cctxt->inodeList->litResElemInfo;
 
     /*
     * In every case, we need to have
@@ -4775,11 +5239,11 @@ xsltParseXSLTStylesheetElemCore(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
 #ifdef XSLT_REFACTORED_MANDATORY_VERSION
        if (isXsltElem)
            xsltTransformError(NULL, cctxt->style, node,
-           "The attribute 'version' is missing.\n");
+               "The attribute 'version' is missing.\n");
        cctxt->style->errors++; 
 #else
        /* OLD behaviour. */
-xsltTransformError(NULL, cctxt->style, node,
+       xsltTransformError(NULL, cctxt->style, node,
            "xsl:version is missing: document may not be a stylesheet\n");
        cctxt->style->warnings++;
 #endif
@@ -4800,7 +5264,11 @@ xsltTransformError(NULL, cctxt->style, node,
     */
     cctxt->inode->exclResultNs =
        xsltParseExclResultPrefixes(cctxt, node, NULL, 1);
-
+    /*
+    * Create/reuse info for the literal result element.
+    */
+    if (cctxt->inode->nsChanged)
+       xsltLREInfoCreate(cctxt, NULL);
     /*
     * Processed top-level elements:
     * ----------------------------
@@ -4868,22 +5336,7 @@ xsltTransformError(NULL, cctxt->style, node,
     {
        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.
     */
@@ -4900,15 +5353,10 @@ xsltTransformError(NULL, cctxt->style, node,
                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)) {
+           if (IS_XSLT_ELEM_FAST(cur)) {
                /*
                * xsl:import is only allowed at the beginning.
                */
@@ -4966,7 +5414,7 @@ xsltTransformError(NULL, cctxt->style, node,
                    xsltParseTopLevelXSLTElem(cctxt, cur,
                        XSLT_FUNC_ATTRSET);             
                } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
-                   xsltNamespaceAlias(style, cur);
+                   /* NOP; done already */                 
                } else {
                    if (cctxt->inode->forwardsCompat) {
                        /*
@@ -5022,10 +5470,6 @@ exit:
                    "parsed %d templates\n", templates);
 #endif
     return(0);
-
-internal_err:
-    xsltCompilerNodePop(cctxt, node);
-    return(-1);
 }
 
 /**
@@ -5053,7 +5497,7 @@ internal_err:
 static int
 xsltParseXSLTStylesheetElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
 {
-    xmlNodePtr cur;
+    xmlNodePtr cur, start;
 
     if ((cctxt == NULL) || (node == NULL))
        return(-1);
@@ -5083,9 +5527,11 @@ xsltParseXSLTStylesheetElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
     }
     if (cur == NULL)
        goto exit;
+    start = cur;
     /*
     * Pre-process all xsl:include elements.
     */
+    cur = start;
     while ((cur != NULL) &&
        xsltParseFindTopLevelElem(cctxt, cur,
            BAD_CAST "include", XSLT_NAMESPACE, 0, &cur) == 1)
@@ -5093,6 +5539,17 @@ xsltParseXSLTStylesheetElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
        xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_INCLUDE);
        cur = cur->next;
     }
+    /*
+    * Pre-process all xsl:namespace-alias elements.
+    */
+    cur = start;
+    while ((cur != NULL) &&
+       xsltParseFindTopLevelElem(cctxt, cur,
+           BAD_CAST "namespace-alias", XSLT_NAMESPACE, 0, &cur) == 1)
+    {
+       xsltNamespaceAlias(cctxt->style, cur);
+       cur = cur->next;
+    }
 
     if (cctxt->isInclude) {
        /*
@@ -5341,6 +5798,7 @@ xsltParseSimplifiedStylesheetTree(xsltCompilerCtxtPtr cctxt,
     return(0);
 }
 
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
 int
 xsltRestoreDocumentNamespaces(xsltNsMapPtr ns, xmlDocPtr doc)
 {
@@ -5360,6 +5818,7 @@ xsltRestoreDocumentNamespaces(xsltNsMapPtr ns, xmlDocPtr doc)
     }
     return(0);
 }
+#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
 
 /**
  * xsltParseStylesheetProcess:
@@ -5595,16 +6054,20 @@ xsltParseStylesheetImportedDoc(xmlDocPtr doc,
            }
            retStyle->principalData = principalData;
            /*
-           * Create the compilation context (only once; for the
-           * principal stylesheet).
+           * 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) {
+           */
+           cctxt = xsltCompilationCtxtCreate(retStyle);
+           if (cctxt == NULL) {
                xsltFreeStylesheet(retStyle);
                return(NULL);
-           }
-           cctxt = XSLT_CCTXT(retStyle);
+           }               
+           retStyle->compCtxt = (void *) cctxt;
+           cctxt->style = retStyle;
+           cctxt->dict = retStyle->dict;
            cctxt->psData = principalData;
            /*
            * Push initial dummy node info.
@@ -5648,11 +6111,13 @@ xsltParseStylesheetImportedDoc(xmlDocPtr doc,
        */
        if (retStyle != NULL) {
            if (retStyle->errors != 0) {
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
                /*
                * Restore all changes made to namespace URIs of ns-decls.
                */
                if (cctxt->psData->nsMap)               
                    xsltRestoreDocumentNamespaces(cctxt->psData->nsMap, doc);
+#endif
                /*
                * Detach the doc from the stylesheet; otherwise the doc
                * will be freed in xsltFreeStylesheet().
@@ -5718,7 +6183,7 @@ xsltParseStylesheetDoc(xmlDocPtr doc) {
     if (ret->compCtxt != NULL) {
        /* TEST TODO: REMOVE test output*/
        /* printf("MAX NODE INFO: %d\n", XSLT_CCTXT(ret)->maxNodeInfos); */ 
-       xsltCompilerCtxtFree(XSLT_CCTXT(ret));
+       xsltCompilationCtxtFree(XSLT_CCTXT(ret));
        ret->compCtxt = NULL;
     }
 #endif
index 7fb8940..a43c69b 100644 (file)
 extern "C" {
 #endif
 
+#define XSLT_IS_TEXT_NODE(n) (((n) != NULL) && \
+    (((n)->type == XML_TEXT_NODE) || \
+     ((n)->type == XML_CDATA_SECTION_NODE)))
+
 /**
  * XSLT_REFACTORED:
  *
- * Internal define to enable the refactored parts of Libxslt
- * mostly related to pre-computation.
+ * Internal define to enable the refactored parts of Libxslt.
  */
 /* #define XSLT_REFACTORED */
 
 #ifdef XSLT_REFACTORED
 
-extern const xmlChar *xsltConstNamespaceNameXSLT;
+/* TODO: REMOVE: #define XSLT_REFACTORED_EXCLRESNS */
+
+/* TODO: REMOVE: #define XSLT_REFACTORED_NSALIAS */
 
 /**
- * IS_XSLT_ELEM_FAST:
+ * XSLT_REFACTORED_XSLT_NSCOMP
  *
- * Checks that the element pertains to XSLT namespace.
+ * Internal define to enable the pointer-comparison of
+ * namespaces of XSLT elements. 
  */
-#define IS_XSLT_ELEM_FAST(e) \
-    (((e) != NULL) && ((e)->type == XML_ELEMENT_NODE) && \
-     ((e)->ns != NULL) && ((e)->ns->href == xsltConstNamespaceNameXSLT))
+#define XSLT_REFACTORED_XSLT_NSCOMP
 
-#define IS_IN_XSLT_NS(e) \
-    (((e)->ns != NULL) && ((e)->ns->href == xsltConstNamespaceNameXSLT))
+/**
+ * XSLT_REFACTORED_XPATHCOMP
+ *
+ * Internal define to enable the optimization of the
+ * compilation of XPath expressions.
+ */
+#define XSLT_REFACTORED_XPATHCOMP
+
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
+
+extern const xmlChar *xsltConstNamespaceNameXSLT;
+
+#define IS_XSLT_ELEM_FAST(n) \
+    (((n) != NULL) && ((n)->ns != NULL) && \
+    ((n)->ns->href == xsltConstNamespaceNameXSLT))
 
 #define XSLT_HAS_INTERNAL_NSMAP(s) \
     (((s) != NULL) && ((s)->principal) && \
@@ -57,6 +74,16 @@ extern const xmlChar *xsltConstNamespaceNameXSLT;
 
 #define XSLT_GET_INTERNAL_NSMAP(s) ((s)->principal->principalData->nsMap)
 
+#else /* XSLT_REFACTORED_XSLT_NSCOMP */
+
+#define IS_XSLT_ELEM_FAST(n) \
+    (((n) != NULL) && ((n)->ns != NULL) && \
+     (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE)))
+
+
+#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
+
+
 /**
  * XSLT_REFACTORED_MANDATORY_VERSION:
  *
@@ -288,7 +315,9 @@ typedef enum {
     XSLT_FUNC_FALLBACK,
     XSLT_FUNC_MESSAGE,
     XSLT_FUNC_INCLUDE,
-    XSLT_FUNC_ATTRSET
+    XSLT_FUNC_ATTRSET,
+    XSLT_FUNC_LITERAL_RESULT_ELEMENT,
+    XSLT_FUNC_UNKOWN_FORWARDS_COMPAT,
 #endif
 } xsltStyleType;
 
@@ -354,9 +383,9 @@ XSLTPUBFUN int XSLTCALL
  *                                                                     *
  ************************************************************************/
 
-typedef struct _xsltNsList xsltNsList;
-typedef xsltNsList *xsltNsListPtr;
-struct _xsltNsList {
+typedef struct _xsltNsListContainer xsltNsListContainer;
+typedef xsltNsListContainer *xsltNsListContainerPtr;
+struct _xsltNsListContainer {
     xmlNsPtr *list;
     int number;
 };
@@ -392,7 +421,7 @@ struct _xsltNsList {
  *
  * The in-scope namespaces.
  */
-#define XSLT_ITEM_NSINSCOPE_FIELDS xsltNsListPtr inScopeNs;
+#define XSLT_ITEM_NSINSCOPE_FIELDS xsltNsListContainerPtr inScopeNs;
 
 /**
  * XSLT_ITEM_COMMON_FIELDS:
@@ -425,7 +454,7 @@ struct _xsltStylePreComp {
     xmlNodePtr inst;           /* the node in the stylesheet's tree
                                   corresponding to this item. */
     /* Currently no navigational fields. */
-    xsltNsListPtr inScopeNs;
+    xsltNsListContainerPtr inScopeNs;
 };
 
 /**
@@ -924,6 +953,19 @@ struct _xsltStyleItemInclude {
 
 /************************************************************************
  *                                                                     *
+ *  XSLT elements in forwards-compatible mode                           *
+ *                                                                     *
+ ************************************************************************/
+
+typedef struct _xsltStyleItemUknown xsltStyleItemUknown;
+typedef xsltStyleItemUknown *xsltStyleItemUknownPtr;
+struct _xsltStyleItemUknown {
+    XSLT_ITEM_COMMON_FIELDS
+};
+
+
+/************************************************************************
+ *                                                                     *
  *  Extension elements                                                  *
  *                                                                     *
  ************************************************************************/
@@ -961,15 +1003,50 @@ struct _xsltStyleItemExtElement {
  *                                                                     *
  ************************************************************************/
 
+typedef struct _xsltEffectiveNs xsltEffectiveNs;
+typedef xsltEffectiveNs *xsltEffectiveNsPtr;
+struct _xsltEffectiveNs {
+    xsltEffectiveNsPtr next; /* next item in the list */
+    const xmlChar *prefix;
+    const xmlChar *nsName;
+};
+
 /*
- * Literal result elements.
- */
-typedef struct _xsltStyleItemLRElement xsltStyleItemLRElement;
-typedef xsltStyleItemLRElement *xsltStyleItemLRElementPtr;
-struct _xsltStyleItemLRElement {
+ * Info for literal result elements.
+ * This will be set on the elem->psvi field and will be
+ * shared by literal result elements, which have the same
+ * excluded result namespaces; i.e., this *won't* be created uniquely
+ * for every literal result element.
+ */
+typedef struct _xsltStyleItemLRElementInfo xsltStyleItemLRElementInfo;
+typedef xsltStyleItemLRElementInfo *xsltStyleItemLRElementInfoPtr;
+struct _xsltStyleItemLRElementInfo {
     XSLT_ITEM_COMMON_FIELDS
-    xsltPointerListPtr exclResultNs;
+    /*
+    * @effectiveNs is the set of effective ns-nodes
+    *  on the literal result element, which will be added to the result
+    *  element if not already existing in the result tree.
+    *  This means that excluded namespaces (via exclude-result-prefixes,
+    *  extension-element-prefixes and the XSLT namespace) not added
+    *  to the set.
+    *  Namespace-aliasing was applied on the @effectiveNs.
+    */
+    xsltEffectiveNsPtr effectiveNs;
+};
+
+#ifdef XSLT_REFACTORED
+
+typedef struct _xsltNsAlias xsltNsAlias;
+typedef xsltNsAlias *xsltNsAliasPtr;
+struct _xsltNsAlias {
+    xsltNsAliasPtr next; /* next in the list */    
+    xmlNsPtr literalNs;
+    xmlNsPtr targetNs;
+    xmlDocPtr docOfTargetNs;
 };
+#endif
+
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
 
 typedef struct _xsltNsMap xsltNsMap;
 typedef xsltNsMap *xsltNsMapPtr;
@@ -981,6 +1058,7 @@ struct _xsltNsMap {
     const xmlChar *origNsName; /* the original XML namespace name */
     const xmlChar *newNsName; /* the mapped XML namespace name */    
 };
+#endif
 
 /************************************************************************
  *                                                                     *
@@ -991,6 +1069,13 @@ struct _xsltNsMap {
 typedef struct _xsltPrincipalStylesheetData xsltPrincipalStylesheetData;
 typedef xsltPrincipalStylesheetData *xsltPrincipalStylesheetDataPtr;
 
+typedef struct _xsltNsList xsltNsList;
+typedef xsltNsList *xsltNsListPtr;
+struct _xsltNsList {
+    xsltNsListPtr next; /* next in the list */
+    xmlNsPtr ns;
+};
+
 #define XSLT_ELEMENT_CATEGORY_XSLT 0
 #define XSLT_ELEMENT_CATEGORY_EXTENSION 1
 #define XSLT_ELEMENT_CATEGORY_LR 2
@@ -1012,11 +1097,22 @@ struct _xsltCompilerNodeInfo {
                                 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 */
+    /* The current in-scope namespaces */
+    xsltNsListContainerPtr inScopeNs;
+    /* The current excluded result namespaces */
+    xsltPointerListPtr exclResultNs; 
+    /* The current extension instruction namespaces */
     xsltPointerListPtr extElemNs;
+    /* The current info for literal result elements. */
+    xsltStyleItemLRElementInfoPtr litResElemInfo;
+    /* 
+    * Set to 1 if in-scope namespaces changed,
+    *  or excluded result namespaces changed,
+    *  or extension element namespaces changed.
+    * This will trigger creation of new infos
+    *  for literal result elements.
+    */
+    int nsChanged;
     int preserveWhitespace;
     int stripWhitespace;
     int isRoot; /* whether this is the stylesheet's root node */
@@ -1024,7 +1120,7 @@ struct _xsltCompilerNodeInfo {
     /* whether the content of an extension element was processed */
     int extContentHandled;
     /* the type of the current child */
-    xsltStyleType curChildType;
+    xsltStyleType curChildType;    
 };
 
 #define XSLT_CCTXT(style) ((xsltCompilerCtxtPtr) style->compCtxt) 
@@ -1068,7 +1164,13 @@ struct _xsltCompilerCtxt {
     * mechanisms like whitespace-stripping in the stylesheet.
     */
     int strict;
-    xsltPrincipalStylesheetDataPtr psData;    
+    xsltPrincipalStylesheetDataPtr psData;
+#ifdef XSLT_REFACTORED_XPATHCOMP
+    xmlXPathContextPtr xpathCtxt;
+#endif
+    xsltStyleItemUknownPtr unknownItem;
+    int hasNsAliases; /* Indicator if there was an xsl:namespace-alias. */
+    xsltNsAliasPtr nsAliases;
 };   
 
 #else /* XSLT_REFACTORED */
@@ -1164,19 +1266,21 @@ struct _xsltPrincipalStylesheetData {
     /*
     * Global list of in-scope namespaces.
     */
-    void *inScopeNamespaces;
+    xsltPointerListPtr inScopeNamespaces;
     /*
     * Global list of information for [xsl:]excluded-result-prefixes.
     */
-    void *exclResultNamespaces;
+    xsltPointerListPtr exclResultNamespaces;
     /*
     * Global list of information for [xsl:]extension-element-prefixes.
     */
-    void *extElemNamespaces;
+    xsltPointerListPtr extElemNamespaces;
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
     /*
     * Namespace name map to get rid of string comparison of namespace names.
     */
     xsltNsMapPtr nsMap;
+#endif
 };
 
     
@@ -1227,6 +1331,7 @@ struct _xsltStylesheet {
     
     /*
      * Namespace aliases.
+     * NOTE: Not used in the refactored code.
      */
     xmlHashTablePtr nsAliases; /* the namespace alias hash tables */
 
@@ -1237,6 +1342,7 @@ struct _xsltStylesheet {
 
     /*
      * Namespaces.
+     * TODO: Eliminate this.
      */
     xmlHashTablePtr nsHash;     /* the set of namespaces in use:
                                    ATTENTION: This is used for
@@ -1309,6 +1415,7 @@ struct _xsltStylesheet {
     void *attVTs;
     /*
      * if namespace-alias has an alias for the default stylesheet prefix
+     * NOTE: Not used in the refactored code.
      */
     const xmlChar *defaultAlias;
     /*
@@ -1600,10 +1707,12 @@ XSLTPUBFUN void XSLTCALL
 XSLTPUBFUN int XSLTCALL
                        xsltParseAnyXSLTElem    (xsltCompilerCtxtPtr cctxt,
                                                 xmlNodePtr elem);
+#ifdef XSLT_REFACTORED_XSLT_NSCOMP
 XSLTPUBFUN int XSLTCALL
                        xsltRestoreDocumentNamespaces(
                                                 xsltNsMapPtr ns,
                                                 xmlDocPtr doc);
+#endif
 #endif /* XSLT_REFACTORED */
 
 #ifdef __cplusplus
index 723962f..d9b094e 100644 (file)
@@ -2063,22 +2063,50 @@ xsltGetProfileInformation(xsltTransformContextPtr ctxt)
  */
 xmlXPathCompExprPtr
 xsltXPathCompile(xsltStylesheetPtr style, const xmlChar *str) {
-    xmlXPathContextPtr xctxt;
+    xmlXPathContextPtr xpathCtxt;
     xmlXPathCompExprPtr ret;
 
-    if (style != NULL)
-       xctxt = xmlXPathNewContext(style->doc);
-    else
-       xctxt = xmlXPathNewContext(NULL);
-    if (style != NULL)
-       xctxt->dict = style->dict;
-    ret = xmlXPathCtxtCompile(xctxt, str);
-    xmlXPathFreeContext(xctxt);
+    if (style != NULL) {
+#ifdef XSLT_REFACTORED_XPATHCOMP
+       if (XSLT_CCTXT(style)) {
+           /*
+           * Proposed by Jerome Pesenti
+           * --------------------------
+           * For better efficiency we'll reuse the compilation
+           * context's XPath context. For the common stylesheet using
+           * XPath expressions this will reduce compilation time to
+           * about 50%.
+           *
+           * See http://mail.gnome.org/archives/xslt/2006-April/msg00037.html
+           */
+           xpathCtxt = XSLT_CCTXT(style)->xpathCtxt;
+           xpathCtxt->doc = style->doc;
+       } else
+           xpathCtxt = xmlXPathNewContext(style->doc); 
+#else
+       xpathCtxt = xmlXPathNewContext(style->doc);
+#endif
+       xpathCtxt->dict = style->dict;
+    } else {
+       xpathCtxt = xmlXPathNewContext(NULL);
+    }
+    /*
+    * Compile the expression.
+    */
+    ret = xmlXPathCtxtCompile(xpathCtxt, str);
+
+#ifdef XSLT_REFACTORED_XPATHCOMP
+    if ((style == NULL) || (! XSLT_CCTXT(style))) {
+       xmlXPathFreeContext(xpathCtxt);
+    }
+#else
+    xmlXPathFreeContext(xpathCtxt);
+#endif
     /*
      * TODO: there is a lot of optimizations which should be possible
      *       like variable slot precomputations, function precomputations, etc.
      */
-     
+
     return(ret);
 }