首先,使用的 tokenize 函数实际上并不正确。理论上,它应该像这样吐出一个标签元素列表(严格来说是“结果树片段”)
<tag>a</tag>
<tag>b</tag>
<tag>c</tag>
<tag>d</tag>
但它实际上错过了最后一个元素
<tag>a</tag>
<tag>b</tag>
<tag>c</tag>
<tag></tag>
你最好在这里找到另一个标记化函数(在 StackOverflow 中肯定有工作的)。
但是,在回答您关于在此之上使用 xsl:for-each 的问题时,您可能会想要做这样的事情......
<xsl:variable name="tags">
<xsl:call-template name="tokenize">
<xsl:with-param name="pText" select="@CommaSeparated"/>
</xsl:call-template>
</xsl:variable>
<xsl:for-each select="$tags/tag">
<xsl:copy-of select="." />
</xsl:for-each>
也就是说,将标签列表存储在一个变量中,然后循环遍历它们。但是,如果您在 XSLT1.0 中尝试此操作,则会收到错误消息“表达式必须计算为节点集。”。为了解决这个问题,您需要使用扩展功能。EXSLT 可能是最常见的。您可以像这样在 XSLT 中声明它
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="exsl">
你可以简单地改变xsl:for-each如下:
<xsl:for-each select="exsl:node-set($tags)/tag">
因此,给定以下 XML
<a CommaSeparated="a,b,c,d"></a>
以及以下 XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/a">
<xsl:variable name="tags">
<xsl:call-template name="tokenize">
<xsl:with-param name="pText" select="@CommaSeparated"/>
</xsl:call-template>
</xsl:variable>
<xsl:for-each select="exsl:node-set($tags)/tag">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
<xsl:template name="tokenize">
<xsl:param name="pText"/>
<xsl:if test="string-length($pText)">
<tag>
<xsl:value-of select="substring-before($pText, ',')"/>
</tag>
<xsl:call-template name="tokenize">
<xsl:with-param name="pText" select="substring-after($pText, ',')"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
以下是输出(由于您使用的错误标记化功能,最后一个标签为空白)
<tag>a</tag>
<tag>b</tag>
<tag>c</tag>
<tag></tag>