将新闻列表转换为按年份和月份分组的HTML菜单



目标是输出一个<ul>,使用 xslt 1.0 删除按年份分组的重复月份。

这似乎类似于在 XSLT 中按月和年对 XML 节点进行分组,但我不确定如何为以下标记转换解决方案:

<news>
    <entry>
        <title>News Item 1</title>
        <meta>
            <year>2011</year>
            <month>12</month>
            <day>05</day>
        </meta>
    </entry>
    <entry>
        <title>News Item 2</title>
        <meta>
            <year>2011</year>
            <month>12</month>
            <day>09</day>
        </meta>
    </entry>
    <entry>
        <title>News Item 3</title>
        <meta>
            <year>2011</year>
            <month>11</month>
            <day>25</day>
        </meta>
    </entry>
    <entry>
        <title>News Item 4</title>
        <meta>
            <year>2011</year>
            <month>10</month>
            <day>16</day>
        </meta>
    </entry>
    <entry>
        <title>News Item 5</title>
        <meta>
            <year>2011</year>
            <month>12</month>
            <day>05</day>
        </meta>
    </entry>
    <entry>
        <title>News Item 6</title>
        <meta>
            <year>2010</year>
            <month>06</month>
            <day>13</day>
        </meta>
    </entry>
</news>

期望的输出

<ul>
    <li>
        <a href="#">2011</a>
        <ul>
            <li>
                <a href="#">12</a>
            </li>
            <li>
                <a href="#">11</a>
            </li>
            <li>
                <a href="#">10</a>
            </li>
        </ul>
    </li>
    <li>
        <a href="#">2010</a>
        <ul>
            <li>
                <a href="#">06</a>
            </li>
        </ul>
    </li>
</ul>

此转换:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:key name="kEntryByYear" match="entry"
  use="meta/year"/>
 <xsl:key name="kMetaByYearMonth" match="meta"
  use="concat(year, '+', month)"/>
 <xsl:template match="/*">
  <ul>
    <xsl:apply-templates select=
     "entry
        [generate-id()
        =
         generate-id(key('kEntryByYear',
                          meta/year
                         )[1]
                     )
         ]
      ">
       <xsl:sort select="meta/year" data-type="number"
        order="descending"/>
     </xsl:apply-templates>
  </ul>
 </xsl:template>
 <xsl:template match="entry">
  <li>
   <a href="#"><xsl:value-of select="meta/year"/></a>
   <ul>
     <xsl:apply-templates select=
          "key('kEntryByYear', meta/year)/meta
             [generate-id()
             =
              generate-id(key('kMetaByYearMonth',
                              concat(year, '+', month)
                              )[1]
                          )
             ]
          ">
      <xsl:sort select="month"
           data-type="number" order="descending"/>
     </xsl:apply-templates>
   </ul>
  </li>
 </xsl:template>
 <xsl:template match="meta">
  <li>
    <a href="#"><xsl:value-of select="month"/></a>
  </li>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<news>
    <entry>
        <title>News Item 1</title>
        <meta>
            <year>2011</year>
            <month>12</month>
            <day>05</day>
        </meta>
    </entry>
    <entry>
        <title>News Item 2</title>
        <meta>
            <year>2011</year>
            <month>12</month>
            <day>09</day>
        </meta>
    </entry>
    <entry>
        <title>News Item 3</title>
        <meta>
            <year>2011</year>
            <month>11</month>
            <day>25</day>
        </meta>
    </entry>
    <entry>
        <title>News Item 4</title>
        <meta>
            <year>2011</year>
            <month>10</month>
            <day>16</day>
        </meta>
    </entry>
    <entry>
        <title>News Item 5</title>
        <meta>
            <year>2011</year>
            <month>12</month>
            <day>05</day>
        </meta>
    </entry>
    <entry>
        <title>News Item 6</title>
        <meta>
            <year>2010</year>
            <month>06</month>
            <day>13</day>
        </meta>
    </entry>
</news>

产生所需的正确结果

<ul>
   <li>
      <a href="#">2011</a>
      <ul>
         <li>
            <a href="#">12</a>
         </li>
         <li>
            <a href="#">11</a>
         </li>
         <li>
            <a href="#">10</a>
         </li>
      </ul>
   </li>
   <li>
      <a href="#">2010</a>
      <ul>
         <li>
            <a href="#">06</a>
         </li>
      </ul>
   </li>
</ul>

解释

  1. 通过单个键对entry进行Muenchian分组(meta/year(。

  2. 通过组合键对meta进行Muenchian分组,具体取决于yearmonth