Re: [xsl] how to make a log file in XSLT?

Subject: Re: [xsl] how to make a log file in XSLT?
From: "Michael Kay mike@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 12 Mar 2023 20:22:23 -0000
The rule that you can't read and write to the same URI is there because in
XSLT order of evaluation is undefined, so it would be undefined whether the
read or the write comes first.

In terms of your specific example, it's undefined whether the global variable
(that uses doc()) has already been evaluated when you try to open the file for
writing using xsl:result-document. If it hasn't, you could run into some kind
of interlock that prevents the underlying file being opened twice, or doc()
could read file that's in an undefined state.

I would recommend using xsl:message for this, with a message listener that
directs the output accordingly.

Alternatively, use the EXPath file module - this allows you to read and write
the same file, but any resequencing of operations by the optimizer is liable
to cause trouble.

Michael Kay
Saxonica

> On 12 Mar 2023, at 20:11, Jean-Luc Chevillard jeanluc.chevillard@xxxxxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
> Dear list members,
>
> I have been wondering for a long time whether there was a method for
> automatically recording some elements of information every time I run
> a given script.
>
> As a minimum example, I would start with an empty file
> +++++++++++++++
> <?xml version="1.0" encoding="UTF-8"?>
> <log>
> </log>
> +++++++++++++++++++++++
>
> After running the script once, the file would become
> +++++++++++++++
> <?xml version="1.0" encoding="UTF-8"?>
> <log>
>   <entry>[2023-03-12 (19:53)]</entry>
> </log>
> +++++++++++++++++++++++
>
> After running the script a second time, one hour later, the file would
become
> +++++++++++++++
> <?xml version="1.0" encoding="UTF-8"?>
> <log>
>   <entry>[2023-03-12 (20:53)]</entry>
>  <entry>[2023-03-12 (19:53)]</entry>
> </log>
> +++++++++++++++++++++++
>
> I have just tried doing this by applying the script at the bottom of
> this message (in which "copy.xslt" is the identity transform) to a
> base file, but as I expected, I obtained an error message stating:
>
> System ID: C:\JLC\XML_tests\cEnAvaraiyam\log_book_experiment.xslt
> Scenario: 4a_log_experiment
> XML file: C:\JLC\XML_tests\cEnAvaraiyam\cEnA_MSS_rectangles_chart.xml
> XSL file: C:\JLC\XML_tests\cEnAvaraiyam\log_book_experiment.xslt
> Engine name: Saxon-PE 11.4
> Severity: fatal
> Problem ID: XTRE1500
> Description: Cannot read a document that was written during the same
> transformation:
> file:/C:/JLC/XML_tests/cEnAvaraiyam/experimental_log_book.xml
> Start location: 17:63
> Length: 1
> URL: http://www.w3.org/TR/xslt20/#err-XTRE1500
>
> Is there a method for obtaining the desired result by using XSLT?
>
> Thanks for your answers
>
> -- Jean-Luc
>
> ++++++++++++++++++++++++++++
> log_book_experiment.xslt
> ++++++++++++++++++++++++++++
> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>    xmlns:xs="http://www.w3.org/2001/XMLSchema";
>    exclude-result-prefixes="xs"
>    version="2.0">
>
>    <xsl:import href="copy.xslt"/>
>
>    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
>
>    <xsl:variable name="TIME_STAMP"
> select="concat('[',format-date(current-date(), '[Y]-[M02]-[D02]'), '
> (', format-time(current-time(), '[H]:[m]'), ')]')"/>
>
>    <xsl:variable name="Log_file_name"
select="'experimental_log_book.xml'"/>
>
>    <xsl:variable name="current_log_content"
select="document($Log_file_name)"/>
>
>    <xsl:variable name="new_log_content">
>        <log>
>            <entry><xsl:value-of select="$TIME_STAMP"/></entry>
>            <xsl:for-each select="$current_log_content//entry">
>                <xsl:copy-of select="."/>
>            </xsl:for-each>
>        </log>
>    </xsl:variable>
>
>    <xsl:template match="/">
>        <xsl:result-document href="{$Log_file_name}">
>            <xsl:copy-of select="$new_log_content"></xsl:copy-of>
>        </xsl:result-document>
>        <xsl:apply-templates select="root"/>
>    </xsl:template>
>
>
> </xsl:stylesheet>
> +++++++++++++++++++++++++++++++++

Current Thread