Search code examples
xmlxsltxslt-2.0

I am getting this "The system identifier of the principal output file is unknown;" error while using xsl:result-document


I am trying to write some content in a file using xsl:result-document. While compiling the code, I am getting this error

The system identifier of the principal output file is unknown;".

Input:

<?xml version="1.0" encoding="UTF-8"?>
<document>
    <title>This is an example document</title>
    <section>
        <title>This is section one</title>
        <p>This is the content of section one.</p>
    </section>
    <section>
        <title>This is section two</title>
        <p>This is the content of section two.</p>
    </section>
</document>

XSLT processing:

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/document">      
        <xsl:for-each select="section">
            <xsl:result-document href="section{position()}.html">
                <xsl:copy-of select="."/>
            </xsl:result-document>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

Expected Result:

  • section1.html:

    <title>This is section one</title>
    <p>This is the content of section one.</p>
    
  • section2.html:

    <title>This is section two</title>
    <p>This is the content of section two.</p>
    

But I get the error Message:

The system identifier of the principal output file is unknown;

Please guide me where I need to change.
This is the logic, I have tried

<xsl:for-each select="section">
  <xsl:result-document href="section{position()}.html">
    <xsl:copy-of select="."/>
  </xsl:result-document>
</xsl:for-each>

Solution

  • The following code was tested with Saxon-HE 9.9.1.4J from Saxonica. To get exactly the output you specified in your question, change your XSLT-2.0 stylesheet to

    <?xml version="1.0"?>
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
        <xsl:template match="/document">      
            <xsl:for-each select="section">
                <xsl:result-document href="section{position()}.html" omit-xml-declaration="yes">
                    <xsl:copy-of select="*"/>
                </xsl:result-document>
            </xsl:for-each>
        </xsl:template>
    
    </xsl:stylesheet>
    

    Two things were changed:

    • xsl:copy-of was changed from . to * to select only all child elements
    • A new attribute was added to xsl:result-document to omit the XML declaration.

    The outputted files are:

    • section1.html:

      <title>This is section one</title>
      <p>This is the content of section one.</p>
      
    • section2.html:

      <title>This is section two</title>
      <p>This is the content of section two.</p>
      

    This seems to be as desired.

    Relating to your error message a quote from a 2005 response of Michael Kay:

    If you invoke Saxon from the command line without specifying the -o option, the principal output goes to standard out, which has no known URI, so you get this failure. The answer is to specify the -o option. (I've fixed this recently so that if -o is not specified, parents.xml will go in the current directory, if you're executng from the command line - but not if Saxon is called using the Java API).

    My test has been done with the current Java version of Saxon, so it should work now.