我想计算XML中相同元素的数量,就像uniq -c
对文本文件所做的那样
输入:
<doc>
<page>
<elem>a</elem>
<elem>a</elem>
<elem>a</elem>
<elem>b</elem>
<elem>b</elem>
<elem>c</elem>
<elem>a</elem>
<elem>a</elem>
</page>
</doc>
预期输出:
<doc>
<page>
<elem c="3">a</elem>
<elem c="2">b</elem>
<elem c="1">c</elem>
<elem c="2">a</elem>
</page>
</doc>
在XSLT2.0中,使用<xsl:for-each-group select="elem" group-adjacent=".">
非常容易做到这一点,但在XSLT1.0中则相当棘手。我会使用尾部递归模板来模拟"while循环":
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" />
<xsl:template match="/">
<doc><xsl:apply-templates select="doc/page" /></doc>
</xsl:template>
<xsl:template match="page">
<page><xsl:apply-templates select="elem[1]" /></page>
</xsl:template>
<!-- an element whose value is the same as the next one - don't output
anything now, just increment counter for the next elem -->
<xsl:template match="elem[. = following-sibling::elem[1]]">
<xsl:param name="count" select="1" />
<xsl:apply-templates select="following-sibling::elem[1]">
<xsl:with-param name="count" select="$count + 1" />
</xsl:apply-templates>
</xsl:template>
<!-- otherwise - output element with current counter value and start again
from 1 for the next (if any) element -->
<xsl:template match="elem">
<xsl:param name="count" select="1" />
<elem c="{$count}"><xsl:value-of select="." /></elem>
<xsl:apply-templates select="following-sibling::elem[1]" />
</xsl:template>
</xsl:stylesheet>
page
模板仅将模板应用于第一个elem
,然后每个elem
负责处理链中的下一个。