2010-06-09 55 views
3

我一直在關閉xslt,因爲我成爲了SharePoint管理員,它使用xslt很多顯示列表數據。我最近開始使用它來轉換我使用擴展方法轉換爲xml的數據庫結果。我正在嘗試生成乾淨的html。XSLT爲簡單分組的XML數據使用模板而不是爲每個

我的第一次嘗試,工作正常。然而,我曾經在各地都用過,我從那以後就讀過這是一件壞事。我讀了一堆關於使用密鑰的東西,但我無法理解或者無法使用它。所以我重寫了這個樣式表,下面是它下面的樣式表。它使用沒有for-each的模板。

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="/"> 


<html> 
    <head> 
    <link rel="Stylesheet" type="text/css" href="../styles/BoxReportStyle.css" /> 
    </head> 
    <body> 


    <span class="BoxReport"> 
     <h2>Checked Out Boxes by Department with Transaction History</h2> 

     Count=<xsl:value-of select="count(/CheckedOutBoxes/row) "/> 

    <!-- Get the divisions, since we are groing to group by division--> 
    <xsl:variable name="DivisionList" select="/CheckedOutBoxes/row[ not(Division = preceding-sibling::row/Division) ]/Division" /> 

    <xsl:for-each select="$DivisionList"> 

     <xsl:variable name="DivisionName" select="." /> 

     <h3> 
     <xsl:value-of disable-output-escaping="yes" select="$DivisionName "/> 
     </h3> 

     <!-- Get the list of departments, so we can group by department --> 
     <xsl:variable name="DepartmentList" select="/CheckedOutBoxes/row[ Division = $DivisionName and not(Department = preceding-sibling::row/Department) ]/Department" /> 

     <xsl:for-each select="$DepartmentList"> 
     <xsl:variable name="DepartmentName" select="." /> 

     <h4> 
      <xsl:value-of disable-output-escaping="yes" select="$DepartmentName"/> 
     </h4> 

     <xsl:variable name="Rows" select="/CheckedOutBoxes/row[ Division = $DivisionName and Department = $DepartmentName ]" /> 

     <!-- Start displaying the checked out box information for this division and department --> 
     <table> 
      <th>Box Number</th> 
      <th>Status Name</th> 
      <th>Entry Date</th> 
      <th>Description</th> 

      <xsl:for-each select="$Rows"> 

      <tr> 
       <td> 
       <xsl:value-of select="BoxNumber"/> 
       </td> 
       <td> 
       <xsl:value-of select="StatusName"/> 
       </td> 
       <td> 
       <xsl:value-of select="EntryDate"/> 
       </td> 
       <td width="200px"> 
       <xsl:value-of disable-output-escaping="yes" select="Description"/> 
       </td> 

      </tr> 

      <!-- Now display the transaction history if there is any--> 
      <xsl:if test=" count(Transaction) > 0 "> 
       <tr> 
       <td></td> <!-- One blank row to shift things over--> 
       <td colspan="3"> 
        <!-- Display transaction table--> 
        <table class="SubTable"> 
        <th>Transaction Date</th> 
        <th>Requestor</th> 
        <th>Comments</th> 

        <xsl:for-each select="Transaction" > 
         <tr> 
         <td> 
          <xsl:value-of select="TransactionDate"/> 
         </td> 
         <td> 
          <xsl:value-of select="Requestor"/> 
         </td> 
         <td width="200px"> 
          <xsl:value-of disable-output-escaping="yes" select="Comments"/> 
         </td> 
         </tr> 
        </xsl:for-each> 
        </table> 
       </td> 
       </tr> 
      </xsl:if> 
      </xsl:for-each> 
     </table> 

     </xsl:for-each> 

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


    </body> 

</html> 


    </xsl:template> 



</xsl:stylesheet> 

我現在已經重寫了,要這樣:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 



<xsl:template match="/"> 
<html> 
    <head> 
    <link rel="Stylesheet" type="text/css" href="../styles/BoxReportStyle.css" /> 
    </head> 
    <body> 
    <span class="BoxReport"> 

     <h2>Checked Out Boxes by Department with Transaction History</h2> 

     Count=<xsl:value-of select="count(/CheckedOutBoxes/row) "/> 

     <xsl:apply-templates mode="Division" select="/CheckedOutBoxes/row[ not(Division = preceding-sibling::row/Division) ]"></xsl:apply-templates> 


    </span> 
    </body> 
</html> 
    </xsl:template> 

<xsl:template mode="Division" match="row"> 
<h3> 
    <xsl:value-of select="Division" disable-output-escaping="yes"/> 
</h3> 

<xsl:variable name="DivisionName" select="Division" /> 

<xsl:apply-templates mode="Department" select="/CheckedOutBoxes/row[ Division = $DivisionName and not(Department = preceding-sibling::row/Department) ]"></xsl:apply-templates> 

</xsl:template> 

<xsl:template mode="Department" match="row"> 
<h4> 
    <xsl:value-of select="Department" disable-output-escaping="yes"/> 
</h4> 

<xsl:variable name="DivisionName" select="Division" /> 
<xsl:variable name="DepartmentName" select="Department" /> 

<table> 
    <th>Box Number</th> 
    <th>Status Name</th> 
    <th>Entry Date</th> 
    <th>Description</th> 

    <xsl:apply-templates mode="row" select="/CheckedOutBoxes/row[ Division = $DivisionName and Department = $DepartmentName ]" ></xsl:apply-templates> 

    </table> 



</xsl:template> 

<xsl:template mode="row" match="row"> 

<tr> 
    <td> 
    <xsl:value-of select="BoxNumber"/> 
    </td> 
    <td> 
    <xsl:value-of select="StatusName"/> 
    </td> 
    <td> 
    <xsl:value-of select="EntryDate"/> 
    </td> 
    <td width="200px"> 
    <xsl:value-of disable-output-escaping="yes" select="Description"/> 
    </td> 

</tr> 

<!-- Display Transaction stuff as another row if we have any --> 
<xsl:if test=" count(Transaction) > 0 "> 
    <tr> 
    <td></td><!-- Shift the transaction over--> 
    <td colspan="3"> 
     <!-- Start Transaction Table --> 
     <table class="SubTable"> 
     <th>Transaction Date</th> 
     <th>Requestor</th> 
     <th>Comments</th> 

     <xsl:apply-templates select="Transaction"> 
      <xsl:sort order="descending" select="TransactionDate"/> 
     </xsl:apply-templates> 
     </table> 
    </td> 
    </tr> 
</xsl:if> 

</xsl:template> 


<xsl:template match="Transaction"> 
<tr> 
    <td> 
    <xsl:value-of select="TransactionDate"/> 
    </td> 
    <td> 
    <xsl:value-of select="Requestor"/> 
    </td> 
    <td width="200px"> 
    <xsl:value-of disable-output-escaping="yes" select="Comments"/> 
    </td> 
</tr> 
    </xsl:template> 

</xsl:stylesheet> 

我不包括樣品的輸入和輸出,因爲這是生成的所有汽車。如果需要,我可以花費很多時間,並嘗試製作一些東西。

我的問題是,這是一個更好的方法嗎?另外,如果關鍵方式更好,有人可以解釋它,或提供一個良好解釋的鏈接?

回答

1

基本上使用for-each與模板的問題歸結爲創建可重用,更通用的轉換。

通過使用模板,所有匹配的節點 - 不僅僅是for-each中明確使用的節點 - 可以從模板中受益,這有助於避免重複的代碼,同時將工作表分成更小的單元,從而更易於管理。實際上,它與在命令式編程中調用彼此巨大的過程或更小的過程幾乎相同。

雖然有些人認爲使用模板可能會在某些引擎中表現更好,但我相信這並不會真正有所作爲。

也就是說,你可能想要了解muenchian method(它使用鍵)實際上分組數據,你有重複的鍵。在某些發動機上使用preceding-sibling軸的速度非常緩慢,因此在不是絕對需要時最好避免使用軸。

像這樣的東西應該爲師(未測試)做的伎倆:

<xsl:key name="divisions" match="/CheckedOutBoxes/row/Division" use="." /> 

...

<xsl:apply-templates mode="Division" select="/CheckedOutBoxes/Division[generate-id(.)=generate-id(key('divisions', .))]" /> 
+0

關鍵獲得所有非重複的部門?也許我可以更好地理解它,如果這是它正在做的事情。然後,我可以爲部門基本上與部門相同的另一個關鍵。然後,應用模板的select語句將確保我正在爲當前部門而不是所有部門執行這些部門。 – 249076 2010-06-09 15:39:42

+1

在這種情況下,'key()'函數基本上返回一個包含所有匹配的「Divisions」的節點集。這裏的「魔術」是'generate-id()'函數,該函數返回傳遞給它的節點集中第一個節點的唯一標識ID。因此,將每個'Division'節點ID與具有相同內容的第一個節點的ID進行比較(這就是爲什麼我們使用'key()'函數),因此每個不同的內容僅匹配一次。 – Lucero 2010-06-09 16:05:57

+0

嗯,我認爲在對模板做了一點工作之後,就可以將部門和部門模板與部門和部門相匹配,而不是排成一行,並且實現了我得到的工作,而不是前面的兄弟姐妹。我現在明白了一切,但希望在學習之後我會開始更好地理解它。 – 249076 2010-06-09 16:52:47

1

了 「每個」 模板是XSLT的一個很好的功能。

使用「模板」而不是「for-each」的建議主要是關於可能濫用XSLT處理模型的建議。

在你的例子中很清楚:一個樸素的「模板」和許多「for-each」指導過程。

XSLT本身的關鍵用途是關於性能。它的用處在於替換涉及重複傳輸輸入樹中許多節點的XPath表達式。 Muenchian分組方法是鍵的特殊用法。簡單的分組可以在不使用密鑰的情況下達到最佳效果。

另一方面,人口是轉型的特例。我認爲維護將XHTML語義與XSLT轉換分開會更好。以www.aranedabienesraices.com.ar爲例。

+0

我想我看到模板的位置,把事情分解了。這幾乎就像函數調用一樣。因此,通過匹配「/」我可以看到整體佈局,然後我可以按照應用模板來逐步完成轉換。我可能會保留兩個樣式表。 – 249076 2010-06-09 15:50:15

相關問題