0

I want to batch process all the XML files in a directory, generating output filenames based on a value in each XML. I am using the Saxon collection function in conjunction with the base-uri function, but I am having difficulty accessing each URI individually.

Edit: the below stylesheet gives the error message: "A sequence of more than one item is not allowed as the first argument of base-uri()"

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" />
    <xsl:param name="input-dir" select="'file:///C:/path/to/directory'"/>

    <xsl:template name="main">
        <xsl:variable name="input-docs" select="collection(iri-to-uri(concat($input-dir, '?select=*.xml')))"/>
        <xsl:variable name="old-filename" select="base-uri($input-docs)"/>
        <xsl:variable name="new-filename" select="item[@name = 'LogNo']/text"/>

        <xsl:for-each select="$old-filename">
            <xsl:result-document href="concat ($new-filename, '.xml')">
                <xsl:copy-of select="."/>
            </xsl:result-document>
        </xsl:for-each>

    </xsl:template>

</xsl:stylesheet>

Edit: for completeness, I've added the two command line prompts that I've attempted. I'm not sure if the path to the input directory should be specified in the stylesheet or in the command line.

 java -jar "C:\path\to\saxon.jar" -it:main -o:"C:\path\to\renamed\XML"  -xsl:"C:\path\to\stylesheet.xslt" 

 java -jar "C:\path\to\saxon.jar" -s:"C:\path\to\input\XML" -o:"C:\path\to\renamed\XML"  -xsl:"C:\path\to\stylesheet.xslt" 
4
  • Is the work done, when you put the "concat ($new-filename, '.xml')" into {}? Commented Nov 14, 2016 at 19:26
  • I'm afraid I don't follow... where would the curly braces go? Commented Nov 14, 2016 at 19:30
  • uL1 is suggesting to use an AVT (w3.org/TR/xslt#attribute-value-templates) so it would look like href="{concat($new-filename, '.xml')}". However, the context of your for-each is going to be a string ($old-filename); maybe you want to select $input-docs instead? Commented Nov 14, 2016 at 20:06
  • I tried adding the curly braces <xsl:result-document href="{concat($new-filename, '.xml')}"> and changing the context of the for-each to <xsl:for-each select="base-uri($input-docs)">, but I'm still getting an error message. Before, the error message said "A sequence of more than one item is not allowed as the first argument of base-uri()". Now the error message says "The context item is absent" Commented Nov 14, 2016 at 20:15

1 Answer 1

0

It often becomes clear where your errors are if you follow the discipline of always declaring the data type of your variables.

For example, it's evident that the declaration of input-docs should have type as="document-node()*". But that's clearly not a valid argument to a call on base-uri().

So it's obvious what's wrong with your code (and indeed, the error message says it clearly). Correcting it is more difficult, because you haven't told us what you want to achieve. But the normal logic would be something like this:

<xsl:template name="main">
    <xsl:variable name="input-docs" 
      select="collection(iri-to-uri(concat($input-dir, '?select=*.xml')))" 
      as="document-node()*"/>
    <xsl:for-each select="$input-docs">
      <xsl:variable name="new-filename" 
                    select="item[@name = 'LogNo']/text"         
                    as="xs:string"/>
      <xsl:result-document href="concat ($new-filename, '.xml')">
        <xsl:copy-of select="."/>
      </xsl:result-document>
    </xsl:for-each>

If you want to get the base-uri of the documents in the collection you should probably be doing this inside the xsl;for-each - but I'm not sure what you actually want to do with the information. (Also, using document-uri() might be more appropriate than base-uri(), but the distinction is subtle).

Sign up to request clarification or add additional context in comments.

10 Comments

I'd like to output one XML file for every input file in the directory, but I want the filename to be based on an element within each file. I'm now getting the error message: Error on line 6 of LogNo.xslt: XTTE0570: A sequence of more than one item is not allowed as the value of variable $input-docs (document-node(), document-node(), ...) A sequence of more than one item is not allowed as the value of variable $input-docs (document-node(), document-node(), ...)
@b00kgrrl, are you sure you have as="document-node()*" (with the asterisk * after document-node()) when you get that error?
When I add the asterisk, I don't get that error any more. I am now able to output one XML file per input file, but the new-filename is not getting picked up. The problem seems to be in the command line. The input directory is not getting picked up. This is what I have: java -jar "C:\path\to\saxon.jar" -it:main -o:"C:\path\to\renamed\XML" -xsl:"C:\path\to\stylesheet.xslt"
If $input-dir is defined as a global stylesheet parameter, then you can/should supply a value for it on the command line e.g as input-dir=file:///my/dir
If I do this at the command line: java -jar C:\path\to\jar -it:main input-dir="C:\path\to\input\XML" -o:"C:\path\to\fixed\XML" -xsl:"C:\path\to\stylesheet.xslt" I get an error: "Output is a directory, but input is not" (The input directory does exist.)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.