documents.[hc] : added new procedure xsltFindDocument, needed when
authorWilliam M. Brack <wbrack@src.gnome.org>
Sun, 10 Jun 2001 06:30:59 +0000 (06:30 +0000)
committerWilliam M. Brack <wbrack@src.gnome.org>
Sun, 10 Jun 2001 06:30:59 +0000 (06:30 +0000)
documents.[hc] : added new procedure xsltFindDocument, needed when document changed within xsltApplyTemplates and xsltForEach
keys.c : saved and restored ctxt->document within xsltInitKey
transform.c : fixed several problems with document() within xsltApplyTemplates and xsltForEach.  Also cleaned up misc. messages

libxslt/documents.c
libxslt/documents.h
libxslt/keys.c
libxslt/transform.c

index 40108e0..f06e4bc 100644 (file)
@@ -198,3 +198,31 @@ xsltLoadStyleDocument(xsltStylesheetPtr style, const xmlChar *URI) {
     return(ret);
 }
 
+/**
+ * xsltFindDocument:
+ * @ctxt: an XSLT transformation context
+ * @@doc: a parsed XML document
+ *
+ * Try to find a document within the XSLT transformation context
+ *
+ * Returns the desired xsltDocumentPtr or NULL in case of error
+ */
+xsltDocumentPtr
+xsltFindDocument (xsltTransformContextPtr ctxt, xmlDocPtr doc) {
+    xsltDocumentPtr ret;
+
+    if ((ctxt == NULL) || (doc == NULL))
+       return(NULL);
+
+    /*
+     * Walk the context list to find the document
+     */
+    ret = ctxt->docList;
+    while (ret != NULL) {
+       if (ret->doc == doc)
+           return(ret);
+       ret = ret->next;
+    }
+    return(NULL);
+}
+
index d4c3ff4..0f371fa 100644 (file)
@@ -20,6 +20,8 @@ xsltDocumentPtr       xsltNewDocument         (xsltTransformContextPtr ctxt,
                                         xmlDocPtr doc);
 xsltDocumentPtr        xsltLoadDocument        (xsltTransformContextPtr ctxt,
                                         const xmlChar *URI);
+xsltDocumentPtr        xsltFindDocument        (xsltTransformContextPtr ctxt,
+                                        xmlDocPtr doc);
 void           xsltFreeDocuments       (xsltTransformContextPtr ctxt);
 
 xsltDocumentPtr        xsltLoadStyleDocument   (xsltStylesheetPtr style,
@@ -27,6 +29,7 @@ xsltDocumentPtr       xsltLoadStyleDocument   (xsltStylesheetPtr style,
 xsltDocumentPtr        xsltNewStyleDocument    (xsltStylesheetPtr style,
                                         xmlDocPtr doc);
 void           xsltFreeStyleDocuments  (xsltStylesheetPtr style);
+
 #ifdef __cplusplus
 }
 #endif
index 415cd5d..23082b3 100644 (file)
@@ -299,7 +299,6 @@ xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name,
     xsltGenericDebug(xsltGenericDebugContext,
        "Get key %s, value %s\n", name, value);
 #endif
-
     table = (xsltKeyTablePtr) ctxt->document->keys;
     while (table != NULL) {
        if (xmlStrEqual(table->name, name) &&
@@ -332,6 +331,8 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc,
     xsltKeyTablePtr table;
     int        oldPos, oldSize;
     xmlNodePtr oldInst;
+    xsltDocumentPtr oldDoc;
+    xmlDocPtr oldXDoc;
 
     /*
      * Evaluate the nodelist
@@ -345,8 +346,11 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc,
     oldPos = ctxt->xpathCtxt->proximityPosition;
     oldSize = ctxt->xpathCtxt->contextSize;
     oldInst = ctxt->inst;
+    oldDoc = ctxt->document;
+    oldXDoc= ctxt->xpathCtxt->doc;
 
     ctxt->document = doc;
+    ctxt->xpathCtxt->doc = doc->doc;
     ctxt->xpathCtxt->node = (xmlNodePtr) doc->doc;
     ctxt->node = (xmlNodePtr) doc->doc;
     /* TODO : clarify the use of namespaces in keys evaluation */
@@ -357,6 +361,7 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc,
     ctxt->xpathCtxt->contextSize = oldSize;
     ctxt->xpathCtxt->proximityPosition = oldPos;
     ctxt->inst = oldInst;
+
     if (res != NULL) {
        if (res->type == XPATH_NODESET) {
            nodelist = res->nodesetval;
@@ -422,6 +427,8 @@ xsltInitCtxtKey(xsltTransformContextPtr ctxt, xsltDocumentPtr doc,
     doc->keys = table;
 
 error:
+    ctxt->document = oldDoc;
+    ctxt->xpathCtxt->doc = oldXDoc;
     if (res != NULL)
        xmlXPathFreeObject(res);
 }
index 8ccf420..fe4195d 100644 (file)
@@ -733,11 +733,11 @@ xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
 #ifdef WITH_XSLT_DEBUG_PROCESS
                    if (cur->type == XML_PI_NODE)
                        xsltGenericDebug(xsltGenericDebugContext,
-                        "xsltProcessOneNode: template found for PI %s\n",
+                        "xsltDefaultProcessOneNode: template found for PI %s\n",
                                         cur->name);
                    else if (cur->type == XML_COMMENT_NODE)
                        xsltGenericDebug(xsltGenericDebugContext,
-                        "xsltProcessOneNode: template found for comment\n");
+                        "xsltDefaultProcessOneNode: template found for comment\n");
 #endif
                    oldNode = ctxt->node;
                    ctxt->node = cur;
@@ -785,7 +785,7 @@ xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node) {
            if (delete != NULL) {
 #ifdef WITH_XSLT_DEBUG_PROCESS
                xsltGenericDebug(xsltGenericDebugContext,
-            "xsltDefaultProcessOneNode: removing ignorable blank node\n");
+            "xsltProcessOneNode: removing ignorable blank node\n");
 #endif
                xmlUnlinkNode(delete);
                xmlFreeNode(delete);
@@ -1125,7 +1125,7 @@ xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node,
        URL = xmlBuildURI(filename, base);
        if (URL == NULL) {
            xsltGenericError(xsltGenericErrorContext,
-               "xsltDocumentComp: URL computation failed %s\n", filename);
+               "xsltDocumentElem: URL computation failed %s\n", filename);
        } else {
            xmlFree(filename);
            filename = URL;
@@ -1208,7 +1208,7 @@ void xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node);
  * @inst:  the xslt sort node
  * @comp:  precomputed informations
  *
- * function attached to xslt:sort nodes, but this should not be
+ * function attached to xsl:sort nodes, but this should not be
  * called directly
  */
 void
@@ -1217,11 +1217,11 @@ xsltSort(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED,
        xsltStylePreCompPtr comp) {
     if (comp == NULL) {
        xsltGenericError(xsltGenericErrorContext,
-            "xslt:sort : compilation had failed\n");
+            "xsl:sort : compilation failed\n");
        return;
     }
     xsltGenericError(xsltGenericErrorContext,
-        "xslt:sort : improper use this should not be reached\n");
+        "xsl:sort : improper use this should not be reached\n");
 }
 
 /**
@@ -1367,7 +1367,7 @@ xsltText(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED,
                 (text->type != XML_CDATA_SECTION_NODE)) ||
                (text->next != NULL)) {
                xsltGenericError(xsltGenericErrorContext,
-                                "xslt:text content problem\n");
+                                "xsl:text content problem\n");
                break;
            }
            copy = xmlNewDocText(ctxt->output, text->content);
@@ -1421,7 +1421,7 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
                      (const xmlChar *)"name", XSLT_NAMESPACE);
        if (prop == NULL) {
            xsltGenericError(xsltGenericErrorContext,
-                "xslt:element : name is missing\n");
+                "xsl:element : name is missing\n");
            goto error;
        }
        name = prop;
@@ -1447,14 +1447,14 @@ xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node,
                if (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)) {
 #ifdef WITH_XSLT_DEBUG_PARSING
                    xsltGenericDebug(xsltGenericDebugContext,
-                        "xslt:element : xml prefix forbidden\n");
+                        "xsl:element : xml prefix forbidden\n");
 #endif
                    goto error;
                }
                ns = xmlSearchNs(inst->doc, inst, prefix);
                if (ns == NULL) {
                    xsltGenericError(xsltGenericErrorContext,
-                       "no namespace bound to prefix %s\n", prefix);
+                       "xsl:element : no namespace bound to prefix %s\n", prefix);
                } else {
                    ns = xsltGetNamespace(ctxt, inst, ns, ctxt->insert);
                }
@@ -1527,7 +1527,7 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
        return;
     if (comp == NULL) {
        xsltGenericError(xsltGenericErrorContext,
-            "xslt:attribute : compilation had failed\n");
+            "xsl:attribute : compilation failed\n");
        return;
     }
 
@@ -1538,7 +1538,7 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
     }
     if (ctxt->insert->children != NULL) {
        xsltGenericError(xsltGenericErrorContext,
-            "xslt:attribute : node has already children\n");
+            "xsl:attribute : node has already children\n");
        return;
     }
     if (comp->name == NULL) {
@@ -1546,7 +1546,7 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
                                         XSLT_NAMESPACE);
        if (prop == NULL) {
            xsltGenericError(xsltGenericErrorContext,
-                "xslt:element : name is missing\n");
+                "xsl:attribute : name is missing\n");
            goto error;
        }
        name = prop;
@@ -1563,7 +1563,7 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
     if (!xmlStrncasecmp(prefix, (xmlChar *)"xml", 3)) {
 #ifdef WITH_XSLT_DEBUG_PARSING
        xsltGenericDebug(xsltGenericDebugContext,
-            "xslt:attribute : xml prefix forbidden\n");
+            "xsl:attribute : xml prefix forbidden\n");
 #endif
        goto error;
     }
@@ -1579,7 +1579,7 @@ xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr node,
                ns = xmlSearchNs(inst->doc, inst, prefix);
                if (ns == NULL) {
                    xsltGenericError(xsltGenericErrorContext,
-                       "no namespace bound to prefix %s\n", prefix);
+                       "xsl:attribute : no namespace bound to prefix %s\n", prefix);
                } else {
                    ns = xsltGetNamespace(ctxt, inst, ns, ctxt->insert);
                }
@@ -1677,7 +1677,7 @@ xsltProcessingInstruction(xsltTransformContextPtr ctxt, xmlNodePtr node,
                            (const xmlChar *)"name", XSLT_NAMESPACE);
        if (ncname == NULL) {
            xsltGenericError(xsltGenericErrorContext,
-                "xslt:processing-instruction : name is missing\n");
+                "xsl:processing-instruction : name is missing\n");
            goto error;
        }
        name = ncname;
@@ -1730,7 +1730,7 @@ xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
        return;
     if ((comp == NULL) || (comp->select == NULL) || (comp->comp == NULL)) {
        xsltGenericError(xsltGenericErrorContext,
-            "xsl:copy-of : compilation have failed\n");
+            "xsl:copy-of : compilation failed\n");
        return;
     }
 
@@ -1751,7 +1751,7 @@ xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
        if (res->type == XPATH_NODESET) {
 #ifdef WITH_XSLT_DEBUG_PROCESS
            xsltGenericDebug(xsltGenericDebugContext,
-                "xslcopyOf: result is a node set\n");
+                "xsltCopyOf: result is a node set\n");
 #endif
            list = res->nodesetval;
            if (list != NULL) {
@@ -1776,7 +1776,7 @@ xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
        } else if (res->type == XPATH_XSLT_TREE) {
 #ifdef WITH_XSLT_DEBUG_PROCESS
            xsltGenericDebug(xsltGenericDebugContext,
-                "xslcopyOf: result is a result tree fragment\n");
+                "xsltCopyOf: result is a result tree fragment\n");
 #endif
            list = res->nodesetval;
            if ((list != NULL) && (list->nodeTab != NULL) &&
@@ -1801,7 +1801,7 @@ xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
 #ifdef WITH_XSLT_DEBUG_PROCESS
            else
                xsltGenericDebug(xsltGenericDebugContext,
-                    "xslcopyOf: result %s\n", res->stringval);
+                    "xsltCopyOf: result %s\n", res->stringval);
 #endif
        }
     }
@@ -1830,7 +1830,7 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
        return;
     if ((comp == NULL) || (comp->select == NULL) || (comp->comp == NULL)) {
        xsltGenericError(xsltGenericErrorContext,
-            "xsl:value-of : compilation have failed\n");
+            "xsl:value-of : compilation failed\n");
        return;
     }
 
@@ -1861,7 +1861,7 @@ xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node,
     }
     if (copy == NULL) {
        xsltGenericError(xsltGenericErrorContext,
-           "xsltDefaultProcessOneNode: text copy failed\n");
+           "xsltValueOf: text copy failed\n");
     }
 #ifdef WITH_XSLT_DEBUG_PROCESS
     else
@@ -1887,7 +1887,7 @@ xsltNumber(xsltTransformContextPtr ctxt, xmlNodePtr node,
 {
     if (comp == NULL) {
        xsltGenericError(xsltGenericErrorContext,
-            "xslt:number : compilation had failed\n");
+            "xsl:number : compilation failed\n");
        return;
     }
 
@@ -1916,7 +1916,7 @@ xsltApplyImports(xsltTransformContextPtr ctxt, xmlNodePtr node,
 
     if ((ctxt->templ == NULL) || (ctxt->templ->style == NULL)) {
        xsltGenericError(xsltGenericErrorContext,
-            "xslt:apply-imports : internal error no current template\n");
+            "xsl:apply-imports : internal error no current template\n");
        return;
     }
     template = xsltGetTemplate(ctxt, node, ctxt->templ->style);
@@ -1949,7 +1949,7 @@ xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
        return;
     if (comp == NULL) {
        xsltGenericError(xsltGenericErrorContext,
-            "xslt:call-template : compilation had failed\n");
+            "xsl:call-template : compilation failed\n");
        return;
     }
 
@@ -1960,7 +1960,7 @@ xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
        comp->templ = xsltFindTemplate(ctxt, comp->name, comp->ns);
        if (comp->templ == NULL) {
            xsltGenericError(xsltGenericErrorContext,
-                "xslt:call-template : template %s not found\n", comp->name);
+                "xsl:call-template : template %s not found\n", comp->name);
            return;
        }
     }
@@ -1981,11 +1981,11 @@ xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
                }
            } else {
                xsltGenericError(xsltGenericDebugContext,
-                    "xslt:call-template: misplaced xslt:%s\n", cur->name);
+                    "xsl:call-template: misplaced xsl:%s\n", cur->name);
            }
        } else {
            xsltGenericError(xsltGenericDebugContext,
-                "xslt:call-template: misplaced %s element\n", cur->name);
+                "xsl:call-template: misplaced %s element\n", cur->name);
        }
        cur = cur->next;
     }
@@ -2007,19 +2007,21 @@ xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
 void
 xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
                   xmlNodePtr inst, xsltStylePreCompPtr comp) {
-    xmlNodePtr cur, delete = NULL, oldnode;
+    xmlNodePtr cur, delete = NULL, oldNode;
     xmlXPathObjectPtr res = NULL;
-    xmlNodeSetPtr list = NULL, oldlist;
+    xmlNodeSetPtr list = NULL, oldList;
     int i, oldProximityPosition, oldContextSize;
-    const xmlChar *oldmode, *oldmodeURI;
+    const xmlChar *oldMode, *oldModeURI;
     xsltStackElemPtr params = NULL, param, tmp, p;
     int nbsorts = 0;
+    int newdoc = 0;
     xmlNodePtr sorts[XSLT_MAX_SORT];
-
+    xmlDocPtr oldXDocPtr, newXDocPtr;
+    xsltDocumentPtr oldCDocPtr, newCDocPtr;
 
     if (comp == NULL) {
        xsltGenericError(xsltGenericErrorContext,
-            "xslt:apply-templates : compilation had failed\n");
+            "xsl:apply-templates : compilation failed\n");
        return;
     }
     if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL))
@@ -2034,16 +2036,26 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
     /*
      * Get mode if any
      */
-    oldnode = ctxt->node;
-    oldmode = ctxt->mode;
-    oldmodeURI = ctxt->modeURI;
+    oldNode = ctxt->node;
+    oldMode = ctxt->mode;
+    oldModeURI = ctxt->modeURI;
     ctxt->mode = comp->mode;
     ctxt->modeURI = comp->modeURI;
 
+    /*
+     * The xpath context size and proximity position, as
+     * well as the xpath and context documents, may be changed
+     * so we save their initial state and will restore on exit
+     */
+    newXDocPtr = oldXDocPtr = ctxt->xpathCtxt->doc;
+    newCDocPtr = oldCDocPtr = ctxt->document;
+    oldContextSize = ctxt->xpathCtxt->contextSize;
+    oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
+
     if (comp->select != NULL) {
        if (comp->comp == NULL) {
            xsltGenericError(xsltGenericErrorContext,
-                "xslt:apply-templates : compilation had failed\n");
+                "xsl:apply-templates : compilation failed\n");
            goto error;
        }
 #ifdef WITH_XSLT_DEBUG_PROCESS
@@ -2051,8 +2063,6 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
             "xsltApplyTemplates: select %s\n", comp->select);
 #endif
 
-       oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
-       oldContextSize = ctxt->xpathCtxt->contextSize;
        ctxt->xpathCtxt->node = node;
        ctxt->xpathCtxt->namespaces = comp->nsList;
        ctxt->xpathCtxt->nsNr = comp->nsNr;
@@ -2062,6 +2072,22 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
        if (res != NULL) {
            if (res->type == XPATH_NODESET) {
                list = res->nodesetval;
+               /* For a 'select' nodeset, need to check if document has changed */
+               if ( (res->nodesetval!=NULL) &&
+                    (res->nodesetval->nodeTab!=NULL) &&
+                    (res->nodesetval->nodeTab[0]->doc!=NULL) &&
+                    (res->nodesetval->nodeTab[0]->doc->doc!=NULL) &&
+                    (res->nodesetval->nodeTab[0]->doc->doc)!=ctxt->xpathCtxt->doc) {     
+                   newXDocPtr=res->nodesetval->nodeTab[0]->doc->doc;
+                   /* The nodeset is from another document, so must change */
+                   if ((newCDocPtr = xsltFindDocument(ctxt,newXDocPtr))==NULL) { 
+                       xsltGenericError(xsltGenericErrorContext,
+                               "xsl:apply-templates : can't find doc\n");
+                       goto error;
+                   }
+                   /* Can't actually do the change yet, so set flag for later */
+                   newdoc = 1;
+               }
                res->nodesetval = NULL;
             } else {
                list = NULL;
@@ -2133,10 +2159,8 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
        "xsltApplyTemplates: list of %d nodes\n", list->nodeNr);
 #endif
 
-    oldlist = ctxt->nodeList;
+    oldList = ctxt->nodeList;
     ctxt->nodeList = list;
-    oldContextSize = ctxt->xpathCtxt->contextSize;
-    oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
     ctxt->xpathCtxt->contextSize = list->nodeNr;
 
     /* 
@@ -2155,17 +2179,17 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
            } else if (IS_XSLT_NAME(cur, "sort")) {
                if (nbsorts >= XSLT_MAX_SORT) {
                    xsltGenericError(xsltGenericDebugContext,
-                       "xslt:call-template: %s too many sort\n", node->name);
+                       "xsl:call-template: %s too many sort\n", node->name);
                } else {
                    sorts[nbsorts++] = cur;
                }
            } else {
                xsltGenericError(xsltGenericDebugContext,
-                   "xslt:call-template: misplaced xslt:%s\n", cur->name);
+                   "xsl:call-template: misplaced xsl:%s\n", cur->name);
            }
         } else {
             xsltGenericError(xsltGenericDebugContext,
-                 "xslt:call-template: misplaced %s element\n", cur->name);
+                 "xsl:call-template: misplaced %s element\n", cur->name);
         }
         cur = cur->next;
     }
@@ -2174,6 +2198,20 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
        xsltDoSortFunction(ctxt, sorts, nbsorts);
     }
 
+
+    /* The original 'select' may have required a change of document*/
+    if (newdoc) {
+#ifdef WITH_XSLT_DEBUG_PROCESS
+       xsltGenericDebug(xsltGenericDebugContext,
+            "xsltApplyTemplates: Changing document - context doc %s, xpathdoc %s\n",
+            newCDocPtr->doc->URL, newXDocPtr->URL);
+#endif
+
+       ctxt->document = newCDocPtr;
+       ctxt->xpathCtxt->doc = newXDocPtr;
+       ctxt->xpathCtxt->node = list->nodeTab[0];
+    }
+
     for (i = 0;i < list->nodeNr;i++) {
        ctxt->node = list->nodeTab[i];
        ctxt->xpathCtxt->proximityPosition = i + 1;
@@ -2199,14 +2237,16 @@ xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node,
        }
     }
     xsltFreeStackElemList(params);     /* free the parameter list */
-    ctxt->nodeList = oldlist;
+    ctxt->nodeList = oldList;
     ctxt->xpathCtxt->contextSize = oldContextSize;
     ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
+    ctxt->xpathCtxt->doc = oldXDocPtr;
+    ctxt->document = oldCDocPtr;
 
 error:
-    ctxt->node = oldnode;
-    ctxt->mode = oldmode;
-    ctxt->modeURI = oldmodeURI;
+    ctxt->node = oldNode;
+    ctxt->mode = oldMode;
+    ctxt->modeURI = oldModeURI;
     if (res != NULL)
        xmlXPathFreeObject(res);
     if (list != NULL)
@@ -2241,13 +2281,13 @@ xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr node,
     replacement = inst->children;
     if (replacement == NULL) {
        xsltGenericError(xsltGenericErrorContext,
-            "xslt:choose: empty content not allowed\n");
+            "xsl:choose: empty content not allowed\n");
        goto error;
     }
     if ((!IS_XSLT_ELEM(replacement)) ||
        (!IS_XSLT_NAME(replacement, "when"))) {
        xsltGenericError(xsltGenericErrorContext,
-            "xslt:choose: xsl:when expected first\n");
+            "xsl:choose: xsl:when expected first\n");
        goto error;
     }
     while (IS_XSLT_ELEM(replacement) && (IS_XSLT_NAME(replacement, "when"))) {
@@ -2311,12 +2351,8 @@ xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr node,
        replacement = replacement->next;
     }
     if (replacement != NULL) {
-#ifdef WITH_XSLT_DEBUG_PROCESS
-       xsltGenericDebug(xsltGenericDebugContext,
-           "xsl:otherwise: applying default fallback\n");
-#endif
        xsltGenericError(xsltGenericErrorContext,
-            "xslt:choose: unexpected content %s\n", replacement->name);
+            "xsl:choose: unexpected content %s\n", replacement->name);
        goto error;
     }
 
@@ -2348,7 +2384,7 @@ xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr node,
        return;
     if ((comp == NULL) || (comp->test == NULL) || (comp->comp == NULL)) {
        xsltGenericError(xsltGenericErrorContext,
-            "xsl:if : compilation have failed\n");
+            "xsl:if : compilation failed\n");
        return;
     }
 
@@ -2408,17 +2444,19 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
                   xmlNodePtr inst, xsltStylePreCompPtr comp) {
     xmlXPathObjectPtr res = NULL;
     xmlNodePtr replacement;
-    xmlNodeSetPtr list = NULL, oldlist;
+    xmlNodeSetPtr list = NULL, oldList;
     int i, oldProximityPosition, oldContextSize;
     xmlNodePtr oldNode = ctxt->node;
     int nbsorts = 0;
     xmlNodePtr sorts[XSLT_MAX_SORT];
+    xmlDocPtr oldXDocPtr, newXDocPtr;
+    xsltDocumentPtr oldCDocPtr, newCDocPtr;
 
     if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
        return;
     if ((comp == NULL) || (comp->select == NULL) || (comp->comp == NULL)) {
        xsltGenericError(xsltGenericErrorContext,
-            "xslt:for-each : compilation had failed\n");
+            "xsl:for-each : compilation failed\n");
        return;
     }
 
@@ -2432,6 +2470,8 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
     ctxt->xpathCtxt->node = node;
     ctxt->xpathCtxt->namespaces = comp->nsList;
     ctxt->xpathCtxt->nsNr = comp->nsNr;
+    oldCDocPtr = ctxt->document;
+    oldXDocPtr = ctxt->xpathCtxt->doc;
     res = xmlXPathCompiledEval(comp->comp, ctxt->xpathCtxt);
     ctxt->xpathCtxt->contextSize = oldContextSize;
     ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
@@ -2449,15 +2489,37 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
 
 #ifdef WITH_XSLT_DEBUG_PROCESS
     xsltGenericDebug(xsltGenericDebugContext,
-       "xsltForEach: select evaluate to %d nodes\n", list->nodeNr);
+       "xsltForEach: select evaluates to %d nodes\n", list->nodeNr);
 #endif
 
-    oldlist = ctxt->nodeList;
+    oldList = ctxt->nodeList;
     ctxt->nodeList = list;
     oldContextSize = ctxt->xpathCtxt->contextSize;
     oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
     ctxt->xpathCtxt->contextSize = list->nodeNr;
 
+    /* For a 'select' nodeset, need to check if document has changed */
+    if (list->nodeTab!=NULL) {
+       if ( (res->nodesetval!=NULL) &&
+            (res->nodesetval->nodeTab!=NULL) &&
+            (res->nodesetval->nodeTab[0]->doc!=NULL) &&
+            (res->nodesetval->nodeTab[0]->doc->doc!=NULL) &&
+            (res->nodesetval->nodeTab[0]->doc->doc)!=ctxt->xpathCtxt->doc) {     
+           newXDocPtr=res->nodesetval->nodeTab[0]->doc->doc;
+           /* The nodeset is from another document, so must change */
+           if ((newCDocPtr = xsltFindDocument(ctxt,newXDocPtr))==NULL) {
+               xsltGenericError(xsltGenericErrorContext,
+                       "xsl:for-each : can't find document\n");
+               goto error;
+           }
+           ctxt->document = newCDocPtr;
+           ctxt->xpathCtxt->doc = newXDocPtr;
+           ctxt->xpathCtxt->node = list->nodeTab[0];
+           ctxt->xpathCtxt->contextSize = list->nodeNr;
+           ctxt->xpathCtxt->proximityPosition = 0;
+       }
+    }
+
     /* 
      * handle and skip the xsl:sort
      */
@@ -2465,7 +2527,7 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
     while (IS_XSLT_ELEM(replacement) && (IS_XSLT_NAME(replacement, "sort"))) {
        if (nbsorts >= XSLT_MAX_SORT) {
            xsltGenericError(xsltGenericDebugContext,
-               "xslt:for-each: too many sort\n");
+               "xsl:for-each: too many sort\n");
        } else {
            sorts[nbsorts++] = replacement;
        }
@@ -2485,8 +2547,10 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
        xsltApplyOneTemplate(ctxt, list->nodeTab[i], replacement, 0);
        xsltFreeStackElemList(varsPop(ctxt));
     }
-    ctxt->nodeList = oldlist;
+    ctxt->document = oldCDocPtr;
+    ctxt->nodeList = oldList;
     ctxt->node = oldNode;
+    ctxt->xpathCtxt->doc = oldXDocPtr;
     ctxt->xpathCtxt->contextSize = oldContextSize;
     ctxt->xpathCtxt->proximityPosition = oldProximityPosition;
 
@@ -2613,7 +2677,7 @@ xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc,
                goto error;
        } else if (xmlStrEqual(method, (const xmlChar *) "xhtml")) {
            xsltGenericError(xsltGenericErrorContext,
-            "xsltApplyStylesheet: insupported method xhtml, using html\n",
+            "xsltApplyStylesheet: unsupported method xhtml, using html\n",
                             style->method);
            ctxt->type = XSLT_OUTPUT_HTML;
            res = htmlNewDoc(doctypeSystem, doctypePublic);
@@ -2626,7 +2690,7 @@ xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc,
                goto error;
        } else {
            xsltGenericError(xsltGenericErrorContext,
-                            "xsltApplyStylesheet: insupported method %s\n",
+                            "xsltApplyStylesheet: unsupported method %s\n",
                             style->method);
            goto error;
        }