GNOME Bugzilla – Bug 61673
Current Node is wrong after for-each and apply-templates
Last modified: 2009-08-15 18:40:50 UTC
I think this is a bug in xsltproc Stylesheet: ======== <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:libxslt="http://xmlsoft.org/XSLT/namespace"> <xsl:output method="xml" indent="yes" encoding="ISO-8859-1"/> <xsl:variable name="one"> <xsl:copy-of select="."/> </xsl:variable> <xsl:variable name="two" select="document('two.xml')"/> <xsl:template match="/"> <xsl:apply-templates select="$two" mode="two"/> </xsl:template> <xsl:template match="*" mode="two"> <xsl:for-each select="//content"> <xsl:apply-templates select="libxslt:node-set($one)" mode="one"/> <xsl:text>-----------------</xsl:text> </xsl:for-each> </xsl:template> <xsl:template match="*" mode="one"> <xsl:for-each select="//content"> <!-- here is the problem (.//content works well, but I need the key function)--> <xsl:copy-of select="."/> </xsl:for-each> </xsl:template> </xsl:stylesheet> one.xml ====== <?xml version="1.0"?> <eins> <content>content of one</content> </eins> two.xml ====== <?xml version="1.0"?> <two> <content>content of two1</content> <content>content of two2</content> <content>content of two3</content> </two> RESULT: ======== > xsltproc test.xslt one.xml <?xml version="1.0" encoding="ISO-8859-1"?> <content>content of two1</content> <content>content of two2</content> <content>content of two3</content> ----------------- <content>content of two1</content> <content>content of two2</content> <content>content of two3</content> ----------------- <content>content of two1</content> <content>content of two2</content> <content>content of two3</content> ----------------- Expected Result: ============= <?xml version="1.0" encoding="ISO-8859-1"?> <content>content of one</content> ----------------- <content>content of one</content> ----------------- <content>content of one</content> ----------------- Version ======= xsltproc -V Using libxml 20400 and libxslt 10000 xsltproc was compiled against libxml 20400 and libxslt 10000 libxslt 10000 was compiled against libxml 20400 OS: === uname -a Linux linuxdaheim 2.2.19 #9 SMP Mon Jun 4 21:02:03 CEST 2001 i686 unknown Bernhard
Hum, this one was really hard to track down, though the fix is really small. In a nutshell the copy done of a result value tree could in some case loose the information about the original document and in turn apply-template would not switch back to the proper document container when processing that node. The patch concerns the libxml2 xpath.c module mostly: ---------------------------------- RCS file: /cvs/gnome/gnome-xml/xpath.c,v retrieving revision 1.151 diff -c -r1.151 xpath.c *** xpath.c 2001/10/06 09:59:51 1.151 --- xpath.c 2001/10/06 12:59:48 *************** *** 2755,2761 **** if ((val->nodesetval != NULL) && (val->nodesetval->nodeTab != NULL)) { ret->boolval = 1; ! ret->user = xmlCopyNode(val->nodesetval->nodeTab[0], 1); ret->nodesetval = xmlXPathNodeSetCreate( (xmlNodePtr) ret->user); } else --- 2755,2762 ---- if ((val->nodesetval != NULL) && (val->nodesetval->nodeTab != NULL)) { ret->boolval = 1; ! ret->user = xmlDocCopyNode(val->nodesetval->nodeTab[0], ! val->nodesetval->nodeTab[0]->doc, 1); ret->nodesetval = xmlXPathNodeSetCreate( (xmlNodePtr) ret->user); } else --------------------------- I also tweaked the libxslt/variables.c module a bit: --------------------------- RCS file: /cvs/gnome/libxslt/libxslt/variables.c,v retrieving revision 1.50 diff -c -r1.50 variables.c *** variables.c 2001/09/17 12:52:17 1.50 --- variables.c 2001/10/06 13:03:07 *************** *** 358,364 **** xmlNodePtr container; xmlNodePtr oldInsert; ! container = xmlNewDocNode(ctxt->output, NULL, (const xmlChar *) "fake", NULL); if (container == NULL) return(NULL); --- 358,364 ---- xmlNodePtr container; xmlNodePtr oldInsert; ! container = xmlNewDocNode(ctxt->document->doc, NULL, (const xmlChar *) "fake", NULL); if (container == NULL) return(NULL); *************** *** 478,484 **** xmlNodePtr container; xmlNodePtr oldInsert; ! container = xmlNewDocNode(ctxt->output, NULL, (const xmlChar *) "fake", NULL); if (container == NULL) return(NULL); --- 478,484 ---- xmlNodePtr container; xmlNodePtr oldInsert; ! container = xmlNewDocNode(ctxt->document->doc, NULL, (const xmlChar *) "fake", NULL); if (container == NULL) return(NULL); -------------------------- The run now produces the expected output and nothing else seems to be broken by that change: orchis:~/XSLT/tests/general -> xsltproc bug-65.xsl ../docs/bug-65.xml <?xml version="1.0"?> <content>content of one</content> ----------------- <content>content of one</content> ----------------- <content>content of one</content> ----------------- orchis:~/XSLT/tests/general -> thanks for the report and the test case, Daniel
Should be fixed in the last releases, Daniel