创建节点集并将其作为参数传递

29

我正在使用 XSLT 1.0,尝试创建一个小的节点集,并将其作为参数传递给模板,类似以下内容:

<xsl:call-template name="widget">
  <xsl:with-param name="flags">
    <items>
      <item>widget.recent-posts.trim-length=100</item>
      <item>widget.recent-posts.how-many=3</item>
      <item>widget.recent-posts.show-excerpt</item>
    </items>
  </xsl:with-param>
</xsl:call-template>

这个想法是在 widget 模板内部我可以编写类似于以下的内容:

<xsl:value-of select="$flags/item[1]" />

显然我会得到编译错误.. 我该如何实现这种事情?

2个回答

33

XSLT 1.0中有一种(非标准的)方法可以动态创建临时树并在其上评估XPath表达式但这需要使用xxx:node-set()函数

每当节点在xsl:variablexsl:param的主体内部被动态创建时,该xsl:variable / xsl:param的类型是RTF(结果树片段),并且W3 XSLT 1.0规范严格限制了可以针对RTF计算的XPath表达式的类型。

解决方法是,几乎每个XSLT 1.0供应商都有自己的xxx:node-set()扩展函数,它接受一个RTF并从中产生一个正常的节点集。

xxx前缀(或任何其他您选择的前缀)绑定到的命名空间因不同供应商而异。对于MSXML和两个.NET XSLT处理器,它是:"urn:schemas-microsoft-com:xslt"。EXSLT库使用命名空间:"http://exslt.org/common"。这个EXSLT命名空间在许多XSLT 1.0处理器上实现,并建议使用它的xxx:node-set()扩展,如果可能的话。

下面是一个快速示例

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 xmlns:ext="http://exslt.org/common"
  exclude-result-prefixes="ext msxsl"
 >
 <xsl:template match="/">
  <xsl:variable name="vTempRTF">
   <a>
    <b/>
   </a>
  </xsl:variable>

  <xsl:copy-of select="ext:node-set($vTempRTF)/a/*"/>
 </xsl:template>
</xsl:stylesheet>

7

好的,我成功地通过以下方式解决了这个问题:

首先,在您的样式表中添加一个自定义命名空间,例如xmlns:myns="http://my.ns.com"

然后在样式表的顶部定义节点集:

<myns:recent-posts-flags>
    <item>widget.recent-posts.trim-length=100</item>
    <item>widget.recent-posts.how-many=3</item>
    <item>widget.recent-posts.show-excerpt</item>
</myns:recent-posts-flags>

接下来以以下方式引用:

<xsl:call-template name="widget">
    <xsl:with-param name="flags" select="document('')/*/myns:recent-posts-flags" />
</xsl:call-template>

这个方案可以运行,但是最好还是在<xsl:with-param>标签内部定义节点集,就像我给出的第一个例子一样。有人认为这可能吗?


+1 这是常见问题解答,也在规范中提到:此外,xsl:stylesheet元素可以包含任何不属于XSLT命名空间的元素,前提是该元素的扩展名称具有非空命名空间URI。 (...)这些元素可以提供例如由扩展元素或扩展函数使用的信息,关于如何处理结果树的信息,关于如何获取源树的信息,样式表的元数据以及样式表的结构化文档等信息。 - user357812
这正是我在答案的第二行所说的。 - John J. Camilleri
是的,只有我读得太糟了,谷歌得太快了。>_< - Lilleman
大家好,你们中有人能够使用这种方法来处理PHP吗?似乎php XSLTProcessor无法很好地处理document('')调用... - lbrutti
是的,Ibrutti。它的工作效果非常好,特别是作为定义要在xsl:for-each标签中处理的一组值的手段。 - Patanjali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接