skip to Main Content

I am currently transforming xml to html with an xslt stylesheet. I use VS Code with the XSLT/XPath extension and have a tasks.json to do the transformation. It works fine for a single xml file, but I actually have multiple files, for which the same template applys and which should all be in the same html file.

My working tasks.json for a single file:

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "xslt-js",
            "label": "Saxon-JS Transform (Briefe)",
            "xsltFile": "briefe/tei_to_html.xsl",
            "xmlSource": "briefe/3690096/3690096.xml",
            "resultPath": "edition.html",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": [
                "$saxon-xslt-js"
            ]
        }
    ]
}

I tried to use wildcards for the source "briefe/**/*.xml", which results in an error: Failed to read XML source input (Failed to read … /briefe/**/*.xml (no such file))
An array of the files (it’s only a handful, so I could type them all in) is not possible, because xmlSource only accepts string.

I suppose I am able to handle multiple xml files in my stylesheet with for-each and document, but how do I specify multiple files as source in my task?

Update:

The goal is to process multiple xml files with one XSLT, to produce one result file.

I figured out, that I could feed a json as source:

...
"useJsonSource": true,
"xmlSource": "briefe/list.json",
...

I am trying to find out if I can process the json in xslt and this is the solution.

2

Answers


  1. Chosen as BEST ANSWER

    I solved this task with building a collection in a separate file letters.xml and used this as xmlSource. The collection:

    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-model href="http://www.w3.org/2001/XMLSchema"?>
    
    <collection stable="true">
        <doc href="letter_1.xml"/>
        <doc href="letter_2.xml"/>
    </collection>
    

    With the last comment I switched from xslt-js to xslt, because using xslt-js was not a deliberate decision.

    My tasks.json:

    {
        "version": "2.0.0",
        "tasks": [
            {
                "type": "xslt",
                "label": "xslt: Saxon Transform (Briefe Ebner-Eschenbach)",
                "saxonJar": "SaxonHE11-3J/saxon-he-11.3.jar",
                "xsltFile": "tei_to_html.xsl",
                "xmlSource": "letters.xml",
                "resultPath": "index.html",
                "group": {
                    "kind": "build",
                    "isDefault": true
                },
                "problemMatcher": [
                    "$saxon-xslt"
                ]
            }
        ]
    }
    

    In my tei_to_html.xsl I use the collection in a variable and create pages for the letters:

    <xsl:variable name="letters" select="collection('briefe.xml')"/>
    
    [...]
    
    <xsl:for-each select="$letters">
                <xsl:result-document href="{concat('letter_', position(),'.html')}" method="html">
                    <xsl:call-template name="letter_page"/>
                </xsl:result-document>
            </xsl:for-each>
    

    Thank you all for your help and input! I definitely learned a lot.


  2. Assuming the list.json is e.g. an array of strings with file names ["file1.xml", "file2.xml", "file3.xml"] your XSLT 3 would process e.g.

    <xsl:template match=".[. instance of array(xs:string)]">
      <xsl:apply-templates select="?*!doc(.)"/>
    </xsl:template>
    

    Depending on the rest of your stylesheet you might want to output the HTML document structure around that xsl:apply-templates e.g.

    <xsl:template match=".[. instance of array(xs:string)]">
      <html>
        <head>
          <title>Example</title>
        </head>
        <body>
          <xsl:apply-templates select="?*!doc(.)"/>
        </body>
       </html>
    </xsl:template>
    

    While SaxonJS certainly has a -json option to process a JSON input file I haven’t checked how/whether that interacts nicely with the xslt-js task in VS Code so be prepared to experiment how it works.

    From the command line you would run e.g. xslt3 -json:list.json -xsl:xslt.xsl to have a list.json containing a JSON array with a string of file names processed by the stylesheet xslt.xsl where the template shown above would match that array and push each file named as a document node created with the doc function to any of your other templates.

    Another option would be to pass the file names as a global parameter and to start with the named template name="xsl:initial-template", option -it to do e.g.

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      version="3.0"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      exclude-result-prefixes="#all"
      expand-text="yes">
    
    <xsl:param name="file-names" as="xs:string*" select="'file1.xml', 'file2.xml', 'file3.xml'"/>
    
    <xsl:template name="xsl:initial-template">
      <html>
        <head>
          <title>Example</title>
        </head>
        <body>
          <xsl:apply-templates select="$file-names!doc(.)"/>
        </body>
       </html>
    </xsl:template>
      
    </xsl:stylesheet>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search