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

时间:2015-01-01 17:41:05

标签: xml xslt xslt-2.0 xslt-grouping

我有一个几乎平坦的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>

1 个答案:

答案 0 :(得分:2)

嵌套两个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>