pythonxsltxslt-1.0saxon-c

XSLT transformation using a xdm_node returns an error - Using Saxon-HE 9.9.1.5C with Python 3.9


I have a problem with Saxon HE in Python. When I parse a XML file I get as return a type PyXdmNode.

After that I want to do an XSLT transformation and use the method transform_to_value(xdm_node= ... ).

When I do this, I get the following error:

... File "saxonc.pyx", line 781, in saxonc.PyXsltProcessor.transform_to_value self.setSourceFromXdmNode(value) AttributeError: 'saxonc.PyXsltProcessor' object has no attribute 'setSourceFromXdmNode' ...

What am I doing wrong? It almost looks like in Python an XSLT transformation only works with transform_to_value(source_file = '...' ).

Python File:

import saxonc

proc = saxonc.PySaxonProcessor(license=False)
print(f"\n{proc.version}")
xml = proc.parse_xml(xml_file_name="Test_xml.xml")
# <class 'saxonc.PyXdmNode'>
print(type(xml))

xslt_proc = proc.new_xslt_processor()
xslt_proc.compile_stylesheet(stylesheet_file="Test_xslt.xslt")

# Error line
xml_trans_1 = xslt_proc.transform_to_value(xdm_node= xml)

# All the same only different **kwargs - Works fine
xml_trans_2 = xslt_proc.transform_to_value(source_file= "Test_xml.xml")

XML File - Test_xml.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<TEST Id="T-1">
    <FOO/>
</TEST>

XSLT File - Test_xslt.xslt:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"   xmlns:xsl= "http://www.w3.org/1999/XSL/Transform">
    
    <xsl:output method="xml" indent="yes" />
    
    
    <xsl:template match="@*|node()"> 
        <xsl:copy> 
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="FOO"> 
        <xsl:element name="BAR">
            <xsl:attribute name="Id">
                <xsl:value-of select="'Hello World'"/>
            </xsl:attribute>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet> 

Result:

<TEST Id="T-1">
   <BAR Id="Hello World"/>
</TEST>

Solution

  • With SaxonC 11.3, you can use apply_templates_returning_value(xdm_value = xml) e.g.

    from saxonc import *
    
    with PySaxonProcessor(license=False) as processor:
        print("Test SaxonC on Python")
        print(processor.version)
    
        xml_doc = processor.parse_xml(xml_file_name = 'sample1.xml')
    
        xslt30_processor = processor.new_xslt30_processor()
    
        xslt30_transformer = xslt30_processor.compile_stylesheet(stylesheet_file = 'sheet1.xsl')
    
        result = xslt30_transformer.apply_templates_returning_value(xdm_value = xml_doc)
    
        print(result)
    

    Some other API methods have been changed/fixed, see https://saxonica.plan.io/issues/5446, but I think we have to wait for 11.4 to use the fix.