Search code examples
pythonsaxon-c

saxonche 12.4.2: passing an array as parame to PyXslt30Processor leads to AttributeError: 'saxonche.PyXdmArray' object has no attribute 'derivedaptr'


I'm trying to pass an array to a stylesheet:

`

with PySaxonProcessor(license=False) as proc:
    print(proc.version)
    xsltproc = proc.new_xslt30_processor()
    xsltproc.set_cwd(os.getcwd())
    executable = xsltproc.compile_stylesheet(stylesheet_file="cat.xsl")

    value = proc.make_array([proc.make_integer_value(i) for i in [8,9,10]])
    print(value)
    executable.set_parameter("values", value)

    result = executable.apply_templates_returning_string(source_file="person.xml")
    print(result)

`

However, this results in:

    SaxonC-HE 12.4.2 from Saxonica
    [8,9,10]
    Traceback (most recent call last):
        File "/Users/menzowi/Temp/saxontest/saxon.py", line 22, in <module>
        executable.set_parameter("values", value)
     File "python_saxon/saxonc.pyx", line 1958, in saxonche.PyXsltExecutable.set_parameter
     AttributeError: 'saxonche.PyXdmArray' object has no attribute 'derivedaptr'

I expected a result an XML document with each of the values in the array multiplied by 3. Using this stlesheet:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
    <xsl:param name="values" select="(2, 3, 4, 5)"/>
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="*">
        <output>
            <xsl:for-each select="$values">
                <out>
                    <xsl:value-of select=". * 3"/>
                </out>
            </xsl:for-each>
        </output>
    </xsl:template>
</xsl:stylesheet>

Solution

  • Your (XSLT) code seems to try to process a sequence of (integer) values; for that I suggest you use a PyXdmValue, as shown below:

    from saxonche import PySaxonProcessor, PyXdmValue
    
    with PySaxonProcessor(license=False) as proc:
        print(proc.version)
        xsltproc = proc.new_xslt30_processor()
        executable = xsltproc.compile_stylesheet(stylesheet_file="sheet2.xsl")
    
        result = executable.apply_templates_returning_string(source_file="sample1.xml")
        print(result)
    
        value = PyXdmValue()
    
        for n in [8,9,10]:
            value.add_xdm_item(proc.make_integer_value(n))
    
        print(value)
        executable.set_parameter("values", value)
    
        result = executable.apply_templates_returning_string(source_file="sample1.xml")
        print(result)
    

    As for passing an array, that seems to be a bug in SaxonC: https://saxonica.plan.io/issues/6335. As a workaround, you could pass the array to XPath evaluation calling fn:transform e.g.

    value = saxon_proc.make_array([saxon_proc.make_integer_value(i) for i in [8,9,10]])
    
    xpath_processor = saxon_proc.new_xpath_processor()
    
    xpath_processor.set_parameter('values', value)
    
    xdm_result = xpath_processor.evaluate("""
      transform(
        map { 
          'stylesheet-location' : 'sheet1.xsl',
          'delivery-format' : 'serialized', 
          'stylesheet-params' : map { QName('', 'values') : $values } 
        }
      )?output
    """)
    
    print(xdm_result)
    

    Sample stylesheet processing an array (of integers) instead of a sequence is as follows:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="3.0"
        exclude-result-prefixes="#all">
        <xsl:param name="values" as="array(*)" select="[2, 3, 4, 5]"/>
        <xsl:output method="xml" indent="yes"/>
        <xsl:template name="xsl:initial-template">
            <output>
                <xsl:for-each select="$values?*">
                    <out>
                        <xsl:value-of select=". * 3"/>
                    </out>
                </xsl:for-each>
            </output>
        </xsl:template>
    </xsl:stylesheet>