繁体   English   中英

如何在xsl:apply-templates中使用XSL变量?

[英]How to use XSL variable in xsl:apply-templates?

我对xsl:apply-templates的调用相当复杂:

<xsl:apply-templates select="columnval[@id 
                                       and not(@id='_Name_') 
                                       and not(@id='Group') 
                                       and not(@id='_Count_')]"/>

该表达式在其他地方重用,如下所示:

<xsl:apply-templates select="someothernode[@id 
                                           and not(@id='_Name_') 
                                           and not(@id='Group') 
                                           and not(@id='_Count_')]"/>

我想以某种方式概括它,所以我可以定义一次并在其他地方重用它。 但是,这似乎不起作用:

<xsl:variable name="x">@id and not(@id='_Name_') and not(@id='Group') and not(@id='_Count_')</xsl:variable>
<xsl:apply-templates select="columnval[$x]"/>
<xsl:apply-templates select="someothernode[$x]"/>

有没有更好/不同的方式这样做? 我想要的是在xsl:apply-templates(其中一些从不同的子节点中选择)的多个不同调用中重用xpath表达式。

这将在客户端应用程序中使用,因此我不能使用任何扩展或切换到XSLT 2。 :(

谢谢。

您无法在XSLT中动态构造XPath(至少不是XSLT 1.0)。 但是您可以使用模板模式轻松完成您尝试执行的操作:

<xsl:apply-templates select="columnval" mode="filter"/>
<xsl:apply-template select="someothernode" mode="filter"/>

...

<!-- this guarantees that elements that don't match the filter don't get output -->
<xsl:template match="*" mode="filter"/>

<xsl:template match="*[@id and not(@id='_Name_') and not(@id='Group') and not(@id='_Count_')]" mode="filter">
   <xsl:apply-templates select="." mode="filtered"/>
</xsl:template>

<xsl:template match="columnval" mode="filtered">
   <!-- this will only be applied to the columnval elements that pass the filter -->
</xsl:template>

<xsl:template match="someothernode" mode="filtered">
   <!-- this will only be applied to the someothernode elements that pass the filter -->
</xsl:template>

重构@Robert Rossney和@Tomalak

<xsl:apply-templates select="columnval" mode="filter"/> 
<xsl:apply-templates select="someothernode" mode="filter"/> 

<xsl:template match="*" mode="filter">
   <xsl:param name="pFilter" select="'_Name_|Group|_Count_'"/> 
   <xsl:apply-templates select="self::*
                                [not(contains( 
                                        concat('|',$pFilter,'|'),  
                                        concat('|',@id,'|')))
                                 and @id]"/> 
</xsl:template> 

我会看一下使用xslt的扩展名。 我不认为你可以在“标准”xslt中做到这一点。

这个扩展可以做你想要的: http//www.exslt.org/dyn/functions/evaluate/index.html

使用扩展名exsl:nodeset,您可以创建一个接受节点集$ x的命名模板,并根据您的静态谓词返回已过滤的节点集。

您还可以在XSLT 2.0中定义一个函数。

怎么样:

<xsl:variable name="filter" select="_Name_|Group|_Count_" />

<xsl:apply-templates select="columnval" mode="filtered" />
<xsl:apply-templates select="someothernode" mode="filtered" />

<xsl:template match="someothernode|columnval" mode="filtered">
  <xsl:if test="not(contains(
    concat('|', $filter,'|'), 
    concat('|', @id,'|'), 
  ))">
    <!-- whatever -->
  </xsl:if>
</xsl:template>

你可以让$filter一个param,然后从外面传递它。

您不能做的(正如您所注意到的)是使用变量来存储XPath表达式。

XSLT 1.0和XSLT 2.0都不支持动态评估。

一种方法是在XSLT 2.0中使用<xsl:function>或在XSLT 1.0中使用<xsl:call-template>

 <xsl:function name="my:test" as="xs:boolean">
  <xsl:param name="pNode" as="element()"/>

  <xsl:variable name="vid" select="$pNode/@id"/>

  <xsl:sequence select=
  "$vid and not($vid=('_Name_','Group','_Count_')"/>
 </xsl:function>

然后你可以使用这个功能

<xsl:apply-templates select="columnval[my:test(.)]"/>

当然,您可以按照Robert Rossney的建议在特定的匹配模式中指定测试 ,这可能是最好的方法。

如果您需要动态定义要使用的过滤函数,一个强大的工具是FXSL库,它在XSLT中实现高阶函数(HOF)。 HOF是接受其他函数作为参数的函数,可以返回函数作为结果。

使用此方法,您可以动态确定并将my:test()作为参数传递给执行my:test()的函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM