xml 如何使用 XSLT/XPath 生成逗号分隔的列表?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/666584/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I generate a comma-separated list with XSLT/XPath?
提问by Anders Sandvig
Given this XML data:
鉴于此 XML 数据:
<root> <item>apple</item> <item>orange</item> <item>banana</item> </root>
I can use this XSLT markup:
我可以使用这个 XSLT 标记:
... <xsl:for-each select="root/item"> <xsl:value-of select="."/>, </xsl:for-each> ...
to get this result:
得到这个结果:
apple, orange, banana,
苹果、橙子、香蕉、
but how do I produce a list where the last comma is not present? I assume it can be done doing something along the lines of:
但是如何生成最后一个逗号不存在的列表?我认为可以按照以下方式做一些事情:
... <xsl:for-each select="root/item"> <xsl:value-of select="."/> <xsl:if test="...">,</xsl:if> </xsl:for-each> ...
but what should the test expression be?
但是测试表达式应该是什么?
I need some way to figure out how long the list is and where I currently am in the list, or, alternatively, if I am currently processing the last element in the list (which means I don't care how long it is or what the current position is).
我需要一些方法来确定列表有多长以及我当前在列表中的位置,或者,如果我当前正在处理列表中的最后一个元素(这意味着我不在乎它有多长或什么当前位置是)。
采纳答案by Anders Sandvig
Take a look at the position(), count()and last()functions; e.g., test="position() < last()".
看看position(),count()和last()函数;例如, test="position() < last()"。
回答by Robert Rossney
This is a pretty common pattern:
这是一个很常见的模式:
<xsl:for-each select="*">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
回答by Daniel Haley
For an XSLT 2.0 option, you can use the separatorattribute on xsl:value-of.
对于 XSLT 2.0 选项,您可以使用 上的separator属性xsl:value-of。
This xsl:value-of:
这xsl:value-of:
<xsl:value-of select="/root/item" separator=", "/>
would produce this output:
会产生这个输出:
apple, orange, banana
You could also use more than just a comma for a separator. For example, this:
您还可以不仅仅使用逗号作为分隔符。例如,这个:
<xsl:text>'</xsl:text>
<xsl:value-of select="/root/item" separator="', '"/>
<xsl:text>'</xsl:text>
Would produce the following output:
将产生以下输出:
'apple', 'orange', 'banana'
Another XSLT 2.0 option is string-join()...
另一个 XSLT 2.0 选项是string-join()...
<xsl:value-of select="string-join(/*/item,', ')"/>
回答by Marc Gravell
<xsl:if test="following-sibling::*">,</xsl:if>
or (perhaps more efficient, but you'd have to test):
或(也许效率更高,但您必须进行测试):
<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>
回答by Dimitre Novatchev
A simple XPath 1.0 one-liner:
一个简单的 XPath 1.0 单行:
concat(., substring(',', 2 - (position() != last())))
concat(., substring(',', 2 - (position() != last())))
Put it into this transformation:
把它放到这个转换中:
<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>
and apply it to the XML document:
并将其应用于 XML 文档:
<root>
<item>apple</item>
<item>orange</item>
<item>banana</item>
</root>
to get the wanted result:
得到想要的结果:
apple,orange,banana
apple,orange,banana
EDIT:
编辑:
Here is a comment from Robert Rossney to this answer:
以下是 Robert Rossney 对此答案的评论:
That's pretty opaque code for a human to read. It requires you to know two non-obvious things about XSLT: 1) what the substring function does if its index is out of range and 2) that logical values can be implicitly converted to numerical ones.
对于人类来说,这是非常不透明的代码。它要求您了解有关 XSLT 的两件不明显的事情:1) 如果子字符串函数的索引超出范围,它会做什么,以及 2) 逻辑值可以隐式转换为数字值。
and here is my answer:
这是我的答案:
Guys, never shy from learning something new. In fact this is all Stack Overflow is about, isn't it? :)
伙计们,永远不要羞于学习新事物。事实上,这就是 Stack Overflow 的全部内容,不是吗?:)
回答by jelovirt
Robert gave the classis not(position() = last())answer. This requires you to process the whole current node list to get context size, and in large input documents this might make the conversion consume more memory. Therefore, I normally invert the test to be the first thing
罗伯特给出了分类not(position() = last())答案。这需要您处理整个当前节点列表以获取上下文大小,并且在大型输入文档中这可能会使转换消耗更多内存。因此,我通常将测试反转为第一件事
<xsl:for-each select="*">
<xsl:if test="not(position() = 1)>, </xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
回答by Louise Rogow Howard
This is the way I got it working for me. I tested this against your list:
这就是我让它对我来说有效的方式。我根据您的列表对此进行了测试:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:template match="root">
<xsl:call-template name="comma-join"><xsl:with-param name="list" select="item"/></xsl:call-template>
</xsl:template>
<xsl:template name="comma-join">
<xsl:param name="list" />
<xsl:for-each select="$list">
<xsl:value-of select="." />
<xsl:if test="position() != last()">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

