2009-11-10 49 views
6

2場我旁邊的xml:分組通過XSL

<page> 
    <document> 
     <id>1001</id> 
     <cur>USD</cur> 
     <date>01.01.2009</date> 
     <amount>10</amount> 
    </document> 
    <document> 
     <id>1001</id> 
     <cur>USD</cur> 
     <date>02.01.2009</date> 
     <amount>15</amount> 
    </document> 
    <document> 
     <id>1001</id> 
     <cur>JPY</cur> 
     <date>01.01.2009</date> 
     <amount>5</amount> 
    </document> 
    <document> 
     <id>1002</id> 
     <cur>USD</cur> 
     <date>01.01.2009</date> 
     <amount>5</amount> 
    </document> 
    ... 
</page> 

,我需要把它轉換成HTML。記錄應當由IDCUR進行分組。並且在每組總數量應該被顯示之後。因此,我們希望是這樣的:

Bill: id=1001, cur=USD 
     date=01.01.2009 amount=10 
     date=02.01.2009 amount=15 
     total amount=25 
Bill: id=1001, cur=JPY 
     date=01.01.2009 amount=5 
     total amount=5 
Bill: id=1002, cur=USD 
     date=01.01.2009 amount=5 
     total amount=5 
... 

我怎樣才能做到這一點使用XSL?

當我試圖找到在谷歌的答案,我發現Muenchian方法,但是當我們通過2場要組結果它太複雜了。我是xsl的初學者,對我來說有點困難。 我還發現XSLT 2.0操作者的for-each-基。它受主流瀏覽器的支持嗎?通常是使用它還是我們只應該依賴xslt 1.0?

+0

XSLT 2.0是不是普遍的是,並依靠這將是一個錯誤,除非你能控制的地方發生轉變。如果我是你,我會給它一些認真的想法,並真正考慮將轉換放在服務器端。 – 2009-11-10 08:51:46

+0

沒有,可惜的是我不能做到這一點,改造的,應在客戶端(這不是我的決定) – Roman 2009-11-10 09:25:24

+0

我知道那種感覺,我從來沒有過任何的成功嘗試在客戶端上運行的轉換,在唯恐不任何跨瀏覽器兼容性。 – 2009-11-10 09:51:48

回答

3

你可以用XSLT 1.0

我這裏使用的是創建一個具有兩個字段,ID和CUR複合鍵的方法做到這一點。之後我將這些模板應用到每個組中的第一個文檔。然後在模板中循環遍歷各個文檔,最後我總結文檔數量字段。

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

<xsl:key name="idcur" match="document" use="concat(id,cur)"/> 

<xsl:template match="/page"> 
    <xsl:apply-templates select="document[generate-id() = generate-id(key('idcur',concat(id,cur))[1])]"/> 
</xsl:template> 

<xsl:template match="document"> 
<xsl:variable name="document" select="key('idcur',concat(id,cur))"/> 
Bill: id=<xsl:value-of select="id"/>, cur=<xsl:value-of select="cur"/> 
    <xsl:for-each select="$document"> 
     date=<xsl:value-of select="date"/> amount=<xsl:value-of select="amount"/> 
    </xsl:for-each> 
     total amount=<xsl:value-of select="sum($document/amount)"/> 
</xsl:template> 
</xsl:stylesheet> 

輸出:

Bill: id=1001, cur=USD 
     date=01.01.2009 amount=10 
     date=02.01.2009 amount=15 
     total amount=25 
Bill: id=1001, cur=JPY 
     date=01.01.2009 amount=5 
     total amount=5 
Bill: id=1002, cur=USD 
     date=01.01.2009 amount=5 
     total amount=5 
+0

對於代碼的可讀性起見,我建議使用''了在XSL文本字符串。這樣,輸出格式更容易控制,並且代碼格式可以具有正確的縮進。 – Tomalak 2009-11-10 09:36:47

+0

有效點!但我認爲這不是最終的解決方案。 – 2009-11-10 09:50:34

+0

非常感謝!這不僅是一個很好的解決方案,而且也是我之前讀過的關於xsl的所有理論的一個有用的例子。 – Roman 2009-11-11 10:54:54

0

Concatening兩個字段創建一個複合鍵是不安全的,除非你有絕對的把握所有這些創建密鑰的唯一身份。 這種方法更安全,我認爲:

<?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:key name="ids" match="document" use="id"/> 
<xsl:key name="currencies" match="document" use="cur"/> 

<xsl:template match="/page"> 
    <xsl:apply-templates select="document[generate-id() = generate-id(key('ids',id)[1])]"/> 
</xsl:template> 

<xsl:template match="document"> 
    <xsl:for-each select="key('ids',id)[generate-id() = generate-id(key('currencies', cur)[id=current()/id][1])]"> 
    <xsl:variable name="bills" select="key('ids', id)[cur = current()/cur]"/> 
    <xsl:text>Bill: id=</xsl:text> 
    <xsl:value-of select="id"/> 
    <xsl:text>, cur=</xsl:text> 
    <xsl:value-of select="cur"/> 
    <xsl:for-each select="$bills"> 
     <xsl:text>&#10;date=</xsl:text> 
     <xsl:value-of select="date"/> 
     <xsl:text> amount=</xsl:text> 
     <xsl:value-of select="amount"/> 
    </xsl:for-each> 
    <xsl:text>&#10;total amount=</xsl:text> 
    <xsl:value-of select="sum($bills/amount)"/> 
    <xsl:text>&#10;</xsl:text> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet>