GNOME Bugzilla – Bug 307103
Templates dont match
Last modified: 2006-07-14 16:21:58 UTC
Using libxml 20619, libxslt 10114 and libexslt 812 xsltproc was compiled against libxml 20619, libxslt 10114 and libexslt 812 libxslt 10114 was compiled against libxml 20619 libexslt 812 was compiled against libxml 20619 THE DOCUMENT: ------------- <?xml version="1.0" encoding="UTF-8"?> <firmenindex> <hvfi:firma xmlns:hvfi="http://www.heinze.de/xmlns/herstellerverzeichnis/firmen"> <hvfi:adresse> <name>Mustermann#1</name> <name>Mustermann#2</name> <name>Mustermann#3</name> </hvfi:adresse> </hvfi:firma> </firmenindex> THE STYLESHEET: --------------- <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:hzfo="http://www.heinze.de/xmlns/formating-objects/" exclude-result-prefixes="hzfo"> <xsl:import href="./module1.xsl"/> <xsl:import href="./module2.xsl"/> <xsl:import href="./module3.xsl"/> <xsl:import href="./module4.xsl"/> <xsl:output method="xml"/> <xsl:template match="/"> <xsl:apply-templates select="." mode="hzfo:page.sequence"/> </xsl:template> </xsl:stylesheet> THE MODULE #1: -------------- <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:hzfo="http://www.heinze.de/xmlns/formating-objects/" xmlns:hvfi="http://www.heinze.de/xmlns/herstellerverzeichnis/firmen" exclude-result-prefixes="hzfo"> <xsl:template match="firmenindex" mode="hzfo:page.sequence"> <xsl:text> template#1 in module#1</xsl:text> <xsl:apply-templates select="hvfi:firma"/> </xsl:template> </xsl:stylesheet> THE MODULE #2: -------------- <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:hzfo="http://www.heinze.de/xmlns/formating-objects/" xmlns:hvfi="http://www.heinze.de/xmlns/herstellerverzeichnis/firmen" exclude-result-prefixes="hzfo"> <xsl:template match="hvfi:firma" mode="hzfo:header"> <xsl:text> template#1 in module#2</xsl:text> <xsl:apply-templates select="hvfi:adresse"/> </xsl:template> <xsl:template match="hvfi:firma" mode="hzfo:header.first"> <xsl:text> template#2 in module#2</xsl:text> <xsl:apply-templates select="hvfi:adresse"/> </xsl:template> </xsl:stylesheet> THE MODULE #3: -------------- <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:hvfi="http://www.heinze.de/xmlns/herstellerverzeichnis/firmen"> <xsl:template match="hvfi:adresse/name[position()=1]"> <xsl:text> template#1 in module#3</xsl:text> <xsl:value-of select="."/> </xsl:template> <xsl:template match="hvfi:adresse/name[position()=2]"> <xsl:text> template#2 in module#3</xsl:text> <xsl:value-of select="."/> </xsl:template> <xsl:template match="hvfi:adresse/name[position()>2]"> <xsl:text> template#3 in module#3</xsl:text> <xsl:value-of select="."/> </xsl:template> </xsl:stylesheet> THE MODULE #4: -------------- <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:hzfo="http://www.heinze.de/xmlns/formating-objects/" xmlns:hvfi="http://www.heinze.de/xmlns/herstellerverzeichnis/firmen" exclude-result-prefixes="hzfo"> <xsl:template match="hvfi:firma"> <xsl:apply-templates select="." mode="hzfo:header"/> <xsl:apply-templates select="." mode="hzfo:header.first"/> </xsl:template> <xsl:template match="hvfi:adresse"> <xsl:apply-templates select="name[position()=1]"/> <xsl:apply-templates select="name[position()=2]"/> </xsl:template> </xsl:stylesheet> THE RESULT WITH LibXSLT: ------------------------ <?xml version="1.0"?> template#1 in module#1 template#1 in module#2 template#1 in module#3Mustermann#1 template#2 in module#3Mustermann#2 template#2 in module#2 template#1 in module#3Mustermann#1Mustermann#2 THE RESULT WITH MSXML, Saxon, Sablotron: ---------------------------------------- <?xml version="1.0" encoding="UTF-8"?> template#1 in module#1 template#1 in module#2 template#1 in module#3Mustermann#1 template#2 in module#3Mustermann#2 template#2 in module#2 template#1 in module#3Mustermann#1 template#2 in module#3Mustermann#2 Regards Gero
Reduced, human-readable results: Libxslt "... Mustermann#1 Mustermann#2" Other "... Mustermann#1 template#2 in module#3 Mustermann#2" So it seems Libxslt is missing a call to the following template in "module3.xsl": <xsl:template match="hvfi:adresse/name[position()=2]"> <xsl:text> template#2 in module#3</xsl:text> <xsl:value-of select="."/> </xsl:template>
In xsltTestCompMatch() the proximity position incorrectly evaluates to 1 (shold be 2) the second time the template match of <xsl:template match="hvfi:adresse/name[position()=2]"> is evaluated, thus the "position()=2" predicate evaluates to false. This is strange, since this template is invoked by the following template both times: <xsl:template match="hvfi:adresse"> <xsl:apply-templates select="name[position()=1]"/> <xsl:apply-templates select="name[position()=2]"/> </xsl:template> The first processing of <xsl:apply-templates select="name[position()=2]"/> finds the template, the *second* not. More details: In In xsltTestCompMatch() we have: ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival); The first time the template match is evaluated, @ix evaluates to 1; the second time the same template is evaluated, @ix results in 0 for the same context node. Some later code then computes the proximity position: pos = ix + indx; Which correctly is 2 the first time, and incorrectly 1 the second time. Does the ix = XSLT_RUNTIME_EXTRA(ctxt, sel->indexExtra, ival); maybe use some stored values on the compiled expression, so that evaluating it a second time, wrong values are used? Is a cleanup of the compiled expression, after evaluating it, maybe missed somewhere?
Here is the sequence of events which lead to the bug: 1) Processing <xsl:apply-templates select="name[position()=2]"/> --> the 2nd "name" element becomes the context node --> Processing <xsl:template match="hvfi:adresse/name[position()=2]"> Some values are stored: ctxt->extras[(sel->indexExtra)].val.ival = 2 ctxt->extras[(sel->indexExtra)].val.ival = 2nd "name" element The second time this sequence of templates is invoked: 2) Processing <xsl:apply-templates select="name[position()=2]"/> --> the 1st "name" element becomes the context node --> Processing <xsl:template match="hvfi:adresse/name[position()=2]"> The stored values are retrieved: @ix == 2 @previous == 2nd "name" element At this point @previous is now a *following-sibling* - not a preceding-sibling - of the context node; this means that the computation of the proximity position relative to @previous fails and a fallback-computation for such a reverse case is performed. And now comes the bug: the fallback-computation misses to skip text nodes and the position is computed incorrectly. Adjusting this fallback code to work exactly as in the normal code heals the problem. I'll try to commit the fix today.
Correction, in point 2) it should read (note the "position()=1"): 2) Processing <xsl:apply-templates select="name[position()=1]"/>
Fixed in CVS.