2012-01-03 38 views
3

源XML:XSLT:小計

<Root> 
    <Data> 
     <Code>A</Code> 
     <Value>10</Value> 
    </Data> 
    <Data> 
     <Code>A</Code> 
     <Value>10</Value> 
    </Data> 
    <Data> 
     <Code>B</Code> 
     <Value>10</Value> 
    </Data> 
    <Data> 
     <Code>A</Code> 
     <Value>2</Value> 
    </Data> 
    <Data> 
     <Code>C</Code> 
     <Value>10</Value> 
    </Data> 
    <Data> 
     <Code>A</Code> 
     <Value>5</Value> 
    </Data> 
    <Data> 
     <Code>B</Code> 
     <Value>4</Value> 
    </Data> 
    <Data> 
     <Code>A</Code> 
     <Value>10</Value> 
    </Data> 
    <Data> 
     <Code>C</Code> 
     <Value>10</Value> 
    </Data> 
    <Data> 
     <Code>B</Code> 
     <Value>10</Value> 
    </Data> 
    <Data> 
     <Code>A</Code> 
     <Value>10</Value> 
    </Data> 
    <Data> 
     <Code>C</Code> 
     <Value>5</Value> 
    </Data> 
.... 
</Root> 

XSL-FO代碼:

我的代碼(XSL-FO)含有3列,其中每列包含 'A', 'B' 的內容, 「C」

<fo:table-body> 
    <xfd:table-row-repeat xpath="Root/Data" font-family="Arial Narrow" font-size="10pt" padding-after="0.55cm"> 
     <xsl:if test="Code='A'"> 
     <fo:table-cell> 
     <fo:block height="12pt">Value 
     </fo:block> 
     </fo:table-cell> 
     <fo:table-cell> 
     <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
      <xsl:value-of select="Value" /> 
     </fo:block> 
     </fo:table-cell> 
     <fo:table-cell> 
     <fo:block height="12pt">Points</fo:block> 
     </fo:table-cell> 
     </xsl:if> 
    </xfd:table-row-repeat> 
</fo:table-body> 

對於每個要顯示的列「B」 &「C」 在表尺我已經獲得的「A」次全這些,「B」的值相同的代碼,「C」

<fo:table-body> 
    <xfd:table-row-repeat xpath="Root/Data" font-family="Arial Narrow" font-size="10pt" padding-after="0.55cm"> 
     <xsl:if test="Code='A'"> 
     <fo:table-cell> 
     <fo:block height="12pt">SubTotal 
     </fo:block> 
     </fo:table-cell> 
     <fo:table-cell> 
     <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
      <--Here Sum of first 15 A's. if the A's or B's or C's exceed by 15, then the table flows to 2nd Page. In that case, 1st Page table-footer shows individual subtotals of first 15 A's, 15 B's and C's. In 2nd Page, the subtotals should contain Subtotal of first 15 A's+ Succeeding A's, in the same way B's and C's --> 
     </fo:block> 
     </fo:table-cell> 
     <fo:table-cell> 
     <fo:block height="12pt">Points</fo:block> 
     </fo:table-cell> 
     </xsl:if> 
    </xfd:table-row-repeat> 
</fo:table-body> 

這裏被示出爲僅一列中的XSL-FO代碼(根/數據/代碼= 'A'),所述其他2個欄( 'B' & 'C')由相同的代碼。

條件在詳情:

Condition 1): when Root/Data/Code = 'A' or 'B' or 'C' 
    i need individual totals of 'A', 'B' and 'C' in Table-Footer individual Column. 

Condition 2): inturn if individual count(Root/Data/Code) of 'A', 'B' & 'C' crosses 15.   Then Page flows to 2nd Page then Table-Footer in 2nd Page needs to contains subtotal of first 15 A's + the sum of succeeding A's in the same way for B's And C's 

即如果20 A的,10 B的和25℃的存在於源XML。通過Code標籤分組計算 'A', 'B' 和 'C' 的總和鍵:

In 1st Page, Table-Footer 

SubtotalI(Value of 15 A's)= 
SubtotalII(Value 10 B's)= 
SubtotalIII(Value 15 C's)= 

In 2nd Page, Table-Footer 

SubtotalI(15 A's+ next 5 A's)= 
SubtotalII(Value 10 B's)= <!--No Change as count of B's is less than 15 --> 
SubtotalIII(15 C's + next 10 C's)= 

我試圖使用XSL這個邏輯。由於我是XSLT新手,我發現使用xsl:key解決這個邏輯太困難了。任何人都可以幫助解決這個邏輯嗎?

在此先感謝

+0

這是*不是*你應該在XSLT中做的事情! XSL轉換非常適合轉換文檔結構。它們不適合應用邏輯和條件計算。 – ColinE 2012-01-03 17:18:34

+0

你能否重申你的問題?目前還不清楚你期望得到什麼。 – Lloyd 2012-01-03 17:26:42

+0

我讓我的問題更清晰。現在檢查 – BVS 2012-01-04 02:39:00

回答

0

您試圖達到的目標有幾個難點。計算給定點的小計實際上是最簡單的。你只需要前面的軸和總和來計算的話:

sum(preceding::Value[../Code = 'A']) 

要包括當前值以及使用UNION操作是這樣的:

sum(Value[../Code = 'A'] | preceding::Value[../Code = 'A']) 

一個更大的困難是表現出不同的在每個頁面上的表'頁腳'。頁眉和頁腳在頁面上自動重複,但表格跨越的所有頁面內容相同。我看到的唯一解決方案是自己打破桌子,每次添加不同的桌腳。

到目前爲止,最簡單的方法是每次只取一個固定數量的數據元素,並在一個單獨的表中顯示這些元素。您可以循環遍歷A,B和C類型,每個值爲單獨一行。這樣,表格總是具有相同的行數。您可以嘗試使用可包含的數字來確定在一頁上適合的人數。

以下代碼返回一個包含前10個數據值的表。 A,B和C值彼此平直放置,但如果您願意,您可以分別將它們放置在左側,中間和右側。在表的底部添加小計A,B和C

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

    <xsl:template match="/"> 
     <fo:root> 
      <fo:layout-master-set> 
       <fo:simple-page-master master-name="global"> 
        <fo:region-body/> 
       </fo:simple-page-master> 
      </fo:layout-master-set> 

      <fo:page-sequence master-reference="global"> 
       <fo:flow flow-name="xsl-region-body"> 

        <fo:block> 
         <fo:table table-layout="fixed" width="150mm" border-style="solid"> 
          <fo:table-column column-width="50mm"/> 
          <fo:table-column column-width="50mm"/> 
          <fo:table-column column-width="50mm"/> 

          <fo:table-body font-size="7pt"> 
           <xsl:for-each select="/Root/Data[10 >= position()]"> 
            <fo:table-row border-style="solid"> 
             <fo:table-cell> 
              <fo:block height="12pt"> 
               <xsl:value-of select="Code" /> 
              </fo:block> 
             </fo:table-cell> 
             <fo:table-cell> 
              <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
               <xsl:value-of select="Value" /> 
              </fo:block> 
             </fo:table-cell> 
             <fo:table-cell> 
              <fo:block height="12pt">Points</fo:block> 
             </fo:table-cell> 
            </fo:table-row> 

            <xsl:if test="position() = last()"> 
             <fo:table-row border-style="solid"> 
              <fo:table-cell> 
               <fo:block height="12pt">Subtotal A</fo:block> 
              </fo:table-cell> 
              <fo:table-cell> 
               <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
                <xsl:value-of select="sum(preceding::Value[../Code = 'A'] | Value[../Code = 'A'])" /> 
               </fo:block> 
              </fo:table-cell> 
              <fo:table-cell> 
               <fo:block height="12pt">Points</fo:block> 
              </fo:table-cell> 
             </fo:table-row> 
             <fo:table-row border-style="solid"> 
              <fo:table-cell> 
               <fo:block height="12pt">Subtotal B</fo:block> 
              </fo:table-cell> 
              <fo:table-cell> 
               <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
                <xsl:value-of select="sum(preceding::Value[../Code = 'B'] | Value[../Code = 'B'])" /> 
               </fo:block> 
              </fo:table-cell> 
              <fo:table-cell> 
               <fo:block height="12pt">Points</fo:block> 
              </fo:table-cell> 
             </fo:table-row> 
             <fo:table-row border-style="solid"> 
              <fo:table-cell> 
               <fo:block height="12pt">Subtotal C</fo:block> 
              </fo:table-cell> 
              <fo:table-cell> 
               <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
                <xsl:value-of select="sum(preceding::Value[../Code = 'C'] | Value[../Code = 'C'])" /> 
               </fo:block> 
              </fo:table-cell> 
              <fo:table-cell> 
               <fo:block height="12pt">Points</fo:block> 
              </fo:table-cell> 
             </fo:table-row> 
            </xsl:if> 
           </xsl:for-each> 
          </fo:table-body> 
         </fo:table> 
        </fo:block> 

       </fo:flow> 
      </fo:page-sequence> 

     </fo:root> 
    </xsl:template> 

</xsl:stylesheet> 

你仍然需要一些東西來決定你需要多少N個數據的表需要,然後做一些遞歸調用輸出所有這些。希望這一刻足以讓你重新開始! PS:我注意到你使用的是xfd前綴。這看起來像你正在與Ecrion的XF設計師合作。我不是很熟悉它。上面的代碼是一個普通的XSLT 1.0解決方案。不知道它在XF設計器中的作用,請讓我知道..

+0

@BVS愚蠢的我,我完全忘記佛:標記。應該可以在包含A,B和C的運行總數(單獨的標記類名稱)的每個表格單元格中放置fo:marker。您應該可以使用fo:retrieve-table-marker將當前頁面的最後一個標記值拖入表格頁腳。我試圖改變我的例子,但FOP似乎不支持這個。所以可能值得一試,但你可能會發現你的處理器也不支持它。 HTH! – grtjn 2012-01-06 06:43:58

+0

fo:marker幫助我很多..謝謝噸傢伙 – BVS 2012-01-06 18:42:35