Reputation: 17
I am using XSLT 2.0 (with SaxonHE) to transform some XML Schema Documents into a set of text files. Let say I want a different output file for each xs:complexType found in the input XSD, my template will lool like the following
<?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">
<xsl:output method="text" />
<xsl:template match="@*|node()">
<xsl:apply-templates select="node()|@*" />
</xsl:template>
<xsl:template match="xs:complexType[@name]">
<xsl:variable name="fileName" select="concat('target/',@name,'.txt')" />
<xsl:result-document href="{$fileName}"><xsl:value-of select="$fileName"/></xsl:result-document>
</xsl:template>
</xsl:stylesheet>
For any XSD containing at least one element of the xs:complexType, the output I got is correctly produced in the 'target/{$fileName}.txt' and no other file is produced in the process.
My question arises when I run this transformation with a XSD that does not contain any xs:complexType, the processor produces a default, empty xml file whose name is follow ${input_file}.xml where ${input_file} is the name of the input file. (for instance books.xsd is transformed into books.xsd.xml). How to get rid of that default xml file when nothing matches the templates selected by my transformation ?
The processor I use is SaxonHE9, but I got the same result with others.
Upvotes: 0
Views: 1462
Reputation: 163262
Martin has identified the reason: in effect the XSLT 2.0 spec mandates that there is at least one result document, so if no secondary result documents are created then the primary result is created, even if it's empty. It's a horribly convoluted rule but I think some WG members felt it was needed for XSLT 1.0 compatibility.
The primary result has a file name determined by the "base output URI". When you process a whole directory from the command line, then the base output URI for each transformation is formed from the name of the output directory and the final part of the name of the input file.
The XSLT 3.0 spec relaxes this rule. It says (non-normatively):
In previous versions of this specification it was stated that when the raw result of the initial template or function is an empty sequence, a result tree should be produced if and only if the transformation generates no secondary results (that is, if it does not invoke xsl:result-document). This provision is most likely to have a noticeable effect if the transformation produces serialized results, and these results are written to persistent storage: the effect is then that a transformation producing an empty principal result will overwrite any existing content at the base output URI location if and only if the transformation produces no other output. Processor APIs offering backwards compatibility with earlier versions of XSLT must respect this behavior, but there is no requirement for new processor APIs to do so.
Saxon has taken the cautious approach of retaining the 2.0 behaviour for the time being, but it's certainly something worth looking at again.
Upvotes: 1