如何在 xslt 2.0 中将 flat xml 分组为 2 个级别

How to group flat xml into 2 levels in xslt 2.0

我有一个几乎平坦的 xml,其中有几个条目具有与标题相关的信息,这些信息将显示在条目的元数据之前。这些标题可以分为两级,第二级是可选的。请提出实现该目标的方法。

输入xml:

<world>

 <country>
  <name>USA</name>
  <code>001</code>
  <category type="developed" scheme="level1"/>
  <category type="rich" scheme="level2"/>
 </country>
 <country>
  <name>UK</name>
  <code>044</code>
  <category type="developed" scheme="level1"/>
  <category type="rich" scheme="level2"/>
 </country>
 <country>
  <name>LATVIA</name>
  <code>371</code>
  <category type="developed" scheme="level1"/>
 </country>
 <country>
  <name>BHUTAN</name>
  <code>975</code>
  <category type="developing" scheme="level1"/>
 </country>

</world>

期望的输出:

<world>
  <developed>
    <rich>
      <country>
        <name>USA</name>
        <code>001</code>
      </country>
      <country>
        <name>UK</name>
        <code>044</code>
      </country>
    </rich>
    <country>
      <name>LATVIA</name>
      <code>371</code>
    </country>

  </developed>
  <developing>
    <country>
      <name>BHUTAN</name>
      <code>975</code>
    </country>
  </developing>
</world>

嵌套两个for-each-group:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

<xsl:output indent="yes"/>

<xsl:template match="world">
  <xsl:copy>
    <xsl:for-each-group select="country" group-by="category[@scheme = 'level1']/@type">
      <xsl:element name="{current-grouping-key()}">
        <xsl:for-each-group select="current-group()[category[@scheme = 'level2']]" group-by="category[@scheme = 'level2']/@type">
          <xsl:element name="{current-grouping-key()}">
            <xsl:apply-templates select="current-group()"/>
          </xsl:element>
        </xsl:for-each-group>
        <xsl:apply-templates select="current-group()[not(category[@scheme = 'level2'])]"/>
      </xsl:element>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>

<xsl:template match="country">
  <xsl:copy>
    <xsl:copy-of select="* except category"/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>