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

Mik*_*ike 7 xml xslt templates

可以通过参数将XML传递给XSL模板吗?例如,下面我有模板body调用模板test1,它通过参数传递一些XML var1.然后我尝试a使用XPATH 步行到节点

<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>
Run Code Online (Sandbox Code Playgroud)

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

Dim*_*hev 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>
Run Code Online (Sandbox Code Playgroud)

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

W3C XSLT 1.0规范:

11.1结果树片段

变量在表达式语言中引入了额外的数据类型.此附加数据类型称为结果树片段.变量可以绑定到结果树片段,而不是四种基本XPath数据类型之一(字符串,数字,布尔值,节点集).结果树片段表示结果树的片段.结果树片段被等效地​​处理为仅包含单个根节点的节点集.但是,结果树片段上允许的操作是节点集上允许的操作的子集.仅当在字符串上允许该操作时才允许对结果树片段执行操作(对字符串的操作可能涉及首先将字符串转换为数字或布尔值).特别是,不允许使用/,//[]运算符在结果树片段上.当对结果树片段执行允许的操作时,它的执行方式与在等效节点集上的操作完全相同.

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

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

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

方案:

找到您的XSLT处理器供应商提供的此扩展功能的确切名称.

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

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

MSXML和.NET XslCompiledTransform,XslCompiledTransform:

xmlns:vendor="urn:schemas-microsoft-com:xslt"
Run Code Online (Sandbox Code Playgroud)

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

 xmlns:vendor="http://xml.apache.org/xalan"
Run Code Online (Sandbox Code Playgroud)

撒克逊人(6.x):

 xmlns:vendor="http://icl.com/saxon"
Run Code Online (Sandbox Code Playgroud)

Altova公司:

 xmlns:vendor="http://www.altova.com/xslt-extensions"
Run Code Online (Sandbox Code Playgroud)

所有实现EXSLT的XSLT处理器:

xmlns:vendor="http://exslt.org/common"
Run Code Online (Sandbox Code Playgroud)

如果它的主体<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>
Run Code Online (Sandbox Code Playgroud)

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

<b xmlns:xsl="http://www.w3.org/1999/XSL/Transform">foo</b>
Run Code Online (Sandbox Code Playgroud)

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

  • 感谢Dimitre的全面回应.我将联系我的供应商,看看是否可以进行此类扩展. (2认同)