XSL,使用XML作为模板的参数

时间:2010-09-19 18:25:48

标签: xml xslt templates

通过参数将XML传递给XSL模板是否可以?例如,下面我有模板body调用模板test1,它通过参数var1传递一些XML。然后我尝试使用XPATH

走到节点a
<xsl:template name="test1">
    <xsl:param name="var1" />
    <fo:block>
        <xsl:value-of select="$var1/a" />
    </fo:block>
</xsl:template>

<xsl:template name="body">
    <xsl:call-template name="test1">
        <xsl:with-param name="var1" >
            <a>foo</a>
        </xsl:with-param>
    </xsl:call-template>
</xsl:template>

问题是,这导致我的XSL解释器失败并出现无用的错误消息。我被迫使用一个封闭的源供应商系统来生成文档,所以我无法调试。但在我进一步研究之前,我正在寻找确认这是XSL的有效用法。

1 个答案:

答案 0 :(得分:14)

<xsl:template name="body"> 
    <xsl:call-template name="test1"> 
        <xsl:with-param name="var1" > 
            <a>foo</a> 
        </xsl:with-param> 
    </xsl:call-template> 
</xsl:template>

由于臭名昭着的RTF(结果树片段)类型,传递给模板的$var1参数在XSLT 1.0 / XPath 1.0中几乎无法使用。

来自W3C XSLT 1.0 spec 。:

  

11.1结果树片段

     

变量引入了额外的数据类型   表达语言。这个   其他数据类型称为结果   树片段。变量可以绑定   到结果树片段而不是   四种基本XPath数据类型之一   (字符串,数字,布尔值,节点集)。一个   结果树片段代表一个   结果树的片段。结果   树片段被等同地处理   到一个只包含一个的节点集   单根节点。然而   结果树上允许的操作   片段是那些的子集   允许在节点集上。 <强>一种   结果允许操作   树片段仅在该操作时   将被允许​​在一个字符串(   对字符串的操作可能涉及   首先将字符串转换为   数字或布尔值)。特别是它   不允许使用///,   和结果树上的[]运算符   片段。当允许的操作   在结果树上执行   片段,它完全按照   它会相当于   节点集。

     

复制结果树片段时   进入结果树(见[11.3使用   变量和参数的值   使用xsl:copy-of]),然后是所有节点   这是根节点的子节点   添加等效节点集   序列到结果树。

     

表达式只能返回值   输入结果树片段   引用类型结果的变量   树片段或调用扩展   返回结果树的函数   片段或获取系统属性   其值为结果树片段。

为了避免这种严重的设计决策,几乎每个XSLT处理器都有自己的扩展功能,通常名为xxx:node-set(),其中xxx前缀必须绑定到供应商定义的命名空间。

<强>解决方案

确切了解XSLT处理器供应商提供的此扩展功能的名称。

或者,如果您的XSLT处理器支持EXSLT,请使用EXSLT定义的 exsl:node-set() 扩展功能。

以下是一些特定于供应商的命名空间:

MSXML和.NET XslCompiledTransform,XslCompiledTransform

xmlns:vendor="urn:schemas-microsoft-com:xslt"

Xalan (注意,函数名称是:xxx:nodeset()!):

 xmlns:vendor="http://xml.apache.org/xalan"

撒克逊(6.x):

 xmlns:vendor="http://icl.com/saxon"

<强>的Altova:

 xmlns:vendor="http://www.altova.com/xslt-extensions"

所有实施EXSLT的XSLT处理器

xmlns:vendor="http://exslt.org/common"

如果<xsl:param>的主体不是动态构造的,可以避免

xxx:node-set()以下列方式运作:

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

 <xsl:variable name="vrtfparamXML">
   <a>
     <b>foo</b>
   </a>
 </xsl:variable>

 <xsl:variable name="vparamXML" select=
 "document('')/*/xsl:variable
                [@name='vrtfparamXML']/*"/>

 <xsl:template match="/">
   <xsl:copy-of select="$vparamXML/b"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于任何XML文档(未使用)时,结果是RTF的通缉子

<b xmlns:xsl="http://www.w3.org/1999/XSL/Transform">foo</b>

注意:XSLT 2.0 / XPath 2.0摆脱了RTF“类型”,并且有一个访问临时树并使用XPath 2.0的全部功能导航它们没有任何问题