【问题标题】:XSLT 1.0 grouping on one or multiple levelsXSLT 1.0 在一个或多个级别上分组
【发布时间】:2019-03-29 16:27:16
【问题描述】:

今天的挑战是在 XSLT 1.0 中进行分组。发现有一种叫做键和 Muenchian 分组的东西。

输入 XML:

<Items>
    <Item>
        <ID>1</ID>
        <Name>A</Name>
        <Country>Sweden</Country>
        <Region>Småland</Region>
    </Item>
    <Item>
        <ID>2</ID>
        <Name>B</Name>
        <Country>Sweden</Country>
        <Region>Norrland</Region>
    </Item>
    <Item>
        <ID>3</ID>
        <Name>C</Name>
        <Country>USA</Country>
        <Region>Alaska</Region>
    </Item>
    <Item>
        <ID>4</ID>
        <Name>D</Name>
        <Country>USA</Country>
        <Region>Texas</Region>
    </Item>
    <Item>
        <ID>5</ID>
        <Name>E</Name>
        <Country>Sweden</Country>
        <Region>Norrland</Region>
    </Item>
</Items>

我需要将 XML 精简为更好的结构,并且我不希望从这个示例 XML 中获得按国家和地区结构化的项目。以下是对国家和地区进行排序的所需结果:

<Items>
  <Country Name="Sweden">
    <Region Name="Norrland">
      <Item>
        <ID>2</ID>
        <Name>B</Name>
      </Item>
      <Item>
        <ID>5</ID>
        <Name>E</Name>
      </Item>
    </Region>
    <Region Name="Småland">
      <Item>
        <ID>1</ID>
        <Name>A</Name>
      </Item>
    </Region>
  </Country>
  <Country Name="USA">
    <Region Name="Alaska">
      <Item>
        <ID>3</ID>
        <Name>C</Name>
      </Item>
    </Region>
    <Region Name="Texas">
      <Item>
        <ID>4</ID>
        <Name>D</Name>
      </Item>
    </Region>
  </Country>
</Items>

编辑:

我还想确保地区最终出现在自己的国家/地区,即使存在重复。我相应地编辑了答案。

另外,我想暗示 xsltfiddle.liberty-development.net 是一种进行试错式 XSLT 开发的简单方法...

【问题讨论】:

    标签: xslt-1.0 xslt-grouping


    【解决方案1】:

    article的启发,我找到了一个巧妙的解决方案:

    我已经包含了 cmets 用于单组或双组,请参阅代码中的 cmets。请注意我如何使用第一个键(索引)作为第二个 for-each 循环的输入:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output indent="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:key name="country" match="Item" use="Country" />
      <xsl:key name="region" match="Item" use="concat(Region, '|', Country)" />
    
      <xsl:template match="/Items">
        <Items>
          <xsl:for-each select="Item[generate-id(.) = generate-id(key('country', Country))]">
            <xsl:sort select="Country" />
            <xsl:variable name="_country" select="Country" />
    
            <xsl:element name="Country">
              <xsl:attribute name="Name"><xsl:value-of select="$_country" /></xsl:attribute>
    
              <!-- single level grouping -->
              <!--<xsl:apply-templates select="key('country', Country)" />-->
    
    
              <!-- double grouping -->
              <!-- START -->
              <xsl:for-each select="key('country', Country)[generate-id(.) = generate-id(key('region', concat(Region, '|', Country)))]">
                  <xsl:sort select="Region" />
                  <xsl:variable name="_region" select="Region" />
    
                  <xsl:element name="Region">
                    <xsl:attribute name="Name"><xsl:value-of select="$_region" /></xsl:attribute>
    
                    <xsl:apply-templates select="key('region', concat(Region, '|', Country))" />
                  </xsl:element>
              </xsl:for-each>
              <!-- END -->
    
            </xsl:element>    
          </xsl:for-each>
        </Items>
      </xsl:template>
    
      <xsl:template match="Item">
        <xsl:element name="Item">
          <xsl:element name="ID"><xsl:value-of select="ID" /></xsl:element>
          <xsl:element name="Name"><xsl:value-of select="Name" /></xsl:element>
        </xsl:element>
      </xsl:template>
    </xsl:stylesheet>
    

    【讨论】:

    • 看起来不太对劲。如果您想对一个国家/地区内的区域进行分组,您的第二个键应该是&lt;xsl:key name="region" match="Item" use="concat(Region, '|', Country)"/&gt;。在此处查看类似示例:stackoverflow.com/questions/54478865/… 除非您可以确定每个区域名称都是唯一的。
    • @michael.hor257k 感谢您的意见!我在回家的路上正在考虑这个问题……您验证了我的想法并提出了解决方案!谢谢!我会在测试时编辑答案。
    • 我测试并更新了解决方案,以确保区域最终在他们的国家内,即使有重复。
    猜你喜欢
    • 1970-01-01
    • 2015-11-20
    • 1970-01-01
    • 2015-03-20
    • 2023-02-10
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    • 2021-11-20
    相关资源
    最近更新 更多