0

How it is possible to overwrite an existing (XML) file with XSLT? Currently, using <xsl:result-document/> I get the following ERROR

Cannot write to a URI that has already been read

I found an advice to delete the file before, but they don't explain how. I wonder if there should be a simpler solution to do this.

Here is the sample code. I am using Saxon 9.8.0.12 in Oxygen XML editor 20.1

<xsl:variable name="process">
    <xsl:apply-templates mode="process" select="doc($processedFile)"/>
</xsl:variable>

    <xsl:template match="/">        
        <xsl:result-document href="{$processedFile}" indent="yes" method="xml">
            <xsl:copy-of select="$process"/>
        </xsl:result-document>
    </xsl:template>
o-sapov
  • 320
  • 2
  • 13
  • As you mention oXygen, I think you could consider using XProc with a `p:xslt` step, that way you should be able to use the same file for input and output and XProc would allow you to overwrite that file with one processing step. oXygen has support for XProc. With a single XSLT transformation it is not possible to write to a URI that has also been read. – Martin Honnen Jun 06 '19 at 09:55
  • thanks. I'll check that out. – o-sapov Jun 06 '19 at 12:08

1 Answers1

3

It's a rule in the XSLT specification that you can't read from a URI and then write to the same URI within the same transformation. The reason for this rule is that the order of operations in XSLT is undefined; the optimizer might re-order things so the read happens after the write. (In Saxon-EE, xsl:result-document uses a separate thread, so this is not an idle threat: things will often happen in a different order from what you might naively expect.)

You can circumvent the rule, at your own risk, by using a trivially different URI that refers to the same underlying resource; for example add a redundant /./ step to the path, or a query part ?dummy=yes.

Be aware of course, that if your transformation fails, you have wiped out the input.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164