2013-03-11 66 views
2

這是我的第一個問題。XSL 1.0雙重分組

我想用XSL 1.0改造這個XML:

<RESULTS> 
    <RES> 
     <GROUP>1</GROUP> 
     <SUBGROUP>A</SUBGROUP> 
     <NAME>Alice</NAME> 
    </RES> 

    <RES> 
     <GROUP>1</GROUP> 
     <SUBGROUP>A</SUBGROUP> 
     <NAME>Bart</NAME> 
    </RES> 

    <RES> 
     <GROUP>1</GROUP> 
     <SUBGROUP>B</SUBGROUP> 
     <NAME>Keira</NAME> 
    </RES> 

    <RES> 
     <GROUP>2</GROUP> 
     <SUBGROUP>A</SUBGROUP> 
     <NAME>Mike</NAME> 
    </RES> 

    <RES> 
     <GROUP>2</GROUP> 
     <SUBGROUP>B</SUBGROUP> 
     <NAME>Peter</NAME> 
    </RES> 

    <RES> 
     <GROUP>2</GROUP> 
     <SUBGROUP>B</SUBGROUP> 
     <NAME>Olaf</NAME> 
    </RES> 

</RESULTS> 

進入這個:

<h1> 1 </h1> 
     <h2>A</h2> 
     <p>Alice</p> 
     <p>Bart</p> 

     <h2>B</h2> 
     <p>Keira</p> 

    <h1> 2 </h1> 
     <h2>A</h2> 
     <p>Mike</p> 

     <h2>B</h2> 
     <p>Peter</p> 
     <p>Olaf</p> 

我已經使用Muenchian方法試過了,然而,這只是讓我按組排序,我無法按SUBGROUP對排序結果進行排序。請注意,我必須每個組/子組查看標題。

@ CM Sperberg - 麥昆

我沒有要發佈的文字牆,但如果它可以幫助我做到這一點:

這是我試過的解決方案之一:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="byGROUP" match="RESULTS/RES" use="GROUP" /> 
    <xsl:template match="RESULTS"> 
     <xsl:for-each select="RES[count(. | key('byGROUP', GROUP)[1]) = 1]"> 
      <xsl:sort select="GROUP" order="descending" /> 
      <h1> 
       <xsl:value-of select="GROUP" /> 
      </h1> 

      <xsl:for-each select="key('byGROUP', GROUP)"> 
       <xsl:sort select="SUBGROUP" order="descending" /> 
       <h2> 
        <xsl:value-of select="SUBGROUP" /> 
       </h2> 

       <p> 
        <xsl:value-of select="NAME" /> 
       </p> 

      </xsl:for-each> 

     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

我試過使用前置兄弟來測試是否查看SUBGROUP,但我發現它無法迭代通過節點,所以也許這不是一個好方法。

+0

歡迎來到Stack Overflow!如果你顯示你已經嘗試了什麼以及它出了什麼問題,那麼幫助你瞭解你的問題在哪裏會更容易。 – 2013-03-11 16:06:20

+0

感謝您的反饋,我按照您的要求更新了問題。 – Proqb 2013-03-11 17:21:59

回答

2

做多個分組的典型方法是使用現有水平的值的串聯與所有父值的鍵值:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes" omit-xml-declaration="yes"/> 
    <xsl:key name="byGROUP" match="RESULTS/RES" use="GROUP" /> 
    <xsl:key name="bySUBGROUP" match="RESULTS/RES" 
      use="concat(GROUP, '+', SUBGROUP)" /> 

    <xsl:template match="RESULTS"> 
    <xsl:apply-templates 
     select="RES[count(. | key('byGROUP', GROUP)[1]) = 1] 
       /GROUP"> 
     <xsl:sort select="." order="ascending" /> 
    </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="GROUP"> 
    <h1> 
     <xsl:value-of select="." /> 
    </h1> 
    <xsl:variable name="thisGroup" select="key('byGROUP', .)" /> 
    <xsl:apply-templates 
     select="$thisGroup[count(. | 
          key('bySUBGROUP', concat(GROUP, '+', SUBGROUP))[1]) 
         = 1] 
         /SUBGROUP"> 
     <xsl:sort select="." order="ascending" /> 
    </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="SUBGROUP"> 
    <h2> 
     <xsl:value-of select="." /> 
    </h2> 
    <xsl:apply-templates select="key('bySUBGROUP', concat(../GROUP, '+', .))"/> 
    </xsl:template> 

    <xsl:template match="RES"> 
    <p> 
     <xsl:value-of select="NAME" /> 
    </p> 
    </xsl:template> 
</xsl:stylesheet> 

當你的樣品輸入運行,這將產生:

<h1>1</h1> 
<h2>A</h2> 
<p>Alice</p> 
<p>Bart</p> 
<h2>B</h2> 
<p>Keira</p> 
<h1>2</h1> 
<h2>A</h2> 
<p>Mike</p> 
<h2>B</h2> 
<p>Peter</p> 
<p>Olaf</p> 
+0

首先回答,就是這樣! :)很少有測試證實它可以很好地工作。對於像我這樣的xsl初學者來說,開始時並不那麼明顯。謝謝。 – Proqb 2013-03-11 19:22:34

+0

總是樂於幫忙! – JLRishe 2013-03-11 19:28:27