我有一个由笨拙的程序自动生成的源XML,其中包含重复和空的条目。
我希望能够选择并仅显示最具代表性的条目,过滤空条目。例如,假设我的源XML是
<catalog>
<letter>
<char>A</char>
</letter>
<letter>
<char>B</char>
</letter>
<letter>
<char></char>
</letter>
<letter>
<char>A</char>
</letter>
<letter>
<char></char>
</letter>
<letter>
<char></char>
</letter>
</catalog>
然后,我想只得到A。
我能做到:
<table><tr>
<xsl:for-each select="catalog/letter[char!='']">
<td><xsl:value-of select="char" /></td>
</xsl:for-each>
</tr></table>
将显示一个仅包含A,B,A(不是空列)的表。
现在我想只获得A,因为它是最经常出现的。我该怎么做?
更新
这是一次尝试,但不起作用。
<xsl:variable name="counter" select="0" />
<xsl:variable name="this" select="" />
<xsl:for-each select="catalog/letter[char!='']">
<xsl:variable name="var" select="char" />
<xsl:variable name="cou" select="count(/catalog/letter[char=$var])" />
<xsl:if test="$cou > counter">
<xsl:variable name="this" select="$var" />
</xsl:if>
<td><xsl:value-of select="$this" /></td>
</xsl:for-each>
答案 0 :(得分:2)
首先要提到的是,在XSLT中,变量是不可变的。它们一旦设置就无法更改,所以如果试图拥有一个&#34;计数器&#34;变量,它不起作用。
要修复当前的XSLT,您可以使用xsl:sort
xsl:for-each
命令对具有相同letter
的{{1}}元素的数量进行排序,然后选择第一个。像
char
然而,这是非常低效的,因为你会反复计算相同的节点。
更好的技巧是使用Muenchian Grouping,其中包括定义查找元素的键
<xsl:for-each select="catalog/letter[char!='']">
<xsl:sort select="count(/catalog/letter[char=current()/char])" order="descending" />
<xsl:if test="position() = 1">
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
然后使用此键查找每个不同的字母,并使用相同的字符计算字母数。
试试这个XSLT
<xsl:key name="letter" match="letter[char!='']" use="char" />
这应该只输出<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="letter" match="letter[char!='']" use="char" />
<xsl:template match="/">
<xsl:for-each select="catalog/letter[generate-id() = generate-id(key('letter', char)[1])]">
<xsl:sort select="count(key('letter', char))" order="descending" />
<xsl:if test="position() = 1">
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
。