【问题标题】:XSLT for-each loop for element collection用于元素集合的 XSLT for-each 循环
【发布时间】:2011-02-16 07:17:54
【问题描述】:

是否可以在 XSLT 中创建一个 for-each 循环,而不是针对节点集,而是针对我自己的元素集合?例如,我拆分了一些字符串,结果得到了一个字符串集合。我需要为集合中的每个项目创建一个节点。我知道这个问题可以通过递归模板来解决,但我想知道是否可以避免递归。

【问题讨论】:

  • 好问题 (+1)。请参阅我对两种解决方案的回答——它们都不需要使用扩展功能。 :)

标签: xslt recursion loops foreach


【解决方案1】:

有两种明显、直接的解决方案,其中一种仅在 XSLT 2.0 中受支持:

我。一个通用的解决方案

这适用于 XSLT 1.0 和 XSLT 2.0。

定义您自己的命名空间,并将您的节点集作为该命名空间中某个元素的子元素,该元素全局放置在样式表中(<xsl:stylesheet> 指令的子元素。)

这是一个例子:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my"
 >
 <xsl:output method="text"/>

 <my:nodes>
   <string>Hello </string>
   <string>World</string>
 </my:nodes>

 <xsl:variable name="vLookup"
    select="document('')/*/my:nodes/*"/>

 <xsl:param name="pSearchWord" select="'World'"/>

 <xsl:template match="/">
   <xsl:if test="$pSearchWord = $vLookup">
     <xsl:value-of select=
       "concat('Found the word ', $pSearchWord)"/>
   </xsl:if>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于任何 XML 文档(未使用)时,结果为

Found the word World

请注意,我们根本不需要 xxx:node-set() 扩展函数。

二。 XSLT 2.0 / XPath 2.0 解决方案

在 XSLT 2.0 / XPath 2.0 中,总是可以使用 sequence 类型。例如,可以通过这种方式简单地定义一个包含一系列字符串的变量:

 <xsl:variable name="vLookup" as="xs:string*"
    select="'Hello', 'World'"/>

并在以下转换中使用它:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 >
 <xsl:output method="text"/>

 <xsl:variable name="vLookup" as="xs:string*"
    select="'Hello', 'World'"/>

 <xsl:param name="pSearchWord" select="'World'"/>

 <xsl:template match="/">
   <xsl:if test="$pSearchWord = $vLookup">
     <xsl:value-of select=
       "concat('Found the word ', $pSearchWord)"/>
   </xsl:if>
 </xsl:template>
</xsl:stylesheet>

【讨论】:

    【解决方案2】:

    您使用哪个平台,具体使用哪个 XSLT 处理器?您需要以 XSLT 处理器支持的数据类型的形式提供字符串集合。究竟是哪一个完全取决于您的 XSLT 处理器支持的 API。 例如,对于 .NET 的 XslCompiledTransform,您需要提供一个 XPathNodeIterator。

    【讨论】:

      【解决方案3】:

      使用 XPath 扩展函数 node-set() 可以做到这一点。支持此功能,例如通过msxslexslt 扩展。

      MSDN 给出了一个如何将msxsl:node-set() 函数与xsl:for-each 一起使用的示例:

      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                      xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                      xmlns:user="http://www.contoso.com"
                      version="1.0">
          <xsl:variable name="books">
              <book author="Michael Howard">Writing Secure Code</book>
              <book author="Michael Kay">XSLT Reference</book>
          </xsl:variable>
      
          <xsl:template match="/">
              <authors>
                  <xsl:for-each select="msxsl:node-set($books)/book"> 
                      <author><xsl:value-of select="@author"/)</author>
                  </xsl:for-each>
              </authors>
          </xsl:template>
      </xsl:stylesheet>
      

      【讨论】:

      • 查看我对两种解决方案的回答——它们都不需要使用扩展功能。 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多