使用 XSLT 对子字符串进行分组

Grouping substrings with XSLT

我是 xsl 转换的新手,在对子字符串进行分组时遇到了问题。我有一些 xml 如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<document-root>
  <classes>
    <class1>CATSryverty</class1>
    <class1>CATSt6vvy</class1>
    <class1>CATS4yv6v</class1>
    <class1>DOGSrybytb</class1>
    <class1>DOGSbu6b</class1>
    <class1>DOGS5u57756</class1>
  </classes>
</document-root>

和这个 xsl:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
    <docs>
        <xsl:for-each select="document-root/classes">
            <xsl:element name="classesCSV">
                <xsl:for-each select="class1/text()">
                    <xsl:value-of select="substring(., 1, 4)"/>
                    <xsl:if test="not(position() = last())">,</xsl:if>
                </xsl:for-each>
            </xsl:element>
        </xsl:for-each>
    </docs>
</xsl:template>
</xsl:stylesheet>

这让我明白了:

<?xml version="1.0" encoding="UTF-8"?>
<docs>
 <classesCSV>CATS,CATS,CATS,DOGS,DOGS,DOGS</classesCSV>
</docs>

但我想要的是:

<?xml version="1.0" encoding="UTF-8"?>
<docs>
 <classesCSV>CATS,DOGS</classesCSV>
</docs>

我该如何更改?

XSLT 1.0:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="kDistinct" match="class1" use="substring(., 1,4)"/>
<xsl:template match="/">
 <docs>
    <xsl:for-each select="document-root/classes">
       <xsl:element name="classesCSV">
          <xsl:for-each select="class1[generate-id() = 
                          generate-id(key('kDistinct', substring(.,1,4))[1])]">
             <xsl:value-of select="substring(.,1,4)"/>
             <xsl:if test="not(position() = last())">,</xsl:if>
           </xsl:for-each>
       </xsl:element>
    </xsl:for-each>
 </docs>
</xsl:template>
</xsl:stylesheet>

输出:

<?xml version="1.0" encoding="UTF-8"?>
<docs>
  <classesCSV>CATS,DOGS</classesCSV>
</docs>

XSLT 2.0:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
 <xsl:template match="/">
  <docs>
   <xsl:element name="classesCSV">
      <xsl:for-each-group select="//class1" group-by="substring(., 1,4)">
         <xsl:value-of select="current-grouping-key()"/>
         <xsl:if test="not(position() = last())">,</xsl:if>
      </xsl:for-each-group>
   </xsl:element>
  </docs>
 </xsl:template>
</xsl:stylesheet>