XSLT counts only instances in the current multi-file document file

I was instructed to assemble a book (using XSL FO) from several XML files, now I'm trying to count the numbers in this book (simple numbering, without resetting in chapters, etc.), 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 a composite XML file that selects files that are used with the document() function, for example:

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

Now my problem is that number apparently always only considers instances in the current file, which is not what I want (currently there is only one or two images per file, resulting in all numbers being equal "Figure 1 'or' Figure 2 ').

I looked at two approaches, both essentially two-pass XSLTs. First, a simple approach, create intermediate XML containing the entire book using an identity transformation, which I am reluctant to do for other reasons.

Secondly, using the node-set() extension, which I tried as

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

but it gave the same result.

Any ideas? Perhaps something that is not a two-pass transformation? Any help would be greatly appreciated.

+6
xslt multiple-files
source share
4 answers

The two-pane approach is more logical and reliable.

The one-pass approach is very complex. You can specify the expression in the attribute value <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 arranging documents (which does not work well in a functional language), and this only works for a flat numbering scheme. If hierarchical numbering is used (3.4.2), I do not see an easy way from the maximum number of the previous document.

In connection with these considerations, I would definitely combine all the documents into one before numbering.

+3
source share

I will also use two-phase conversion. But just for fun, with one include level and no repetition, this stylesheet:

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:variable name="vIncludes" select="//include"/> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="include"> <xsl:apply-templates select="document(@src)"/> </xsl:template> <xsl:template match="picture"> <xsl:variable name="vRoot" select="generate-id(/)"/> <xsl:variable name="vInclude" select="$vIncludes[ $vRoot = generate-id(document(@src)) ]"/> <xsl:copy> <xsl:value-of select="count( document( (.|$vInclude)/preceding::include/@src )//picture | (.|$vInclude)/preceding::picture ) + 1"/> </xsl:copy> </xsl:template> </xsl:stylesheet> 

With this input:

 <master> <include src="child3.xml"/> <block> <include src="child1.xml"/> <picture/> </block> <include src="child2.xml"/> <picture/> </master> 

And 'child1.xml'

 <child1> <picture/> </child1> 

And 'child2.xml'

 <child2> <picture/> </child2> 

And 'child3.xml'

 <child3> <picture/> </child3> 

Output:

 <master> <child3> <picture>1</picture> </child3> <block> <child1> <picture>2</picture> </child1> <picture>3</picture> </block> <child2> <picture>4</picture> </child2> <picture>5</picture> </master> 
+2
source share

You can use an auxiliary XML document to keep track of the last digit number and load this file as a document from the stylesheet. Or, if you do not want to manage two output files from the same stylesheet (the "real" FOP output and the number counter), you can simply download the previous chapter FOP file and see the MAX picture.

Or you can pass the last digit number as a parameter with a default value of zero and pass the parameter on the command line. The value of this parameter as a result of parsing the previous one in ascending order of the resulting document.

All of these alternatives assume that you are sequentially transforming the source document in ascending order.

A more structured and robust solution would be to manage the transverse sections of the document, such as indexes, the table of contents and the numbers table, as in most individual FO documents that will be generated in the second pass with their own XSLT.

0
source share

I think I would do a preass, which displays the summary information about all documents in one XML file, and then uses this as an additional input to calculate the number. The summary information in your case may simply be a count of the number of digits contained in each document, but in many cases it may be useful to store other information, such as section identifiers, which will act as the target of the hyperlinks.

0
source share

All Articles