2013-10-23 19 views
-1

考慮到下面的XSLT和XML:排序XML數據和應用XSLT轉換

XSLT

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
       > 
    <xsl:template match="/*"> 
    <html> 
     <head> 
     <style type="text/css"> 
      .exceed{background:yellow;} 
      table{border-collapse:collapse; 
      cellspacing:0px; 
      cellpadding:5px; 
      width:90%;} 
      .total-hours{background-color:#808080;} 
      .total-row-text{font-weight:bold;} 
      .report-header{background-color:#C6BD94;} 
      /*{background-color:#FFFFBB; 

      }*/ 
      .Report { width: 90%; font-family:Cambria,serif; font-size:14px } 
      .Report th { border: solid 1px } 
      .Report td { padding:5px; padding-left:20px; padding-right:20px; border: solid 1px } 
      tr{background-color:#FFFFBB;} 
     </style> 
     </head> 

     <body> 
     <div class='ReportDescription'> 
     </div> 
     <div class='ReportDate'> 
     </div> 
     <table class="Report"> 
      <tr class="report-header"> 
      <xsl:for-each select="headers/header"> 

       <th class="report-Header"> 
       <xsl:value-of select="title"/> 
       </th> 
      </xsl:for-each> 
      </tr> 
      <xsl:apply-templates mode="Gray" select="PreviousDays/Employee[@total]"> 
      </xsl:apply-templates> 
      <xsl:apply-templates mode="normal" select="PreviousDays/Employee[not(@total)]"> 
      </xsl:apply-templates> 
     </table> 
     </body> 
    </html> 
    </xsl:template> 
    <xsl:template match="PreviousDays/Employee" mode="Gray">  
    <tr class="total-hours"> 
     <td class="total-row-text"> 
     <xsl:value-of select="WorkingDate"/> 
     </td> 
     <td class="total-row-text"> 
     <xsl:value-of select="@Name"/> 
     </td> 

     <td class="total-row-text"> 
     <xsl:value-of select="totalhours"/> 
     </td> 
     <td class="total-row-text"> 
     <xsl:value-of select="Description"/> 
     </td> 
    </tr> 

    </xsl:template> 
    <xsl:template mode="normal" match="PreviousDays/Employee"> 

    <tr class="exceed"> 
     <td> 
     <xsl:value-of select="WorkingDate"/> 
     </td> 
     <td> 
     <xsl:value-of select="@Name"/> 
     </td> 

     <td> 
     <xsl:value-of select="HoursOnProject"/> 
     </td>   
     <td> 
     <xsl:value-of select="Department"/> 
     </td> 
    </tr> 
    </xsl:template> 

</xsl:stylesheet> 

XML

<root> 
    <headers> 
    <header><title>Header1</title></header> 
    <header><title>Header2</title></header> 
    <header><title>Header3</title></header> 
    <header><title>Header4</title></header> 
    </headers> 
    <PreviousDays> 
    <Employee Name="Martin Davis"> 
     <WorkingDate>9/12/2013</WorkingDate> 
     <HoursOnProject>8</HoursOnProject> 
     <Description>Description here</Description> 
    </Employee> 
    <Employee total="true" Name="Martin Davis"> 
     <WorkingDate>9/12/2013</WorkingDate> 
     <HoursOnProject></HoursOnProject> 
     <Description>Description here</Description> 
     <totalhours>8</totalhours> 
    </Employee> 
    <Employee Name="Caroline Jackson"> 
     <WorkingDate>9/15/2013</WorkingDate> 
     <HoursOnProject>8.50</HoursOnProject> 
     <Description>Description here</Description> 
    </Employee> 
    <Employee total="true" Name="Caroline Jackson"> 
     <WorkingDate>9/15/2013</WorkingDate> 
     <HoursOnProject></HoursOnProject> 
     <Description>Description here</Description> 
     <totalhours>10</totalhours> 
    </Employee> 
    </PreviousDays> 
</root> 

我怎樣才能確保數據按名稱屬性和WorkingDate進行排序或分組,以便每個人的總行數記錄直接出現在任何正常行之後?最好不使用for-each或type型語句。 (這些類型的解決方案,歡迎雖然)。

所需的輸出

<table class="Report"> 
     <tr class="report-header"> 
     <th class="report-Header">Header1</th> 
     <th class="report-Header">Header2</th> 
     <th class="report-Header">Header3</th> 
     <th class="report-Header">Header4</th> 
     </tr> 
     <tr class="exceed"> 
     <td>9/12/2013</td> 
     <td>Martin Davis</td> 
     <td>8</td> 
     <td></td> 
     </tr> 
     <tr class="total-hours"> 
     <td class="total-row-text">9/12/2013</td> 
     <td class="total-row-text">Martin Davis</td> 
     <td class="total-row-text">8</td> 
     <td class="total-row-text">Description here</td> 
     </tr> 
     <tr class="exceed"> 
     <td>9/15/2013</td> 
     <td>Caroline Jackson</td> 
     <td>8.50</td> 
     <td></td> 
     </tr> 
     <tr class="total-hours"> 
     <td class="total-row-text">9/15/2013</td> 
     <td class="total-row-text">Caroline Jackson</td> 
     <td class="total-row-text">10</td> 
     <td class="total-row-text">Description here</td> 
     </tr>  
    </table> 

請注意,我不想要切換到XSLT 2.0如果我能避免它。

回答

0

你可以試試這個XSL:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> 

<!-- Employee without @total grouped by Name --> 
<xsl:key name="employees-by-name" match="/root/PreviousDays/Employee[not(@total)]" use="@Name" /> 
<!-- Employee with @total grouped by Name --> 
<xsl:key name="employees-total-by-name" match="/root/PreviousDays/Employee[@total]" use="@Name" /> 

<!-- templates for writting the trs --> 
<xsl:template match="Employee" mode="css-class"> 
    <tr class="exceed"> 
    <xsl:apply-templates select="." mode="contents" /> 
    </tr> 
</xsl:template> 
<xsl:template match="Employee[@total='true']" mode="css-class"> 
    <tr class="total-hours"> 
    <xsl:apply-templates select="." mode="contents" /> 
    </tr> 
</xsl:template> 

<!-- template for writting the tds --> 
<xsl:template match="Employee" mode="contents"> 
    <td><xsl:value-of select="WorkingDate"/></td> 
    <td><xsl:value-of select="@Name"/></td> 
    <td><xsl:value-of select="HoursOnProject"/></td>   
    <td><xsl:value-of select="Department"/></td> 
</xsl:template> 


<xsl:template match="/root"> 
    <html> 
    <head> 
     <style type="text/css"> 
     .exceed{background:yellow;} 
     table{border-collapse:collapse;cellspacing:0px;cellpadding:5px;width:90%;} 
     .total-hours td{background-color:#808080;font-weight:bold;} 
     .report-header{background-color:#C6BD94;} 
     .Report {width: 90%; font-family:Cambria,serif; font-size:14px;} 
     .Report th {border: solid 1px;} 
     .Report td {padding:5px; padding-left:20px; padding-right:20px; border: solid 1px;} 
     tr{background-color:#FFFFBB;} 
     </style> 
    </head> 
    <body> 
     <div class='ReportDescription'> 
     </div> 
     <div class='ReportDate'> 
     </div> 
     <table class="Report"> 
     <tr class="report-header"> 
      <xsl:for-each select="headers/header"> 
      <th class="report-Header"> 
       <xsl:value-of select="title"/> 
      </th> 
      </xsl:for-each> 
     </tr> 
     <!-- loop for each Employee which does not have a preceding-sibling with same @Name --> 
     <xsl:for-each select="PreviousDays/Employee[not(@Name = preceding-sibling::Employee/@Name)]"> 
      <!-- apply templates for those elements with same @Name and not @total attribute --> 
      <xsl:apply-templates select="key('employees-by-name',@Name)" mode="css-class"> 
      <xsl:sort select="WorkingDate" /> 
      </xsl:apply-templates> 
      <!-- apply templates for those -or that- elements with same @Name and with @total attribute --> 
      <xsl:apply-templates select="key('employees-total-by-name',@Name)" mode="css-class" /> 
     </xsl:for-each> 
     </table> 
    </body> 
    </html> 
</xsl:template> 

</xsl:stylesheet>