GNOME Bugzilla – Bug 65391
xsl:number ignores "format" attribute!
Last modified: 2009-08-15 18:40:50 UTC
I am using xsl:number to create labels for itemised lists in XSL. When I create a nested list, the inner items should have a different format, i.e. 1., 2. for the outer labels and a., b. for the inner labels. I have no problem creating the appropriate format string for each label, but xsl:number is ignoring the format strings! (The complete files are included at the end). The code in question is this: <xsl:number format="{$format}" level="single"/> <!-- For debugging --> <xsl:value-of select="concat('(format=',$format,')')"/> It produces these two labels: 1.(format=1.) 1.(format=a.) You can see that the xsl:number is ignoring the format string. In general, it appears as if xsl:number does take into account the first format it sees, but then subsequent invocations use the first format. This bug is still present with libxslt-1.0.7-4 and libxml2-2.4.10-2. Thanks, -- Jamie Lokier ------------------ File text.xml ------------------ <?xml version="1.0" encoding="iso-8859-1"?> <?xml-stylesheet type="text/xsl" href="document.xsl"?> <!DOCTYPE document SYSTEM "document.dtd"> <document> <ol> <li>One level deep. <ol> <li> Two levels deep. Why doesn't this have the correct label format? </li> </ol> </li> </ol> </document> -------------------- File test.xsl ------------------- <?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE xsl:stylesheet> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:output method="xml" indent="yes"/> <!-- {{{ Handle enumerated lists including nested counters --> <!-- Unashamedly similar to the docbook-style-xsl package. --> <xsl:template name="list.numeration.next"> <xsl:param name="type" select="'default'"/> <xsl:choose> <xsl:when test="$type = 'arabic'">loweralpha</xsl:when> <xsl:when test="$type = 'loweralpha'">lowerroman</xsl:when> <xsl:when test="$type = 'lowerroman'">upperalpha</xsl:when> <xsl:when test="$type = 'upperalpha'">upperroman</xsl:when> <xsl:when test="$type = 'upperroman'">arabic</xsl:when> <xsl:otherwise>arabic</xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="list.numeration.type"> <xsl:param name="node" select="."/> <xsl:choose> <xsl:when test="$node/ancestor-or-self::ol[position()=1]/@numeration"> <xsl:value-of select="$node/ancestor-or-self::ol[position()=1]/@numeration"/> </xsl:when> <xsl:when test="$node/ancestor::ol"> <xsl:call-template name="list.numeration.next"> <xsl:with-param name="type"> <xsl:call-template name="list.numeration.type"> <xsl:with-param name="node" select="$node/ancestor::ol[position()=1]"/> </xsl:call-template> </xsl:with-param> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="'arabic'"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template name="list.numeration.format"> <xsl:param name="node" select="."/> <xsl:variable name="type"> <xsl:call-template name="list.numeration.type"> <xsl:with-param name="node" select="$node"/> </xsl:call-template> </xsl:variable> <xsl:choose> <xsl:when test="$type = 'arabic'">1.</xsl:when> <xsl:when test="$type = 'loweralpha'">a.</xsl:when> <xsl:when test="$type = 'lowerroman'">i.</xsl:when> <xsl:when test="$type = 'upperalpha'">A.</xsl:when> <xsl:when test="$type = 'upperroman'">I.</xsl:when> <xsl:otherwise>1.</xsl:otherwise> </xsl:choose> </xsl:template> <!-- Choose an appropriate label for a list item node ("li"). A formatted number is returned if the parent is "ol", otherwise a bullet is returned. --> <xsl:template name="list.item.label"> <xsl:param name="li" select="."/> <xsl:choose> <xsl:when test="$li/@label"> <!-- Insert the string specified by the label attribute. --> <xsl:value-of select="$li/@label"/> </xsl:when> <xsl:when test="$li/parent::ol"> <!-- Insert a formatted number or letter. --> <xsl:variable name="format"> <xsl:call-template name="list.numeration.format"> <xsl:with-param name="node" select="$li/parent::ol"/> </xsl:call-template> </xsl:variable> <xsl:number format="{$format}" level="single"/> <!-- For debugging --> <xsl:value-of select="concat('(format=',$format,')')"/> </xsl:when> <xsl:otherwise> <!-- Insert a bullet. --> <xsl:text>•</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- General list spacing from non-list paragraphs. --> <xsl:template match="ul|ol"> <fo:list-block xsl:use-attribute-sets="list-block-properties"> <xsl:apply-templates/> </fo:list-block> </xsl:template> <!-- List items. Both ordered and unordered lists are handled here. --> <xsl:template match="li"> <!-- Choose the appropriate label string. --> <xsl:variable name="label"> </xsl:variable> <fo:list-item xsl:use-attribute-sets="list-item-properties"> <!-- The label to the left of this list item. --> <fo:list-item-label xsl:use-attribute-sets="list-item-label-properties"> <fo:block> <!-- border-style="solid" border-color="green" --> <xsl:call-template name="list.item.label"/> </fo:block> </fo:list-item-label> <!-- The body text of this list item. --> <fo:list-item-body xsl:use-attribute-sets="list-item-body-properties"> <fo:block> <!-- border-style="solid" border-color="red" --> <xsl:apply-templates/> </fo:block> </fo:list-item-body> </fo:list-item> </xsl:template> <!-- }}} --> </xsl:stylesheet>
Okay, I finally took the time to chase that bug down. Found it, the problem occurs when the format has to be recomputed on each evaluation, the code inapropriately cached the value in an internal structure. The fix is rather simple: http://cvs.gnome.org/bonsai/cvsquery.cgi?module=libxslt&branch=HEAD&branchtype=match&dir=libxslt&file=&filetype=match&who=veillard&whotype=match&sortby=Date&hours=&date=explicit&mindate=01%2F14%2F02+06%3A20&maxdate=01%2F14%2F02+06%3A22&cvsroot=%2Fcvs%2Fgnome thanks a lot for you very detailed and self-contained bug report it *really* helps fiding and fixing the problem ! the next version will have that fix incorporated, Daniel
Should be fixed in 1.0.10 release, thanks, Daniel