Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT number only counts instances in current file of a multi-file document

Tags:

xslt

I've been tasked with putting together a book (using XSL FO) from a number of XML-files, now I'm trying to number the figures in this book (simple numbering, no resets at chapters or whatever), my naive approach was to do this

<xsl:template match="figure">
  <fo:block xsl:use-attribute-sets="figure">
    .. stuff to deal with images ..
    <fo:block xsl:use-attribute-sets="figure-caption">
      Figure <xsl:number level="any"/>: <xsl:apply-templates/>
    </fo:block>
  <fo:block xsl:use-attribute-sets="figure-caption">
</xsl:template>

I have an aggregate XML file which selects the files to use using the document() function like so:

<xsl:template match="include">
  <xsl:apply-templates select="document(@src)"/>
</xsl:template>

Now, my problem is that number seems to always only count the instances in the current file, which is not what I want (currently, there's only one or two images per file, resulting in all figures being 'Figure 1' or 'Figure 2').

I've considered two approaches, both being essentially two-pass XSLT. First, the straightforward approach, generate an intermediary XML containing the entire book using an identity transform, which I'm reluctant to do for other reasons.

Second, using node-set() extension, which I tried like this

<xsl:template match="include">
  <xsl:apply-templates select="ext:node-set(document(@src))"/>
</xsl:template>

but this produced the same result.

Any ideas? Perhaps something which isn't a two-pass transformation? Any help would be greatly appreciated.

like image 769
falstro Avatar asked Feb 10 '11 11:02

falstro


People also ask

What is mode in XSLT?

mode. The mode attribute allows an element as specified by its Qualified Names to be processed multiple times, each time producing a different result. If <xsl:template> does not have a match attribute, it cannot have a mode attribute.


1 Answers

The two -pass approach is the more logical and robust one.

One-pass approach is very challenging. One can provide an expression in the value attribute of <xsl:number> and this can be used to sum the "local number" with the maximum accumulated number so far from all previous documents.

However, this requires sequencing the documents (which is something bad in a functional language) and this only works for a flat numbering scheme. In case hierarchical numbering is used (3.4.2), I don't see an easy way to continue from the max number of a previous document.

Due to this considerations, I would definitely merge all documents into one before numbering.

like image 88
Dimitre Novatchev Avatar answered Oct 08 '22 06:10

Dimitre Novatchev