Subject: [xsl] Set difference in xsl:number/@count, xsl:key/@match From: "Deborah Pickett" <debbiep-list-xsl@xxxxxxxxxx> Date: Wed, 21 Mar 2007 13:59:16 +1100 (EST) |
This is in the context of XSLT 1.0, auto-generating numbering for figures (illustrations) in print documentation. I have a solution, but I think it's dirty and wonder if there is a better way. My XML document is a DITA topic. For those who don't know DITA, it's in the family of DocBook and XHTML, but it has funky extensibility mechanisms that let me define a special kind of <figure>, let's call it <flowchart>, and insert it into a topic anywhere that <figure> would normally be allowed. Base XSLT processing for <figure> automatically applies to <flowchart> too, unless I write an override template to handle <flowchart>. Technically, this is all handled with a "class" attribute with crafted default values in the DTD; in DITA, the class is more important than the element name. The XSLT for my flowchart extension will all be in a different .xsl file, so that it can be imported after the base XSLT to override the base figure processing. Not everyone has the same set of extensions. This is SOP for DITA. Example, with explicit class attribute: <topic class=" topic "> <!-- other stuff --> <figure class=" figure "><!-- figure contents --></figure> <flowchart class=" figure flowchart "><!-- figure contents --></flowchart> <figure class=" figure "><!-- figure contents --></figure> <!-- more other stuff --> </topic> Auto-generating text to say "Figure 1", "Figure 2", "Figure 3" is easy: <xsl:number count="*[contains(@class, ' figure ')]"/> but I need my flowchart numbering to be independent, and auto-generate "Figure 1", "Flowchart 1", "Figure 2". I sort of want to say <xsl:number count="*[contains(@class, ' figure ')] except *[contains(@class, ' flowchart ')]"/> only set difference doesn't work in xsl:number/@count, even in XSLT 2.0. Besides, the base processing can't necessarily know about flowcharts, circuitdiagrams, familytrees, or however many specializations of "figure" I've included. Each specialization has to have its own processing XSLT. Other specializations of figure might want to just use figure numbering, too, so the absence of text after " figure " in the class isn't a good indicator. I worked out all by myself about the additive nature of xsl:key when the same name is re-used, and that was the basis for my dirty solution. In short: set difference via keys. Base processing has something like this: <xsl:key name="figure.count" match="*[contains(@class, ' figure ')]" use="'include'"/> And flowchart processing adds more keys: <xsl:key name="figure.count" match="*[contains(@class, ' flowchart ')]" use="'exclude'"/> A shell XSL file imports the base XSLT, then the flowchart XSLT. To get the figure number, I count all the figures up to that point, and subtract the ones that have asked to be excluded: <xsl:variable name="all"> <xsl:number count="key('figure.count', 'include')" level="any"/> </xsl:variable> <xsl:variable name="except"> <xsl:number count="key('figure.count', 'exclude')" level="any"/> </xsl:variable> <!-- some code to handle empty $except (= 0) omitted --> <xsl:value-of select="number($all) - number($except)"/> It works a treat, but it would be simpler if there was some mechanism to "delete" or ignore key members, or use key() in xsl:key to build up a composite key from parts, or attach a predicate to key() in a pattern, or have xsl:number/@count know about set differences. Is there a better way? Even in XSLT 2.0, which seems to have similar limitations about keys in patterns?
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
Re: [xsl] xpath / multiple context , Paul Tyson | Thread | Re: [xsl] Set difference in xsl:num, G. Ken Holman |
Re: [xsl] xpath / multiple context , Wendell Piez | Date | [xsl] Transforming a Loose Structur, Jeff Sese |
Month |