xsl muenchian 分组多个级别

Posted

技术标签:

【中文标题】xsl muenchian 分组多个级别【英文标题】:xsl muenchian grouping multiple levels 【发布时间】:2013-12-06 12:07:00 【问题描述】:

我一直在尝试学习使用其他帖子来理解 muenchian 分组,但我正在努力将正确的分组转换为表格格式。分组需要分为两个级别,首先是赛季“年”,然后是每个赛季显示按“组”分组的匹配项。我已经设法将“组”分组,但它们都显示在最新一季,而不是分成各自的季节。这是xml的一个例子:

<DocumentElement>
  <QueryResults>
    <Years>2013/2014</Years>
    <Group>1</Group>
    <TeamNameShort>TeamA</TeamNameShort>
  </QueryResults>
  <QueryResults>
    <Years>2013/2014</Years>
    <Group>1</Group>
    <TeamNameShort>TeamB</TeamNameShort> 
  </QueryResults>
  <QueryResults>
    <Years>2013/2014</Years>
    <Group>2</Group>
    <TeamNameShort>TeamC</TeamNameShort>
</QueryResults>
<QueryResults>
    <Years>2013/2014</Years>
    <Group>2</Group>
    <TeamNameShort>TeamD</TeamNameShort>
</QueryResults>
 <QueryResults>
    <Years>2012/2013</Years>
    <Group>1</Group>
    <TeamNameShort>TeamA</TeamNameShort>
</QueryResults>
<QueryResults>
    <Years>2012/2013</Years>
    <Group>1</Group>
    <TeamNameShort>TeamB</TeamNameShort>
  </QueryResults>
  <QueryResults>
    <Years>2012/2013</Years>
    <Group>2</Group>
    <TeamNameShort>TeamC</TeamNameShort>
  </QueryResults>
  <QueryResults>
  <Years>2012/2013</Years>
  <Group>2</Group>
  <TeamNameShort>TeamD</TeamNameShort>
  </QueryResults>
</DocumentElement>

xsl 目前看起来像这样

<xsl:stylesheet 
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:cfg="http://tempuri.org/config"
exclude-result-prefixes="cfg"
> 

<xsl:output method="html" indent="yes"/>

<!-- index by season -->
<xsl:key 
name="Season"  
match="QueryResults" 
use="Years" 
/>

<!-- index by "Pool"  -->
<xsl:key 
name="Pool" 
match="QueryResults" 
use="Group" 
/>

<xsl:template match="DocumentElement">
  <xsl:copy>
    <!-- group by season -->
    <xsl:apply-templates mode="season" select="
    QueryResults[
      generate-id()
      =
      generate-id(key('Season', Years)[1])
    ]
  ">
    <xsl:sort select="Years" order="descending" />
  </xsl:apply-templates>
</xsl:copy>
</xsl:template>

<!-- Season -->
<xsl:template match="QueryResults" mode="season">
<xsl:variable name="y" select="Years" />
  <table>
    <tbody>   
    <tr>
      <td colspan="3">Season <xsl:value-of select="$y"/></td>
    </tr>
    <tr>
        <th>Pos</th>
        <th>Group/Year</th>
        <th>Team</th>
    </tr>

<!-- group Season by Pool -->
<xsl:apply-templates mode="pool" select="
    key('Season', $y)[
      generate-id() 
      =
      generate-id(key('Pool',Group)[1])
    ]
  ">
</xsl:apply-templates>
</tbody>
</table>
</xsl:template>

<!-- Pool -->
<xsl:template match="QueryResults" mode="pool">
<xsl:variable name="g" select="Group" />

  <tr>
    <td colspan="3">Pool <xsl:value-of select="Group"/></td>
  </tr>

    <xsl:for-each select="key('Pool',$g)"> 
    <tr>
     <td><xsl:value-of select="Group"/></td>
     <td><xsl:value-of select="Years"/></td>
     <td><xsl:value-of select="TeamNameShort"/></td>
    </tr>
 </xsl:for-each>
</xsl:template>

  <xsl:template match="QueryResults">
<xsl:copy-of select="." />
</xsl:template>

</xsl:stylesheet>

【问题讨论】:

【参考方案1】:

问题在于,您不应该仅按 Group 元素进行分组,而应按给定 YearGroup 进行分组。实际上,您需要使用连接键

<xsl:key name="Pool" match="QueryResults" use="concat(Years, '|', Group)"/>

那么,只要您引用键,就可以简单地使用此连接值。例如

<xsl:apply-templates mode="pool" select="
   key('Season', $y)
      [
         generate-id() = generate-id(key('Pool',concat(Years, '|', Group))[1])
      ]"/>

请注意,这里的 | 字符实际上可以是任何字符,只要它没有出现在您要连接的两个值中的任何一个中即可。

试试这个 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cfg="http://tempuri.org/config" exclude-result-prefixes="cfg">
   <xsl:output method="html" indent="yes"/><!-- index by season -->
   <xsl:key name="Season" match="QueryResults" use="Years"/><!-- index by "Pool"  -->
   <xsl:key name="Pool" match="QueryResults" use="concat(Years, '|', Group)"/>

   <xsl:template match="DocumentElement">
      <xsl:copy><!-- group by season -->
          <xsl:apply-templates mode="season" select="QueryResults[generate-id() = generate-id(key('Season', Years)[1])]">
            <xsl:sort select="Years" order="descending"/>
         </xsl:apply-templates>
      </xsl:copy>
   </xsl:template><!-- Season -->
   <xsl:template match="QueryResults" mode="season">

      <xsl:variable name="y" select="Years"/>
      <table>
         <tbody>
            <tr>
               <td colspan="3">Season 
                  <xsl:value-of select="$y"/></td>
            </tr>
            <tr>
               <th>Pos</th>
               <th>Group/Year</th>
               <th>Team</th>
            </tr><!-- group Season by Pool -->
            <xsl:apply-templates mode="pool" select="key('Season', $y)[generate-id()  = generate-id(key('Pool',concat(Years, '|', Group))[1])]"/>
         </tbody>
      </table>
   </xsl:template>

   <!-- Pool -->
   <xsl:template match="QueryResults" mode="pool">
      <xsl:variable name="g" select="concat(Years, '|', Group)"/>
      <tr>
         <td colspan="3">Pool 
            <xsl:value-of select="Group"/></td>
      </tr>
      <xsl:for-each select="key('Pool',$g)">
         <tr>
            <td>
               <xsl:value-of select="Group"/>
            </td>
            <td>
               <xsl:value-of select="Years"/>
            </td>
            <td>
               <xsl:value-of select="TeamNameShort"/>
            </td>
         </tr>
      </xsl:for-each>
   </xsl:template>

   <xsl:template match="QueryResults">
      <xsl:copy-of select="."/>
   </xsl:template>
</xsl:stylesheet>

【讨论】:

这很有意义,很好的解决方案 - 谢谢! 这是一个优雅的解决方案,写得很好。干得好!

以上是关于xsl muenchian 分组多个级别的主要内容,如果未能解决你的问题,请参考以下文章

使用 XSLT 对 HTML 输出进行分组(muenchian 分组?)

Muenchian分组中的[1]真的有必要吗?

如何改进我的 Muenchian 分组 XSLT?

如何正确使用 Muenchian 按元素对非常重复的标签进行分组?

XSLT 1.0 将同一级别的多个相同节点以不同的值分组

如何将平面 DataFrame 对象转换为具有多个列级别且也按特定维度分组的 DataFrame 对象?