Project

Profile

Help

Bug #5849

closed

transform_to_file() in PyXslt30Processor not working.

Added by Daniel Haley about 1 year ago. Updated about 1 year ago.

Status:
Closed
Priority:
Low
Category:
Python API
Start date:
2023-01-23
Due date:
% Done:

100%

Estimated time:
Found in version:
12.0
Fixed in version:
12.1
Platforms:

Description

Using Saxon 12 (installed w/pypi) on Python 3.8.

transform_to_file() seems to try to use the output file as input.

If I try the following python without an existing output file "simple_output.xml":

from saxonche import *


def run():
    with PySaxonProcessor(license=False) as proc:
        print(f"Processor version: {proc.version}")
        xsltproc = proc.new_xslt30_processor()
        xsltproc.transform_to_file(source_file=r"try_saxon_input.xml",
                                   stylesheet_file=r"simple.xsl",
                                   output_file=r"simple_output.xml")


for x in range(0, 3):
    run()

I get the following console output (I get this 3 times, but only including once for brevity. Also, I'm running this in PyCharm.):

Processor version: SaxonC-HE 12.0 from Saxonica
Error 
   I/O error reported by XML parser processing simple_output.xml. Caused by
  java.io.FileNotFoundException: C:\Users\Dan Haley\Desktop\try_saxon\simple_output.xml (The
  system cannot find the file specified)

If I create a file named "simple_output.xml" with the content <foo/>, I don't get an exception but this is what "simple_output.xml" looks like:

<foo processed="1 2 3"/>

So it appears it's using the output as input.

Here's my XSLT if needed to reproduce:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" expand-text="yes">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:mode on-no-match="shallow-copy"/>
    
    <xsl:template match="/*">
        <xsl:copy>
            <xsl:attribute name="processed" select="let $tokens := tokenize(@processed) 
                return string-join(($tokens,count($tokens)+1),' ')"/>
            <xsl:apply-templates select="@* except @processed|node()"/>
        </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

As a work-around, I'm first compiling the stylesheet and using the transform_to_file() method from PyXsltExecutable.


Files

simple.xsl (599 Bytes) simple.xsl Daniel Haley, 2023-01-23 18:44
try_saxon_input.xml (233 Bytes) try_saxon_input.xml Daniel Haley, 2023-01-23 18:44
try_saxonche_simple.py (439 Bytes) try_saxonche_simple.py Daniel Haley, 2023-01-23 18:44
Actions #1

Updated by O'Neil Delpratt about 1 year ago

Thanks for reporting this issue and sending us the repo. I managed to reproduced the problem and investigating it now.

As a workaround I was able to get the correct output using the PyXsltExecutable which is also recommended as a feature rich XSLT 3.0 API instead of executing the stylesheets with the 'one-shot' methods on the PyXsltTransformer:

from saxonche import *


def run():
    with PySaxonProcessor(license=False) as proc:
        print(f"Processor version: {proc.version}")
        xsltproc = proc.new_xslt30_processor()

        executable = xsltproc.compile_stylesheet(stylesheet_file=r"simple.xsl")

        executable.apply_templates_returning_file(source_file=r"try_saxon_input.xml", output_file=r"simple_output.xml")


for x in range(0, 3):
    run()

This gave me the output:

<?xml version="1.0" encoding="UTF-8"?>
<doc processed="1" attr="some attr"><?pi test?>
   <test>This <x>is</x> a test.</test>
   <!--comment test-->
   <ol>
      <li>one</li>
      <li>two</li>
      <li>three</li>
   </ol>
</doc>
Actions #2

Updated by Daniel Haley about 1 year ago

Thanks O'Neil. I'm also able to use the .transform_to_file() method from the PyXsltExecutable.

Is there any reason to use .apply_templates_returning_file() over .transform_to_file()?

Thanks again!

Actions #3

Updated by O'Neil Delpratt about 1 year ago

Oh yes I forgot about transform_to_file. You can use that method.

The apply_templates_returning_file does not set the global context item for the transformation. If that is required use the transform_to_file or call set_global_context_item before calling apply_templates_returning_file.

Actions #4

Updated by O'Neil Delpratt about 1 year ago

  • Category set to Python API
  • Status changed from New to Resolved
  • Assignee set to O'Neil Delpratt
  • % Done changed from 0 to 100
  • Found in version set to 12.0

This bug issue has been resolved. The PyXslt30Processor.transform_to_file has now been corrected and tested.

Fix available in the next maintenance release.

Actions #5

Updated by O'Neil Delpratt about 1 year ago

  • Status changed from Resolved to Closed
  • Fixed in version set to 12.1

Bug fixed applied in the SaxonC 12.1 maintenance release.

Please register to edit this issue

Also available in: Atom PDF