如何在XSLT中实现"uniq -c"?



我想计算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负责处理链中的下一个。

相关内容

  • 没有找到相关文章

最新更新