2012-01-31 57 views
2

預先感謝您的時間。我有一個深度嵌套的XML,它需要執行XSLT 1.0轉換(用於pdf生成)。我正在部分粘貼XML,並且已經對此表示歉意!使用Muenchian方法的XSLT多級分組

我根據幾個答案重新調整了XML,我意識到我遇到了更多問題。感謝您的耐心等待。

請讓我知道是否需要任何額外的說明。

輸入XML

<Reports> 
    <Report> 
    <ReportID>R123</ReportID> 
    <ReportName>R123Name</ReportName> 
    <PurchaseTypes> 
     <PurchaseType> 
     <Name>Purchase Type 2</Name> 
     <Areas> 
      <Area> 
      <AreaType>American</AreaType> 
      <AreaName>IL</AreaName> 
      <SaleDetails> 
       <SaleDetail> 
       <SaleDetailID> 
        SD45 
       </SaleDetailID> 
       <Amount> 
        177.3 
       </Amount> 
       </SaleDetail> 
       <SaleDetail> 
       <SaleDetailID> 
        SD56 
       </SaleDetailID> 
       <Amount> 
        123 
       </Amount> 
       </SaleDetail> 
      </SaleDetails> 
      </Area> 
      <Area> 
      <AreaType>American</AreaType> 
      <AreaName>MN</AreaName> 
      <SaleDetails> 
       <SaleDetail> 
       <SaleDetailID> 
        SD19 
       </SaleDetailID> 
       <Amount> 
        19 
       </Amount> 
       </SaleDetail> 

      </SaleDetails> 
      </Area> 
     </Areas> 
     </PurchaseType> 
    </PurchaseTypes> 
    </Report> 
</Reports> 

輸出需要類似下面的圖像

樣照2: https://picasaweb.google.com/lh/photo/hxTUY6Qv_9eJyvxQ-UhQutMTjNZETYmyPJy0liipFm0?feat=directlink

@DevNull,這就是我努力:

<xsl:template match="Report"> 
     <xsl:apply-templates select="ReportID|PurchaseTypes/PurchaseType"></xsl:apply-templates> 
     </xsl:template> 

<xsl:template match="PurchaseType"> 
    <xsl:apply-templates select="Name|Areas/Area/AreaType"></xsl:apply-templates> 
    </xsl:template> 

但是我看到了美式區域兩次。 事情是這樣的: R123 採購類型2 美國 美國

+0

您所要求的輸出缺少必要的縮進,因此無法從中猜出任何分組。請修改並更正。 – 2012-02-01 04:53:10

+0

感謝Dimitre;我正在澄清我的問題以獲取更多詳細信息。這是我需要的格式,但我會嘗試重新縮進一點。 – m27 2012-02-01 22:52:52

回答

1

看你的XML輸入和期望輸出的圖像的Excel,它仍然看起來並不像你需要的分組。XML似乎已經按照您需要格式化您的報告的方式進行組織。

下面是使用XSL-FO創建PDF的示例。

你的XML輸入:

<Reports> 
    <Report> 
    <ReportID>R123</ReportID> 
    <ReportName>R123Name</ReportName> 
    <PurchaseTypes> 
     <PurchaseType> 
     <Name>Purchase Type 2</Name> 
     <SaleDetails> 
      <SaleDetail> 
      <SaleDetailID> 
       SD45 
      </SaleDetailID> 
      <Amount> 
       177.3 
      </Amount> 
      </SaleDetail> 
      <SaleDetail> 
      <SaleDetailID> 
       SD56 
      </SaleDetailID> 
      <Amount> 
       123 
      </Amount> 
      </SaleDetail> 
     </SaleDetails> 
     </PurchaseType> 
    </PurchaseTypes> 
    </Report> 
    <Report> 
    <ReportID>R234</ReportID> 
    <ReportName>R234Name</ReportName> 
    <PurchaseTypes> 
     <PurchaseType> 
     <Name>Purchase Type 1</Name> 
     <SaleDetails> 
      <SaleDetail> 
      <SaleDetailID> 
       SD456 
      </SaleDetailID> 
      <Amount> 
       17.3 
      </Amount> 
      </SaleDetail> 
      <SaleDetail> 
      <SaleDetailID> 
       SD556 
      </SaleDetailID> 
      <Amount> 
       23 
      </Amount> 
      </SaleDetail> 
     </SaleDetails> 
     </PurchaseType> 
     <PurchaseType> 
     <Name>Purchase Type 2</Name> 
     <SaleDetails> 
      <SaleDetail> 
      <SaleDetailID> 
       SD451 
      </SaleDetailID> 
      <Amount> 
       12.2 
      </Amount> 
      </SaleDetail> 
     </SaleDetails> 
     </PurchaseType> 
    </PurchaseTypes> 
    </Report> 
</Reports> 

這個樣式錶轉化:

<xsl:stylesheet version="1.0" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="node()|@*"> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:template> 

    <xsl:attribute-set name="reportBorder" use-attribute-sets="reportPadding"> 
    <xsl:attribute name="border">solid 1pt black</xsl:attribute> 
    </xsl:attribute-set> 

    <xsl:attribute-set name="reportPadding"> 
    <xsl:attribute name="padding-left">4pt</xsl:attribute> 
    <xsl:attribute name="padding-right">4pt</xsl:attribute> 
    <xsl:attribute name="padding-top">2pt</xsl:attribute> 
    <xsl:attribute name="padding-bottom">2pt</xsl:attribute>  
    </xsl:attribute-set> 

    <xsl:template match="Reports"> 
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> 
     <fo:layout-master-set> 
     <fo:simple-page-master master-name="my-page" page-width="8.5in" page-height="11in"> 
      <fo:region-body margin="1in" margin-top="1.5in" margin-bottom="1.5in"/> 
     </fo:simple-page-master> 
     </fo:layout-master-set> 
     <fo:page-sequence master-reference="my-page"> 
     <fo:flow flow-name="xsl-region-body"> 
      <xsl:apply-templates/> 
     </fo:flow> 
     </fo:page-sequence> 
    </fo:root> 
    </xsl:template> 

    <xsl:template match="Report"> 
    <fo:table margin-bottom="12pt" border="solid 2pt black" width="2.5in"> 
     <fo:table-column column-number="1" width="1.5in"/> 
     <fo:table-column column-number="2" width="1in"/> 
     <fo:table-body> 
     <xsl:apply-templates select="ReportID|PurchaseTypes/PurchaseType/Name"/> 
     </fo:table-body> 
    </fo:table> 
    </xsl:template> 

    <xsl:template match="ReportID"> 
    <fo:table-row> 
     <fo:table-cell background-color="#FFFF00" border-top="solid 2pt black" border-left="solid 2pt black" xsl:use-attribute-sets="reportPadding"> 
     <fo:block><xsl:value-of select="."/></fo:block> 
     </fo:table-cell> 
     <fo:table-cell border-top="solid 2pt black" border-right="solid 2pt black"> 
     <fo:block>&#xA0;</fo:block> 
     </fo:table-cell> 
    </fo:table-row>  
    </xsl:template> 

    <xsl:template match="Name"> 
    <xsl:if test="ancestor-or-self::PurchaseType[preceding-sibling::PurchaseType]"> 
     <fo:table-row border-left="solid 2pt black"> 
     <fo:table-cell> 
      <fo:block>&#xA0;</fo:block> 
     </fo:table-cell> 
     <fo:table-cell> 
      <fo:block>&#xA0;</fo:block> 
     </fo:table-cell> 
     </fo:table-row> 
    </xsl:if> 
    <fo:table-row> 
     <fo:table-cell background-color="#DDA0DD" border-left="solid 2pt black" xsl:use-attribute-sets="reportPadding"> 
     <fo:block><xsl:value-of select="normalize-space(.)"/></fo:block> 
     </fo:table-cell> 
     <fo:table-cell border-right="solid 2pt black"> 
     <fo:block>&#xA0;</fo:block> 
     </fo:table-cell> 
    </fo:table-row>  
    <fo:table-row background-color="#8FBC8F"> 
     <fo:table-cell xsl:use-attribute-sets="reportBorder"> 
     <fo:block>Sale Detail ID</fo:block> 
     </fo:table-cell> 
     <fo:table-cell xsl:use-attribute-sets="reportBorder"> 
     <fo:block>Amount</fo:block> 
     </fo:table-cell> 
    </fo:table-row> 
    <xsl:apply-templates select="following-sibling::SaleDetails/SaleDetail"/> 
    </xsl:template> 

    <xsl:template match="SaleDetail"> 
    <fo:table-row> 
     <fo:table-cell xsl:use-attribute-sets="reportBorder"> 
     <fo:block><xsl:value-of select="normalize-space(SaleDetailID)"/></fo:block> 
     </fo:table-cell> 
     <fo:table-cell xsl:use-attribute-sets="reportBorder" text-align="right"> 
     <fo:block><xsl:value-of select="normalize-space(Amount)"/></fo:block> 
     </fo:table-cell> 
    </fo:table-row>  
    </xsl:template> 
</xsl:stylesheet> 

產生以下PDF:

enter image description here

希望發生的事情並不在FO丟失標記。

+0

謝謝Zachary和DevNull。這正是我正在尋找的,但是我很抱歉,因爲我想請求更多的解釋,因爲我仍然沒有100%清楚。您可能會記得,我發佈的早期示例XML有多層嵌套。我正在編輯我早先的XML一次。我感謝你的耐心和你的解釋一樣,我的概念越來越清晰,我可以更加細化我的問題。對於更新的XML,我主要介紹了另一層嵌套來處理我的問題。 – m27 2012-02-02 20:47:43

+0

無法爲FO/PDF做+2,所以,只需+1,抱歉。 – 2012-02-02 22:27:42

+0

謝謝你的回答和澄清。 – m27 2012-02-03 05:23:25

0

這不是一組問題。我很新的Meunchian自己,所以我甚至不能真正說明如何使用它,所以我會推遲到W3C

鍵提供了一種與包含一個隱含的 文件工作交叉參考結構。

Jeni Tennison

分組是在XSLT樣式表中一個共同的問題:你怎麼走元素的 列表,並將它們分成不同的組。有些情況下,你需要做的這兩個主要 情況:

  • 的內容(例如組全部由英國諾丁漢的人在一起)
  • 分組按位置分組(如組每單10項)

因爲所有的數據都是非常分層的,所以很容易就可以一路順着樹從樹下移到後代組。

下面是完整的解決方案:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:variable name="newline" select="'&#13;&#10;'"/> 
    <xsl:variable name="tab" select="'&#9;'"/> 

    <xsl:template match="/Reports"> 
    <xsl:apply-templates select="descendant::Report"/> 
    </xsl:template> 

    <xsl:template match="Report"> 
    <xsl:value-of select="ReportID"/> 
    <xsl:value-of select="$newline"/> 
    <xsl:apply-templates select="descendant::PurchaseType"/> 
    </xsl:template> 

    <xsl:template match="PurchaseType"> 
    <xsl:value-of select="Name"/> 
    <xsl:value-of select="$newline"/> 
    <xsl:text>Sale Detail ID</xsl:text> 
    <xsl:value-of select="concat($tab,$tab)"/> 
    <xsl:text>Amount</xsl:text> 
    <xsl:value-of select="$newline"/> 
    <xsl:apply-templates select="descendant::SaleDetail"/> 
    <xsl:value-of select="$newline"/> 
    </xsl:template> 

    <xsl:template match="SaleDetail"> 
    <xsl:value-of select="normalize-space(SaleDetailID)"/> 
    <xsl:value-of select="concat($tab,$tab,$tab)"/> 
    <xsl:value-of select="normalize-space(Amount)"/> 
    <xsl:value-of select="$newline"/> 
    </xsl:template> 
</xsl:stylesheet> 

產生如下(我不得不選項卡轉換爲空格這麼格式)。的理由不符合你的形象:

R123 
Purchase Type 2 
Sale Detail ID    Amount 
SD45      177.3 
SD56      123 

R234 
Purchase Type 1 
Sale Detail ID    Amount 
SD456      17.3 
SD556      23 

Purchase Type 2 
Sale Detail ID    Amount 
SD451      12.2 
+0

非常感謝Zachary爲你的指點。我想我沒有正確地澄清自己。問題在於,某個報告可能僅針對品牌類型1銷售。同樣,銷售可能僅針對美國地區類型等。因此,我在考慮分組。 如果我嘗試使用// BrandType,實質上,我將爲XML文檔中的所有品牌類型獲取saledetail,而不僅僅是給定報表的該區域類型下的品牌類型。我正在澄清我的問題以獲取更多詳細信息。 – m27 2012-02-01 22:50:48

+0

@questiontoask:好的。請記住,選擇'// BrandType'只是一個開始的建議。就目前來看,你的問題給試圖回答的人帶來了很大的負擔,要弄清楚「......某一報告可能僅銷售品牌類型1的可能性」。意思是,銷售......「是指。您能否提供更小,更具體的XML源代碼和適當格式的輸出來突出這些要求? – 2012-02-02 00:42:27

+0

我縮短了XML。此外,由於我無法上傳圖片(作爲新用戶),因此我發佈了一個Picasa鏈接,用於上傳所需的輸出圖像。再次感謝你的幫助。 – m27 2012-02-02 04:15:45