2013-08-01 83 views
2

我試圖將一個無所不包的xsl樣式表更改爲兩階段樣式表設置,其中第一步將xml轉換爲「理想」xml,第二步步驟僅僅是格式化。如何使用XSL轉換管道或兩階段轉換

最初,我們有這個XML(多餘的部分去掉)

<?xml-stylesheet type="text/xsl" href="xsl/storeFinancialReport.xsl" ?> 
<storeFinancialReport> 
    <ProductGroupEntry><ProductGroupCode>xz1</ProductGroupCode><ProductGroup>thing1</ProductGroup><Quantity>0.0000</Quantity><DiscountExcl>0.000000</DiscountExcl><SalesExcl>30.700000</SalesExcl><Sales>35.000000</Sales></ProductGroupEntry> 
    <ProductGroupEntry><ProductGroupCode>xz2</ProductGroupCode><ProductGroup>thing2</ProductGroup><Quantity>13.0000</Quantity><DiscountExcl>0.000000</DiscountExcl><SalesExcl>1480.970000</SalesExcl><Sales>1688.310000</Sales></ProductGroupEntry> 
    <ProductGroupEntry><ProductGroupCode>xz3</ProductGroupCode><ProductGroup>thing3</ProductGroup><Quantity>2.0000</Quantity><DiscountExcl>0.000000</DiscountExcl><SalesExcl>50.730000</SalesExcl><Sales>57.830000</Sales></ProductGroupEntry> 
    <ProductGroupEntry><ProductGroupCode>xz4</ProductGroupCode><ProductGroup>thing4</ProductGroup><Quantity>2.0000</Quantity><DiscountExcl>0.000000</DiscountExcl><SalesExcl>40.450000</SalesExcl><Sales>46.110000</Sales></ProductGroupEntry> 
    <ProductGroupEntry><ProductGroupCode>xz5</ProductGroupCode><ProductGroup>thing5</ProductGroup><Quantity>2.0000</Quantity><DiscountExcl>1.000000</DiscountExcl><SalesExcl>18.000000</SalesExcl><Sales>18.000000</Sales></ProductGroupEntry> 
    <ProductGroupEntry><ProductGroupCode>xz6</ProductGroupCode><ProductGroup>thing6</ProductGroup><Quantity>4.0000</Quantity><DiscountExcl>10.080000</DiscountExcl><SalesExcl>62.900000</SalesExcl><Sales>68.420000</Sales></ProductGroupEntry> 
</storeFinancialReport> 

我現在正試圖創建一個單獨的模板,做翻譯,數額,計算等,可以重複使用,然後纔有在主文件的第二個模板中的html格式導入帶有「濃縮/理想化」模板的文件

到目前爲止,我在下面有理論上稱之爲模板,它將執行等等,商店這在一個變量,然後這個新轉換的XML作爲變量傳遞給HTML格式的模板。

主/ HTML格式的文件

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.1" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:set="http://exslt.org/sets" 
extension-element-prefixes="set"> 
<xsl:output method="html" version="1.0" encoding="UTF-8" 
    indent="yes" /> 

<xsl:include href="scrap_book_enrichment.xsl" /> 

<!-- call Product Group Block --> 

<xsl:template name="ProductGroupBlock"> 
    <xsl:variable name="buildProductGroupResultXml"> <!-- store the results of this template call to this variable --> 
     <xsl:call-template name="buildProductGroup"> 
      <xsl:with-param name="buildProductGroupResults" select="//storeFinancialReport"/> 
     </xsl:call-template> 
    </xsl:variable> 

    <xsl:call-template name="displayProductGroupResults"> 
     <xsl:with-param name="buildProductGroupResults2" select="$buildProductGroupResultXml" /> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="displayProductGroupResults"> 
    <xsl:param name="buildProductGroupResults2" /> 
    <xsl:for-each select="buildProductGroup"> 
     <tr> 
      <td> 
       <xsl:value-of select="/" /> 
      </td> 
      <td colspan="3"> 
       <xsl:value-of 
        select="$buildProductGroupResults2/ProductGroupCodeText/text()" /> 
      </td> 

      <td align="right"> 
       <xsl:value-of 
        select="$buildProductGroupResults2/ProductGroupQuantityText/text()" /> 
      </td> 

      <td align="right"> 
       <xsl:value-of 
        select="$buildProductGroupResults2/ProductGroupDiscountExclText/text()" /> 
      </td> 

      <td align="right"> 
       <xsl:value-of 
        select="$buildProductGroupResults2/ProductGroupSalesExclText/text()" /> 
      </td> 

      <td align="right"> 
       <xsl:value-of 
        select="$buildProductGroupResults2/ProductGroupSalesText/text()" /> 
      </td> 

      <td align="right"> 
       <xsl:value-of 
        select="$buildProductGroupResults2/ProductGroupSalesMinusSalesExclText/text()" /> 
      </td> 

      <td align="right"> 
       <xsl:value-of 
        select="$buildProductGroupResults2/ProductGroupSalesExclPercentage/text()" /> 
      </td> 

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

</xsl:stylesheet> 

第二個導入文件,創建 「理想」 XML

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:set="http://exslt.org/sets" extension-element-prefixes="set"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 


<xsl:template name="buildProductGroup"> 
<xsl:param name="buildProductGroupResults" /> 
<xsl:for-each select="set:distinct($buildProductGroupResults/ProductGroupEntry/ProductGroup)"> 

     <xsl:variable name="ProductGroup"> 
         <xsl:value-of select="text()" /> 
        </xsl:variable> 

        <buildProductGroup> 
         <ProductGroupCodeText><xsl:value-of select="$buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../ProductGroupCode/text()" /><xsl:text> - </xsl:text><xsl:value-of select="$ProductGroup" /></ProductGroupCodeText> 

         <ProductGroupQuantityText><xsl:value-of select="format-number(sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../Quantity/text()), '0')" /> 
         </ProductGroupQuantityText> 

         <ProductGroupDiscountExclText><xsl:value-of 
           select="format-number(sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../DiscountExcl/text()), '###,##0.00')" /> 
           </ProductGroupDiscountExclText> 

         <ProductGroupSalesExclText><xsl:value-of 
           select="format-number(sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../SalesExcl/text()), '###,##0.00')" /> 
           </ProductGroupSalesExclText> 

         <ProductGroupSalesText><xsl:value-of 
           select="format-number(sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../Sales/text()), '###,##0.00')" /> 
           </ProductGroupSalesText> 

         <ProductGroupSalesMinusSalesExclText><xsl:value-of select="format-number(sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../Sales/text()) - sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../SalesExcl/text()),'###,##0.00')" /> 
         </ProductGroupSalesMinusSalesExclText> 

         <ProductGroupSalesExclPercentage> 
          <xsl:choose> 
           <xsl:when test="sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../SalesExcl)=0"> 
            <xsl:text>0.00</xsl:text> 
           </xsl:when> 
           <xsl:when test="sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../SalesExcl)!=0"> 
            <xsl:value-of 
             select="format-number(number(( sum($buildProductGroupResults/ProductGroup[text()=$ProductGroup]/../SalesExcl) div (sum($buildProductGroupResults/SalesExcl))) * 100), '###,##0.00')" /> 
           </xsl:when> 
          </xsl:choose> 
          <xsl:text>%</xsl:text> 
         </ProductGroupSalesExclPercentage> 

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


</xsl:template> 

</xsl:stylesheet> 

我知道這些都是相當矮胖,但我相信我已經儘可能減少它,同時保持它真正的我所需要的。我們有十幾個或更多這樣的部分,但我顯然錯過了實現這一目標的基本步驟。

其目的是爲了「豐富」階段創建一個不同的XML,我所見到的格式xsl處理的「理想」xml。不幸的是,當我在eclipse中通過翻譯器運行這些文件時,它只是將原始xml進行了整理,並刪除了所有格式並將它們拼湊在一塊文本中。可能有幾個想法是我在這裏誤解的,但是一旦我有了這一節,我想其他人將會更容易。

非常感謝

米奇。

[更新日期2013年8月6日]

由於花的時間無法完成這一點,我們將獲得在其他方面的利益,已決定花時間,使我們的報告框架,內在地處理流水線xsls。因此,在一個樣式表中需要此功能不再是一項要求。

+0

你在哪裏運行這個XSLT?在瀏覽器中?我不知道任何支持set的瀏覽器:distinct。 – JLRishe

+0

目前爲了測試目的,我通過Eclipse運行它們,但通常情況下是結束HTML輸出到瀏覽器。 設置:distinct部分不是我添加的東西,它已經在那裏,所以我必須假設它按預期工作。 –

+1

替換模板的一個問題是,在「調用產品組塊」部分中,它使用帶有「select」屬性的xsl:call-template。它應該只有「名稱」屬性。 –

回答

1

您特別針對此問題以及XSLT的方法是錯誤的。

  • 您的輸入已經處於理想狀態,不需要進行「清理」轉換步驟。
  • 不要使用命名模板,使用模板匹配。
  • 請勿使用<xsl:for-each>,使用模板匹配。使用<xsl:key>分組。
  • 不要混合標記和佈局。將與演示文稿相關的東西(align="right")移至CSS。
  • 最後但並非最不重要的:不要(!!!)使用瀏覽器端XSLT。 XSLT用於在服務器上運行。 (是的,我知道,您可以在技術上在瀏覽器中運行XSLT,瀏覽器端XSLT支持最多不一致,請自己省卻頭痛,不要這麼做)。

我不認爲有一種方法可以逐步改進您的XSLT,因此我從頭開始重寫它。

這就是你需要:

<xsl:stylesheet 
    version="1.1" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:set="http://exslt.org/sets" 
    extension-element-prefixes="set" 
    exclude-result-prefixes="set" 
> 
    <xsl:output method="html" version="4.0" encoding="UTF-8" indent="yes" /> 

    <xsl:variable name="currencyFormat" select="'###,##0.00'" /> 
    <xsl:variable name="percentageFormat" select="'0.00%'" /> 

    <xsl:key name="kProductGroup" match="ProductGroupEntry" use="ProductGroupCode" /> 

    <xsl:template match="storeFinancialReport"> 
    <table> 
     <xsl:apply-templates select="ProductGroupEntry" mode="byGroupCode" /> 
    </table> 
    </xsl:template> 

    <xsl:template match="ProductGroupEntry" mode="byGroupCode"> 
    <xsl:variable name="inThisGroup" select="key('kProductGroup', ProductGroupCode)" /> 

    <xsl:if test="generate-id(.) = generate-id($inThisGroup[1])"> 
     <xsl:variable name="sumQuantity"  select="sum($inThisGroup/Quantity)" /> 
     <xsl:variable name="sumDiscountExcl" select="sum($inThisGroup/DiscountExcl)" /> 
     <xsl:variable name="sumSalesExcl" select="sum($inThisGroup/SalesExcl)" /> 
     <xsl:variable name="sumSales"  select="sum($inThisGroup/Sales)" /> 
     <xsl:variable name="netSales"  select="$sumSales - $sumSalesExcl" /> 
     <xsl:variable name="pctSalesExcl"> 
     <xsl:choose> 
      <xsl:when test="$sumSales"> 
      <xsl:value-of select="$sumSalesExcl div $sumSales" /> 
      </xsl:when> 
      <xsl:otherwise>0</xsl:otherwise> 
     </xsl:choose> 
     </xsl:variable> 

     <tr> 
     <td colspan="3"><xsl:value-of select="concat(ProductGroup, ' - ', ProductGroupCode)" /></td> 
     <td class="num"><xsl:value-of select="count($inThisGroup)" /></td> 
     <td class="num"><xsl:value-of select="format-number($sumQuantity, '0')" /></td> 
     <td class="num"><xsl:value-of select="format-number($sumDiscountExcl, $currencyFormat)" /></td> 
     <td class="num"><xsl:value-of select="format-number($sumSalesExcl, $currencyFormat)" /></td> 
     <td class="num"><xsl:value-of select="format-number($sumSales, $currencyFormat)" /></td> 
     <td class="num"><xsl:value-of select="format-number($netSales, $currencyFormat)" /></td> 
     <td class="num"><xsl:value-of select="format-number($pctSalesExcl, $percentageFormat)" /></td> 
     </tr> 
    </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

輸出:

 
thing1 - xz1 1 0 0.00  30.70  35.00  4.30 87.71% 
thing2 - xz2 1 13 0.00 1,480.97 1,688.31 207.34 87.72% 
thing3 - xz3 1 2 0.00  50.73  57.83  7.10 87.72% 
thing4 - xz4 1 2 0.00  40.45  46.11  5.66 87.73% 
thing5 - xz5 1 2 1.00  18.00  18.00  0.00 100.00% 
thing6 - xz6 1 4 10.08  62.90  68.42  5.52 91.93% 

親身體驗:http://www.xmlplayground.com/FmLo2Y

延伸閱讀:

  • This answer解釋XSL鍵是如何工作的以及它們如何用於分組。
  • This answer說明<xsl:apply-templates>如何工作。
+0

哇 - 非常感謝您在回覆中提出瞭如此多的想法和工作。我會申請這個,並讓你知道它是如何發生的。至於你對更多「架構」類型的迴應的評論,我恐怕會直截了當地進入那些擁有系統框架的人羣,這些人在幾年前寫下來,沒有改變它的手段,這消除了瀏覽器端的變化XSLT並添加CSS。至少,我應該能夠利用不同的方法進行循環和分組。 - 再次,非常感謝! –

+0

對不起,另一方面,數據對於報告的這一部分是有利的,但希望我們能夠將新行添加到xml中,稍後將用作報告的摘要部分 - 從而進行總和在可重用的樣式表中與格式分開。 「清理」步驟將包含這些額外的數據要求。我原本應該更清楚一些。 - 換句話說,要求的基礎是計算步驟和格式步驟的分離,所以我們可以重新使用帶格式化xsl的calc步驟以及我理解的csv xsl –

+1

。恐怕沒有辦法在瀏覽器中管理兩個單獨的轉換。你可以使用''或''。然而,在轉換過程中,預先計算值的任何「中間」步驟都會導致所謂的*結果樹片段*(RTF),除非您有權訪問['node- set()'擴展函數](http://www.exslt.org/exsl/functions/node-set/)。既然你似乎參考了EXSLT,我懷疑你會這麼做。無論如何,瀏覽器中的XSLT很麻煩,不靈活和有限。 – Tomalak