将模板参数命名为XPath以进行模板匹配

时间:2013-01-19 17:40:09

标签: xslt xpath xslt-1.0

是否可以将命名模板的参数指定为另一个模板中的匹配模式?

在这里,如果我尝试调用'摘录'模板并将XPath作为'path'参数传递,我会收到错误:

<xsl:template name="excerpt">
    <xsl:param name="path" select="''" />
    <xsl:apply-templates select="$path" />
</xsl:template>

<xsl:template match="$path">
    <article class="newsarticle">
        <h2><a href="{$root}/news/view/{title/@handle}"><xsl:value-of select="title" /></a></h2>
        <xsl:copy-of select="excerpt/node()" />
    </article>
</xsl:template>

我可以用<xsl:for-each>完成它,但我想知道是否有一个很好的解决方案,使用与上述方法类似的东西。

修改:这是我正在尝试完成的工作,使用<xsl:for-each>

<xsl:template name="excerpt">
    <xsl:param name="path" select="''" />
    <xsl:for-each select="$path">
        <article class="newsarticle">
            <h2><a href="{$root}/news/view/{title/@handle}"><xsl:value-of select="title" /></a></h2>
            <xsl:copy-of select="excerpt/node()" />
        </article>
    </xsl:for-each>
</xsl:template>

修改:调用模板的示例:

<xsl:call-template name="excerpt">
    <xsl:with-param name="path" select="path/to/nodeset" />
</xsl:call-template>

2 个答案:

答案 0 :(得分:1)

感谢您提供更多信息。这里要做的一个澄清是,在call-template那里,你传递的是节点集,而不是路径。在没有复杂的解析逻辑或扩展函数的情况下,路径的字符串值在XSLT 1.0中几乎毫无价值。

有一种方法可以做你想做的事情,只是与你想象的方式略有不同。您只需要使用具有通用match值和mode值的模板,就像这样。

<xsl:template name="excerpt">
    <xsl:param name="items" select="''" />
    <xsl:apply-templates select="$items" mode="excerptItem" />
</xsl:template>

<xsl:template match="node() | @*" mode="excerptItem">
    <article class="newsarticle">
        <h2>
          <a href="{$root}/news/view/{title/@handle}">
             <xsl:value-of select="title" />
          </a>
        </h2>
        <xsl:copy-of select="excerpt/node()" />
    </article>
</xsl:template>

但是如果命名模板仅用于调用匹配模板,那么根本不需要命名模板。您可以直接使用匹配模板:

<xsl:apply-templates select="path/to/nodeset" mode="excerptItem" />

mode属性的目的是当您在mode中指定apply-templates时,XSLT将仅考虑具有相同mode值的模板。因此,您可以定义两个不同的模板,以不同的方式处理相同的元素:

<xsl:template match="Item" mode="header">
     Item in header: <xsl:value-of select="." />
</xsl:template>
<xsl:template match="Item" mode="body">
     Item in body: <xsl:value-of select="." />
</xsl:template>

然后您可以指定在不同时间使用哪一个:

<div id="header">
    <xsl:apply-templates match="/root/Items/Item" mode="header" />
</div>
<div id="body">
    <xsl:apply-templates match="/root/Items/Item" mode="body" />
</div>

并且在每种情况下都使用适当的一个。您可以阅读有关模式here的更多信息。

node() | @*是一个匹配任何节点或属性的通用XPath,因此如果您在模板的match属性中使用它,则可以创建一个模板,该模板几乎可以匹配您在apply-templates(只要没有其他模板具有更高的优先级)。将其与mode结合使用,可以创建一个可以在任何节点上调用的模板,并且只在特定时间调用。在您的示例中,看起来您将与此模板一起使用的元素将始终相同,因此明确指定它可能是更好的做法:

<xsl:template match="ExportItem" mode="excerptItem">

答案 1 :(得分:0)

  

是否可以获取命名模板的参数作为   在另一个模板中匹配路径?

不,在XSLT 2.0中,模板的匹配模式只能包含变量引用作为id()函数的参数

有关模式的完整语法,请参阅XSLT 2.0 W3C规范

http://www.w3.org/TR/xslt20/#pattern-syntax

在XSLT 1.0中,在匹配模式中的任何位置都有一个变量引用是错误的。