Load multiple files with XSL document and store them in separate variables

1.1k Views Asked by At

i wrote a little XSL transformation to combine multiple .xml-documents into one file. For this purpose i am using the document() function. Currently my solution is working fine, but i am asking myself if there is a more elegant way to do this.

Is there another way to load multiple files and store each of them in a variable and then process these multiple variables within xsl:copy-of?

Here is an example of my current XSL transformation (the XSLT is part of a XPROC-pipeline and the first file gets loaded within the pipeline):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tei="http://www.tei-c.org/ns/1.0"
xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="#all">




<!-- Laden der übrigen TEI-Dateien -->
<xsl:variable name="Fig2" select="document('2_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig3" select="document('3_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig4" select="document('4_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig5" select="document('5_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig6" select="document('6_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig7" select="document('7_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig8" select="document('8_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig9" select="document('9_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig10" select="document('10_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig11" select="document('11_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig12" select="document('12_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig13" select="document('13_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig14" select="document('14_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig15" select="document('15_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig16" select="document('16_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig17" select="document('17_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig18" select="document('18_Figuration_transformiert.xml', tei:TEI)"/>
<xsl:variable name="Fig19" select="document('19_Figuration_transformiert.xml', tei:TEI)"/>


<xsl:template match="/">
    <html>
        <xsl:copy-of select="."/>
        <xsl:copy-of select="$Fig2"/>
        <xsl:copy-of select="$Fig3"/>  
        <xsl:copy-of select="$Fig4"/>
        <xsl:copy-of select="$Fig5"/>
        <xsl:copy-of select="$Fig6"/>
        <xsl:copy-of select="$Fig7"/>
        <xsl:copy-of select="$Fig8"/>
        <xsl:copy-of select="$Fig9"/>
        <xsl:copy-of select="$Fig10"/>
        <xsl:copy-of select="$Fig11"/> 
        <xsl:copy-of select="$Fig12"/>
        <xsl:copy-of select="$Fig13"/>
        <xsl:copy-of select="$Fig14"/>
        <xsl:copy-of select="$Fig15"/>
        <xsl:copy-of select="$Fig16"/>
        <xsl:copy-of select="$Fig17"/>
        <xsl:copy-of select="$Fig18"/>
        <xsl:copy-of select="$Fig19"/>
      </html>
</xsl:template>

</xsl:stylesheet>
3

There are 3 best solutions below

2
On BEST ANSWER

Along the lines of this (the XML document you use as input does not matter here):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tei="http://www.tei-c.org/ns/1.0"
xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="#all">

    <xsl:param name="files" select="'1_Figuration_transformiert.xml;2_Figuration_transformiert.xml;...'" />

    <xsl:template match="/">
        <html>
            <xsl:for-each select="tokenize($files, ';')">
                <xsl:copy-of select="document(.)/*" />
            </xsl:for-each>
        </html>
    </xsl:template>

</xsl:stylesheet>

The actual list of filenames is meant to be passed in from the outside instead of being hard-coded. This makes integration into batch processes easy.

You can vary the approach. For example,

  • If all documents have the same suffix, you can make a list of numbers and use
    document(concat(., '_Figuration_transformiert.xml')).
  • If there is a fixed number of documents and there are no gaps in the numbers, you could use
    <xsl:for-each select="1 to 19">.
  • If the start and end of the loop are variable, you could make <xsl:param> for them and use use
    <xsl:for-each select="$start to $end">.
0
On

You ask: Is there another way to load multiple files and store each of them in a variable and then process these multiple variables within xsl:copy-of?

Well, no: if you want 18 variables, each holding one file, then you will need 18 variable declarations. But you can achieve the same effect without having 18 variables.

Firstly, you don't need any variables at all, since each of them is only used once. You could just inline them all (replace the variable reference $Fig6 by the expression used to initialize the variable Fig6).

Secondly, if the URIs will always be systematically named like this, then you don't need to spell them all out: you can put the names in a single variable

<xsl:variable name="figs" select="(2 to 18)!(. || '_Figuration_transformiert.xml')"/>

and then replace a reference to $Fig6 with a reference to $figs[6]. And then of course you don't need to spell out $figs[1], $figs[2], etc: you can process them all in a loop.

(The variable declaration above is XSLT 3.0 syntax, but you can achieve the same thing in XSLT 2.0 with a bit more code).

0
On

If the XProc processor uses Saxon 9 as the XSLT 2 processor then you could also try whether using the collection functions eases that ask by using e.g. <xsl:copy-of select="collection(concat(base-uri(), '?select=*_Figuration_transformiert.xml'))"/> instead of all the separate copy-of instructions.

See http://saxonica.com/html/documentation9.8/sourcedocs/collections.html.