Search code examples
xmlxsltxpathtei

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


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>

Solution

  • 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">.