是否可以在xslt样式表中使用Dynamic xPath表达式?

时间:2009-10-11 19:26:51

标签: xml xslt ant xpath

我想在xpath表达式中使用xslt参数的值。具体而言,作为not()表达式<xsl:if调用的一部分。

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- my_param contains a string '/foo/bar', passed in from ant -->
    <!-- the 'no' is just a default value -->
    <xsl:param name="my_param">no</xsl:param>
    <xsl:variable name="var_myparam" select="$my_param" />
    <!-- ... -->

    <!-- this works -->
    <xsl:if test="not(/foo/bar)" /> <!-- expression returns boolean true -->
        <!-- ... -->
    </xsl:if>

    <!-- I can't figure out how to do this the right way -->
    <!-- None of these appear to work -->
    <xsl:if test="not($var_myparam)" /> <!-- expression returns boolean false -->
        <!-- ... -->
    </xsl:if>       
    <xsl:if test="not({$var_myparam})" /> <!-- complains Required attribute 'test' is missing -->
        <!-- ... -->
    </xsl:if>       
    <xsl:if test="not({$myparam})" />   <!-- complains Required attribute 'test' is missing -->
        <!-- ... -->
    </xsl:if>       
    <xsl:if test="not($myparam)" />     <!-- expression returns boolean false -->
        <!-- ... -->
    </xsl:if>       

</xsl:transform>

我有点不清楚在xslt样式表中创建动态xpath表达式的正确语法是什么。对于参数,变量以及两者的扩展方式之间的差异,我也有点模糊。例如,有了参数,我知道有时我需要括号,有时我不需要。

<!-- when creating an element, it seems I need brackets -->
<xsl:element name="{$my_param}" />

<!-- when selecting an element value for the output stream, no brackets are needed -->
<xsl:value-of select="$my_param"/>

非常感谢任何一般/特定的帮助。

3 个答案:

答案 0 :(得分:5)

结帐http://www.exslt.org/。 具体来看动态:评估模块。

答案 1 :(得分:4)

XSLT不支持XPath的动态评估 - 这就是为什么你需要使用像EXSLT evaluate这样的扩展函数来实现它。

如果您不想使用扩展函数(并且有充分的理由不这样做),另一种可能性是在执行转换之前查询输入文档的DOM,并将节点集作为参数传递给转换

修改

关于那些花括号:这些是属性值模板(AVT)。这些在XSLT转换中在语义上是等效的:

<foo>
   <xsl:attribute name="bar">
      <xsl:value-of select="XPathExpression"/>
   </xsl:attribute>
</foo>

<foo bar="{XPathExpression}"/>

第二个只是第一个的快捷方式。

关于变量和参数:从语法上讲,变量和参数之间没有区别;在XPath表达式中引用$foo的任何地方,只要fooxsl:variable定义xsl:param,它就会一样。

两者之间的区别在于它们是如何填充的。变量填充在xsl:variable声明中。使用xsl:param在命名模板中声明参数,但是使用xsl:with-param,使用<xsl:call-template name="foo"> <xsl:with-param name="bar" select="XPathExpression"/> </xsl:call-template> <xsl:template name="foo"> <xsl:param name="bar"/> ... 调用命名模板时填充它们,例如:

xsl:stylesheet

这是一个很奇怪的例外,它是<xsl:stylesheet ... <xsl:param name="system-date"/> ... 的孩子的参数。没有办法在变换中填充这些参数;那些是外部填充的,由任何(特定于环境)机制调用转换。

一个非常常见的用例是弥补XSLT没有系统日期功能的事实。所以你会看到类似的东西:

XsltArgumentList args = new XsltArgumentList();
args.AddParam("system-date", "", DateTime.Now.ToString("s"));
xslt.Transform(input, args, result);

然后,在调用转换时,就像这样(在C#中):

{{1}}

答案 2 :(得分:3)

尝试一些变体:

<xsl:if test="not($var_myparam = 'no'))">
</xsl:if>

问题在于XPath如何评估布尔值。在XPath中,任何非空字符串都将计算为true。结帐write-up about xpath booleans

至于你的其他问题......变量和参数在XPath表达式中的作用相同。两者都以$ var的形式引用。

对于名为“select”的任何XSLT属性,您不需要括号。括号用于所谓的“属性值模板”。当XSLT期望字符串时,您可以使用它们,例如:

<xsl:template match="name-a">
  <xsl:variable name="old-name" select="name(.)" />
  <name-b old-name="{$old-name}" new-attribute="hello"  />
</xsl:template>

XSLT spec talks about AVTsthis page也是如此。