3
votes

I'm trying to use XSLT conditional includes/static parameters with Saxon/C HE, but I'm getting the following error:

Error 
  Parameter $some_param cannot be supplied dynamically because it is declared as static

To reproduce, I've used an example from a couple of answers I added a few years ago. (Here and here.)

In both of those answers I used the java version 9.7 of Saxon-HE from the command line without issue. I also tested again using java version 10.5 of HE from the command line. Again no issues.

However, if I try to run this example from Python (3.8) using Saxon/C 1.2.1 running with Saxon-HE 9.9.1.5C I get the error above.

Does anyone else have experience with static params in XSLT 3.0 and Saxon/C (especially with Python) that can provide guidance?

Test code...

XML Input (test.xml)

<doc>
    <foo/>
</doc>

Python

import saxonc

saxon_proc = saxonc.PySaxonProcessor(license=False)

print(f"Processor version: {saxon_proc.version}")

xsltproc = saxon_proc.new_xslt30_processor()

# noinspection PyArgumentList
xsltproc.set_parameter("inc2", saxon_proc.make_boolean_value(True))

results = xsltproc.transform_to_string(source_file="test.xml", stylesheet_file="test_main.xsl")

if results:
    print(results)

saxon_proc.release()

Main XSLT 3.0 (test_main.xsl)

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:param name="inc1" as="xs:boolean" select="false()" 
        static="yes" required="no"/>
    <xsl:param name="inc2" as="xs:boolean" select="false()" 
        static="yes" required="no"/>

    <xsl:include href="test_inc1.xsl" use-when="$inc1"/>
    <xsl:include href="test_inc2.xsl" use-when="$inc2"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

First possible included XSLT 3.0 (test_inc1.xsl)

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:template match="foo">
        <xsl:copy>INCLUDE FILE 1!!!</xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

Second possible included XSLT 3.0 (test_inc2.xsl)

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:template match="foo">
        <xsl:copy>INCLUDE FILE 2!!!</xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>

Expected Output (this is what I get using java Saxon-HE from the command line (shown below))

<doc>
   <foo>INCLUDE FILE 2!!!</foo>
</doc>

Actual Output

Processor version: Saxon/C 1.2.1 running with Saxon-HE 9.9.1.5C from Saxonica
Error 
  Parameter $inc2 cannot be supplied dynamically because it is declared as static

Working command line:

java -cp "saxon-he-10.5.jar" net.sf.saxon.Transform -s:"test.xml" -xsl:"test_main2.xsl" inc2="true"

I should also note that I get the same error when trying to use a shadow attribute (command line still works using the command line arg inc_number="2"):

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="inc_number" as="xs:string" select="'1'" static="yes" required="no"/>

    <xsl:include _href="test_inc{$inc_number}.xsl"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
</xsl:stylesheet>
1
I think in the Java API to set a static parameter you need to do that before compilation on XsltCompiler. I am not sure how it is supposed to work in the C++ or Python API where the XsltCompiler doesn't seem to be exposed as a class. Perhaps, after xsltproc = saxon_proc.new_xslt30_processor() and xsltproc.set_parameter("inc2", saxon_proc.make_boolean_value(True)) call the compile methods first e.g. xsltproc.compile_stylesheet(stylesheet_file="test_main.xsl"). I haven't tested whether that improves things.Martin Honnen
The C++ and Java glue code saxonica.plan.io/projects/saxon/repository/he/revisions/master/… seems to make some effort to deal with static params but I am not sure which code path from Python leads to its use. Hopefully you will get an answer from Saxonica later.Martin Honnen
Thanks @MartinHonnen using .compile_stylesheet() was a good suggestion, but unfortunately I still get the same error.Daniel Haley
Hi, unfortunately it is not currently possible to set the static parameters in the current version, but I have added this feature which will be available in the next release.ond1
Thanks @ond1, I will keep an eye out for the next release. In the meantime I'll just use the less ideal method of using a different main XSLT; one for each include.Daniel Haley

1 Answers

0
votes

From @ond1 (O'Neil Delpratt - Saxonica)...

Hi, unfortunately it is not currently possible to set the static parameters in the current version, but I have added this feature which will be available in the next release.

So until setting static params is supported, I'm going to use two different "main" XSLTs; each one including the desired stylesheet. Another option is to transform the XSLT before executing it, but the two separate "main"'s is what I'm already doing anyway.

Also, once setting static params is supported I'll update this answer with a full working example.