XSLT stylesheet parameters in imported stylesheets

2019-04-19 00:30发布

问题:

Is it possible to assign a value to a parameter of an imported stylesheet?

I was expecting something like

<xsl:import ... >
  <xsl:with-param ... 
</xsl:import>

but that is not allowed.

Also tunnel="yes" is forbidden in stylesheet parameters.

回答1:

Try this:

main.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:import href="import.xsl"/>

  <xsl:variable name="param" select="'some-value'"/>

  <xsl:template match="/">
    <xsl:call-template name="foo"/>    
  </xsl:template>

</xsl:stylesheet>

import.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:param name="param" select="'default'"/>

  <xsl:template name="foo">
    <out><xsl:value-of select="$param"/></out>    
  </xsl:template>

</xsl:stylesheet>

An xsl:variable in an importing stylesheet can override an xsl:param in an imported stylesheet, and this effectively sets the value of the parameter.



回答2:

A quick glance at the specs shows that no such construct is permitted:

  • XSLT 1.0: http://www.w3.org/TR/xslt#element-import
  • XSLT 2.0: http://www.w3.org/TR/xslt20/#element-import

In short, href is the only allowed attribute and there is no content allowed in the element's body.

However, if I understand your use case, then you should simply set the parameter in the normal way (using your host language). It shouldn't really matter that it was defined in the imported stylesheet. For example, assume you have this stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:import href="import.xsl"/>
    <xsl:template match="/">
        <xsl:value-of select="$test"/>
    </xsl:template>
</xsl:stylesheet>

Which imports this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="test" select="'default'"/>
</xsl:stylesheet>

...then setting the test parameter in the normal way should just work. Note that you can also "mask" the parameter from the imported sheet if you want to provide a new default value.

So, adding this to the first stylesheet:

<xsl:param name="test" select="'default2'"/>

...would cause it to print default2 (overriding the default from the imported sheet).



回答3:

Maybe this is also helpful:

In XSLT 2.0 one can pass parameters to an overriden template in an imported stylesheet and instantiate it from the overriding template using: <xsl:apply-imports>.

Passing parameters with <xsl:apply-imports> is a feature only of XSLT 2.0 -- this isn't possible in XSLT 1.0.



回答4:

Just to add to lwburk's excellent answer (+1), here's one more example of assigning a value to a parameter in an imported stylesheet.

You wouldn't need to add xsl:param to the main stylesheet; you would just assign the value when you called the stylesheet (on the command line for example).

main.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:import href="import.xsl"/>

  <xsl:template match="/">
    <xsl:call-template name="foo"/>    
  </xsl:template>

</xsl:stylesheet>

import.xsl

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:param name="param" select="'default'"/>

  <xsl:template name="foo">
    <out><xsl:value-of select="$param"/></out>    
  </xsl:template>

</xsl:stylesheet>

example saxon command line (setting new parameter value)

java -cp "saxon9.jar" net.sf.saxon.Transform -s:input.xml -xsl:main.xsl -o:output.xml param="kuba"

output.xml

<out>kuba</out>