假设我有以下列表:
<list>
<item>text1</item>
<item>text2</item>
<item>text3</item>
<item type="type1">text4</item>
<item type="type1">text5</item>
<item type="type1">text6</item>
<item>text7</item>
<item>text8</item>
<item type="type2">text9</item>
<item type="type2">text10</item>
<item>text11</item>
<item>text12</item>
<item type="...">...</item>
...
<item>...</item>
...
</list>
一个重要的事情,我不知道什么值会有type属性!它将以编程方式生成。 Not this one.我只知道某些商品可能具有相同的属性。
我想将此列表转换为:
text1
text2
text3
text4, text5, text6
text7
text8
text9, text10
text11
text12
因此,对于每个没有“type”属性的项目,我只输出item中的文本。对于具有相同属性的每个项目,我将所有项目文本输出到一行中。如何在xslt中实现这一点?当以编程方式生成属性时,如何选择具有相同属性的所有项目?
答案 0 :(得分:2)
您想按类别对项目进行分组。使用密钥轻松完成分组:
migrations
这将创建具有类型的所有项目的索引,并使用它们各自的类型作为键。
接下来,只有在两个条件之一为真时才要生成输出行:
可以表达为:
<xsl:key name="byType" match="item[@type]" use="@type" />
其类型的第一项将输出用逗号分隔的所有其他项。以下相同类型的项目不应输出任何内容(因为它们已经打印过)。
我们可以将每行上要打印的项目列表定义为这两个节点集的并集:
在XPath中,这是<xsl:if test="not(@type) or generate-id() = generate-id(key('byType', @type)[1])">
(节点集永远不能包含两次相同的节点)
所以这个:
. | key('byType', @type)
输出
text1 text2 text3 text4, text5, text6 text7 text8 text9, text10 text11 text12 ... ...
答案 1 :(得分:1)
您想使用Muenchian分组。这样的事情应该有效
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:key name="items-by-type" match="item" use="@type" />
<xsl:template match="/list">
<xsl:for-each select="item[count(. | key('items-by-type', @type)[1]) = 1]">
<xsl:if test="not(@type)">
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
</xsl:if>
<xsl:if test="@type">
<xsl:for-each select="key('items-by-type', @type)">
<xsl:value-of select="." />
<xsl:if test="position() != last()"><xsl:text>, </xsl:text></xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:transform>
http://xsltransform.net/3NJ3914/3
使用key
对item
进行分组。如果未设置@type
,则只需打印该项目。否则,遍历item
的所有@type
并打印它们。