XSLT使用for-each-groups嵌套分组

时间:2012-11-01 15:43:34

标签: xml xslt xpath xslt-2.0

我必须根据某些属性对值进行分组。因此,我想使用for-each-group。

这是我正在使用的输入XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<cities>
  <city country="Germany"   continent="Europe">Munich</city>
  <city country="Germany"   continent="Europe">Dortmund</city>
  <city country="France"    continent="Europe">Brest</city>
  <city country="Japan"         continent="Asia" >Tokyo</city>
  <city country="Korea"      continent="Asia" >Seoul</city>
  <city country="Germany"   continent="Europe">Hannover</city>
  <city country="Poland"         continent="Europe">Krakau</city>
  <city country="Russia"      continent="Asia" >Omsk</city>
  <city country="Japan"         continent="Asia" >Kobe</city>
  <city country="Japan"         continent="Asia" >Ibaraki</city>
  <city country="Russia"      continent="Europe">St. Petersburg</city>
  <city country="Saudi-Arabia" continent="Africa">Riad</city>
  <city country="Ireland"        continent="Europe">Galway</city>
  <city country="Cameroon"       continent="Africa">Yaoundé</city>
  <city country="Austria"    continent="Europe">Vienna</city>
</cities>

现在,我想创建一个具有嵌套列表格式的输出文件 首先,我想按省份分组,然后按国家分组,即在国家和大陆内分组城市。

输出应该看起来像这样:

<ul>
  <li>Europe
    <ul>
      <li>Germany
        <ul>
          <li>Munich</li>
          <li>Dortmund</li>
          <li>...</li>
        </ul>          
      </li>
      <li>France
        <ul>
          <li>...</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>Asia
    <ul>...</ul>
  </li>
  <li>Africa
    <ul>...</ul>
  </li>
</ul>

到目前为止我所拥有的是以下XSLT样式表:

<xsl:template match="cities">
  <ul>
    <xsl:for-each-group select="city" group-by="@continent">
      <li>
        <xsl:value-of select="@continent" />
          <xsl:for-each-group select="stadt" group-by="@land">
           <ul>
             <li>
               <xsl:value-of select="@land" />
             </li>
           </ul>
         </xsl:for-each-group>
      </li>
    </xsl:for-each-group>
  </ul>
</xsl:template>

这适用于第一级,即按大洲分组。 但它不适用于列表中的嵌套级别。 我需要一种方法来引用当前的分组元素,以便按国家分组,只针对当前大陆。

最好/最方便的方法是什么?

1 个答案:

答案 0 :(得分:4)

您的XSLT似乎与XML不匹配,因为您的嵌套 xsl:for-each-group 引用元素 stadt 和属性 @land ,它没有出现在XML中。但是,我认为您真正需要使用的是 current-group()函数来迭代组中的元素。在这种情况下,您按当前大陆的国家/地区进行分组。

<xsl:for-each-group select="current-group()" group-by="@country">

然后你需要另一个嵌套循环来迭代这个国家的城市。

<xsl:for-each select="current-group()">

这是完整的XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:template match="cities">
      <ul>
         <xsl:for-each-group select="city" group-by="@continent">
            <li>
               <xsl:value-of select="@continent"/>
               <ul>
                  <xsl:for-each-group select="current-group()" group-by="@country">
                     <li>
                        <xsl:value-of select="@country"/>
                        <ul>
                           <xsl:for-each select="current-group()">
                              <li>
                                 <xsl:value-of select="."/>
                              </li>
                           </xsl:for-each>
                        </ul>
                     </li>
                  </xsl:for-each-group>
               </ul>
            </li>
         </xsl:for-each-group>
      </ul>
   </xsl:template>
</xsl:stylesheet>

在给定XML上运行时,输出以下内容

<ul>
   <li>Europe
      <ul>
         <li>Germany
            <ul>
               <li>Munich</li>
               <li>Dortmund</li>
               <li>Hannover</li>
            </ul></li>
         <li>France
            <ul>
               <li>Brest</li>
            </ul></li>
         <li>Poland
            <ul>
               <li>Krakau</li>
            </ul></li>
         <li>Russia
            <ul>
               <li>St. Petersburg</li>
            </ul></li>
         <li>Ireland
            <ul>
               <li>Galway</li>
            </ul></li>
         <li>Austria
            <ul>
               <li>Vienna</li>
            </ul></li>
      </ul></li>
   <li>Asia
      <ul>
         <li>Japan
            <ul>
               <li>Tokyo</li>
               <li>Kobe</li>
               <li>Ibaraki</li>
            </ul></li>
         <li>Korea
            <ul>
               <li>Seoul</li>
            </ul></li>
         <li>Russia
            <ul>
               <li>Omsk</li>
            </ul></li>
      </ul></li>
   <li>Africa
      <ul>
         <li>Saudi-Arabia
            <ul>
               <li>Riad</li>
            </ul></li>
         <li>Cameroon
            <ul>
               <li>Yaound</li>
            </ul></li>
      </ul></li>
</ul>

注意,您可能希望用 xsl:apply-templates 替换最内部的 xsl:for-each ,以避免过度缩进!