鉴于此XML数据:
<root> <item>apple</item> <item>orange</item> <item>banana</item> </root>
我可以使用这个XSLT标记:
... <xsl:for-each select="root/item"> <xsl:value-of select="."/>, </xsl:for-each> ...
得到这个结果:
苹果,橘子,香蕉,
但是如何生成最后一个逗号不存在的列表?我认为可以按照以下方式做一些事情:
... <xsl:for-each select="root/item"> <xsl:value-of select="."/> <xsl:if test="...">,</xsl:if> </xsl:for-each> ...
但测试表达式应该是什么?
我需要一些方法来确定列表的长度以及我当前在列表中的位置,或者,如果我当前正在处理列表中的最后一个元素(这意味着我不关心它有多长或者是什么目前的立场是).
Rob*_*ney 54
这是一种非常常见的模式:
<xsl:for-each select="*">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
Run Code Online (Sandbox Code Playgroud)
Dan*_*ley 11
对于XSLT 2.0选项,您可以使用该separator属性xsl:value-of.
这个xsl:value-of:
<xsl:value-of select="/root/item" separator=", "/>
Run Code Online (Sandbox Code Playgroud)
会产生这个输出:
apple, orange, banana
Run Code Online (Sandbox Code Playgroud)
您还可以使用多个逗号作为分隔符.例如,这个:
<xsl:text>'</xsl:text>
<xsl:value-of select="/root/item" separator="', '"/>
<xsl:text>'</xsl:text>
Run Code Online (Sandbox Code Playgroud)
会产生以下输出:
'apple', 'orange', 'banana'
Run Code Online (Sandbox Code Playgroud)
另一个XSLT 2.0选项是string-join()......
<xsl:value-of select="string-join(/*/item,', ')"/>
Run Code Online (Sandbox Code Playgroud)
<xsl:if test="following-sibling::*">,</xsl:if>
Run Code Online (Sandbox Code Playgroud)
或者(也许更有效率,但你必须测试):
<xsl:for-each select="*[1]">
<xsl:value-of select="."/>
<xsl:for-each select="following-sibling::*">
<xsl:value-of select="concat(',',.)"/>
</xsl:for-each>
</xsl:for-each>
Run Code Online (Sandbox Code Playgroud)
一个简单的XPath 1.0单线程:
concat(., substring(',', 2 - (position() != last())))
把它变成这种转变:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:for-each select="*">
<xsl:value-of select=
"concat(., substring(',', 2 - (position() != last())))"
/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
并将其应用于XML文档:
<root>
<item>apple</item>
<item>orange</item>
<item>banana</item>
</root>
Run Code Online (Sandbox Code Playgroud)
得到想要的结果:
apple,orange,banana
编辑:
以下是Robert Rossney对此答案的评论:
对于人类来说,这是非常不透明的代码.它需要你知道关于XSLT的两个非显而易见的事情:1)如果索引超出范围,子串函数会做什么; 2)逻辑值可以隐式转换为数字值.
这是我的答案:
伙计们,从不羞于学习新事物.实际上这是Stack Overflow的全部内容,不是吗?:)
罗伯特给了经典not(position() = last())答案.这要求您处理整个当前节点列表以获取上下文大小,而在大型输入文档中,这可能会使转换消耗更多内存.因此,我通常将测试反转为第一件事
<xsl:for-each select="*">
<xsl:if test="not(position() = 1)>, </xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
Run Code Online (Sandbox Code Playgroud)