1

私は XSLT の初心者で、Muenchian のグループ化方法について混乱しています。ここに私のXML文書があります

<?xml   version='1.0'?> 
<?xml-stylesheet type="text/xsl"    href="test.xslt"?>
<catalog>
    <cd PurchaseDate="20000101">
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <quantity>20</quantity>
        <price>10.90</price>
    </cd>
    <cd PurchaseDate="20000101">
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <quantity>10</quantity>
        <price>9.90</price>
    </cd>
    <cd PurchaseDate="20000102">
        <title>Greatest Hits</title>
        <artist>Dolly Parton</artist>
        <country>USA</country>
        <quantity>15</quantity>
        <price>9.90</price>
    </cd>
    <cd PurchaseDate="20000101">
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <quantity>5</quantity>
        <price>10.20</price>
    </cd>
    <cd PurchaseDate="20000103">
        <title>Eros</title>
        <artist>Eros Ramazzotti</artist>
        <country>EU</country>
        <quantity>6</quantity>
        <price>9.90</price>
    </cd>
    <cd PurchaseDate="20000103">
        <title>One night only</title>
        <artist>Bee Gees</artist>
        <country>UK</country>
        <quantity>16</quantity>
        <price>10.90</price>
    </cd>
    <cd PurchaseDate="20000102">
        <title>Sylvias Mother</title>
        <artist>Dr.Hook</artist>
        <country>UK</country>
        <quantity>3</quantity>
        <price>8.10</price>
    </cd>
    <cd PurchaseDate="20000101">
        <title>Maggie May</title>
        <artist>Rod Stewart</artist>
        <country>UK</country>
        <quantity>8</quantity>
        <price>8.50</price>
    </cd>
    <cd PurchaseDate="20000103">
        <title>Romanza</title>
        <artist>Andrea Bocelli</artist>
        <country>EU</country>
        <quantity>30</quantity>
        <price>10.80</price>
    </cd>
</catalog>

そしてXSLT

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" indent="yes" />
    <xsl:key name="kByCountry" match="cd" use="country" />
    <xsl:output method="html" />
    <xsl:template match="catalog">
        <html>
            <body>
                <table border="1">
                    <xsl:for-each select="cd[count(.|key('kByCountry',country)[1]) = 1]">
                        <xsl:sort select="country" />
                        <tr bgcolor="#9acd32">
                            <td colspan="4">Country:<xsl:value-of select="country" /></td>
                        </tr>
                        <tr>
                            <td>Purchase Date</td>
                            <td>Quantity</td>
                            <td>Unit Price</td>
                            <td>Total</td>
                        </tr>
                        <tr>
                            <td>?date?</td>
                            <td><xsl:value-of select="quantity" />  </td>
                            <td><xsl:value-of select="price" /></td>
                            <td><xsl:value-of select="price*quantity" /></td>
                        </tr>
                        <tr>
                            <td colspan="3" align="right">Sub-total</td>
                            <td>?how to count subtotal together?</td>
                        </tr>
                    </xsl:for-each>
                    <tr>
                        <td colspan="3" align="right">Grand-total</td>
                        <td>?how to count all subtotal together?</td>
                    </tr>
                </table>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

私の質問は、国グループ内のすべての購入日を一覧表示する方法です。国に続いて合計金額を数えられるように

4

2 に答える 2

1

この変換:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kCDPurchByCountryDate" match="cd"
  use="concat(@PurchaseDate,'+', country)"/>

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1">
   <xsl:apply-templates/>
  </xsl:variable>

  <xsl:apply-templates select="ext:node-set($vrtfPass1)/*">
   <xsl:sort select="@country"/>
   <xsl:sort select="@PurchaseDate" order="descending"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match=
 "cd[generate-id()
    =generate-id(key('kCDPurchByCountryDate',
                     concat(@PurchaseDate,'+', country)
                     )[1]
                 )]">
  <trans country="{country}" PurchaseDate="{@PurchaseDate}">
   <amount><xsl:value-of select="quantity*price"/></amount>
   <xsl:apply-templates mode="group" select=
    "key('kCDPurchByCountryDate',concat(@PurchaseDate,'+', country))
        [position() > 1]
    "/>
  </trans>
 </xsl:template>

 <xsl:template match="cd" mode="group">
   <amount><xsl:value-of select="quantity*price"/></amount>
 </xsl:template>
 <xsl:template match="text()"/>

 <xsl:template match="trans">
  <xsl:copy>
   <xsl:copy-of select="@*"/>
   <total><xsl:value-of select="sum(amount)"/></total>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

提供された XML ドキュメントに適用した場合:

<catalog>
    <cd PurchaseDate="20000101">
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <quantity>20</quantity>
        <price>10.90</price>
    </cd>
    <cd PurchaseDate="20000101">
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <quantity>10</quantity>
        <price>9.90</price>
    </cd>
    <cd PurchaseDate="20000102">
        <title>Greatest Hits</title>
        <artist>Dolly Parton</artist>
        <country>USA</country>
        <quantity>15</quantity>
        <price>9.90</price>
    </cd>
    <cd PurchaseDate="20000101">
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <quantity>5</quantity>
        <price>10.20</price>
    </cd>
    <cd PurchaseDate="20000103">
        <title>Eros</title>
        <artist>Eros Ramazzotti</artist>
        <country>EU</country>
        <quantity>6</quantity>
        <price>9.90</price>
    </cd>
    <cd PurchaseDate="20000103">
        <title>One night only</title>
        <artist>Bee Gees</artist>
        <country>UK</country>
        <quantity>16</quantity>
        <price>10.90</price>
    </cd>
    <cd PurchaseDate="20000102">
        <title>Sylvias Mother</title>
        <artist>Dr.Hook</artist>
        <country>UK</country>
        <quantity>3</quantity>
        <price>8.10</price>
    </cd>
    <cd PurchaseDate="20000101">
        <title>Maggie May</title>
        <artist>Rod Stewart</artist>
        <country>UK</country>
        <quantity>8</quantity>
        <price>8.50</price>
    </cd>
    <cd PurchaseDate="20000103">
        <title>Romanza</title>
        <artist>Andrea Bocelli</artist>
        <country>EU</country>
        <quantity>30</quantity>
        <price>10.80</price>
    </cd>
</catalog>

必要な正しい結果が生成されます。

<trans country="EU" PurchaseDate="20000103">
   <total>383.4</total>
</trans>
<trans country="UK" PurchaseDate="20000103">
   <total>174.4</total>
</trans>
<trans country="UK" PurchaseDate="20000102">
   <total>24.299999999999997</total>
</trans>
<trans country="UK" PurchaseDate="20000101">
   <total>218</total>
</trans>
<trans country="USA" PurchaseDate="20000102">
   <total>148.5</total>
</trans>
<trans country="USA" PurchaseDate="20000101">
   <total>218</total>
</trans>

説明:

  1. これは、非再帰的な2パス変換です。数を掛けてから掛け算の結果を合計する問題の再帰的な XSLT 1.0 ソリューションについては、次の質問への回答を参照してください: Multiply 2 numbers and then sum with XSLT :

  2. 最初のパスは、複合キーを使用した Muenchian グループ化方法を使用して、国と購入日ごとにグループ化します。

  3. グループごとに複数のamount要素が生成されます。

  4. transaction2 番目のパスでは、最初のパスで作成された要素をシャロー コピーします。amount子を単一のtotal要素に置き換えます。


Ⅱ.XSLT 2.0 ソリューション:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
  <xsl:for-each-group select="cd" group-by="concat(country,'+',@PurchaseDate)">
    <xsl:sort select="country"/>
    <xsl:sort select="@PurchaseDate" order="descending"/>

    <trans country="{country}" PurchaseDate="{@PurchaseDate}">
      <total><xsl:sequence select="sum(current-group()/(price*quantity))"/></total>
    </trans>
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>
于 2013-04-27T03:56:17.320 に答える
0

あなたが期待するものを示していませんが、ここにあなたが望むものを与える解決策があると思います. <xsl:for-each>noは必要ないことに注意してください。この<xsl:template>ベースのソリューションは、もう少し柔軟です。

この XSLT の場合:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="kCdByCountry" match="cd" use="country"/>

  <xsl:template match="/*">
    <html>
      <body>
        <table border="1">
          <xsl:apply-templates
             select="cd[generate-id() =                        
                        generate-id(key('kCdByCountry', country)[1])]">
            <xsl:sort select="country"/>
          </xsl:apply-templates>
          <tr bgcolor="#9acd32">
            <td colspan="4">
              <xsl:text>Total: </xsl:text>
              <xsl:call-template name="sumProducts">
                <xsl:with-param name="pElemList" select="/*/*"/>
              </xsl:call-template>
            </td>
          </tr>
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="cd">
    <tr bgcolor="#9acd32">
      <td colspan="4">
        <xsl:text>Country: </xsl:text>
        <xsl:value-of select="country"/>
      </td>
    </tr>
    <tr>
      <td>Purchase Date</td>
      <td>Quantity</td>
      <td>Unit Price</td>
      <td>Total</td>
    </tr>
    <xsl:apply-templates select="key('kCdByCountry', country)" mode="values">
      <xsl:sort select="@PurchaseDate" data-type="number"/>
    </xsl:apply-templates>
    <tr bgcolor="#9acd32">
      <td colspan="4">
        <xsl:text>Subtotal: </xsl:text>
        <xsl:call-template name="sumProducts">
          <xsl:with-param
            name="pElemList"
            select="key('kCdByCountry', country)"/>
        </xsl:call-template>
      </td>
    </tr>
  </xsl:template>

  <xsl:template match="cd" mode="values">
    <tr>
      <td>
        <xsl:value-of select="@PurchaseDate"/>
      </td>
      <td>
        <xsl:value-of select="quantity"/>
      </td>
      <td>
        <xsl:value-of select="price"/>
      </td>
      <td>
        <xsl:value-of select="quantity * price"/>
      </td>
    </tr>
  </xsl:template>

  <xsl:template name="sumProducts">
    <xsl:param name="pElemList"/>
    <xsl:param name="pTotal" select="0"/>
    <xsl:choose>
      <xsl:when test="$pElemList">
        <xsl:variable name="vCurrentElem" select="$pElemList[1]"/>
        <xsl:call-template name="sumProducts">
          <xsl:with-param
            name="pElemList"
            select="$pElemList[position() &gt; 1]"/>
          <xsl:with-param
            name="pTotal"
            select="$pTotal + $vCurrentElem/price * $vCurrentElem/quantity"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$pTotal"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

...提供された XML に対して適用されます。

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <cd PurchaseDate="20000101">
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <quantity>20</quantity>
    <price>10.90</price>
  </cd>
  <cd PurchaseDate="20000101">
    <title>Hide your heart</title>
    <artist>Bonnie Tyler</artist>
    <country>UK</country>
    <quantity>10</quantity>
    <price>9.90</price>
  </cd>
  <cd PurchaseDate="20000102">
    <title>Greatest Hits</title>
    <artist>Dolly Parton</artist>
    <country>USA</country>
    <quantity>15</quantity>
    <price>9.90</price>
  </cd>
  <cd PurchaseDate="20000101">
    <title>Still got the blues</title>
    <artist>Gary Moore</artist>
    <country>UK</country>
    <quantity>5</quantity>
    <price>10.20</price>
  </cd>
  <cd PurchaseDate="20000103">
    <title>Eros</title>
    <artist>Eros Ramazzotti</artist>
    <country>EU</country>
    <quantity>6</quantity>
    <price>9.90</price>
  </cd>
  <cd PurchaseDate="20000103">
    <title>One night only</title>
    <artist>Bee Gees</artist>
    <country>UK</country>
    <quantity>16</quantity>
    <price>10.90</price>
  </cd>
  <cd PurchaseDate="20000102">
    <title>Sylvias Mother</title>
    <artist>Dr.Hook</artist>
    <country>UK</country>
    <quantity>3</quantity>
    <price>8.10</price>
  </cd>
  <cd PurchaseDate="20000101">
    <title>Maggie May</title>
    <artist>Rod Stewart</artist>
    <country>UK</country>
    <quantity>8</quantity>
    <price>8.50</price>
  </cd>
  <cd PurchaseDate="20000103">
    <title>Romanza</title>
    <artist>Andrea Bocelli</artist>
    <country>EU</country>
    <quantity>30</quantity>
    <price>10.80</price>
  </cd>
</catalog>

..(欲しい?)結果が生成されます:

<html>
  <body>
    <table border="1">
      <tr bgcolor="#9acd32">
        <td colspan="4">Country: EU</td>
      </tr>
      <tr>
        <td>Purchase Date</td>
        <td>Quantity</td>
        <td>Unit Price</td>
        <td>Total</td>
      </tr>
      <tr>
        <td>20000103</td>
        <td>6</td>
        <td>9.90</td>
        <td>59.4</td>
      </tr>
      <tr>
        <td>20000103</td>
        <td>30</td>
        <td>10.80</td>
        <td>324</td>
      </tr>
      <tr bgcolor="#9acd32">
        <td colspan="4">Subtotal: 383.4</td>
      </tr>
      <tr bgcolor="#9acd32">
        <td colspan="4">Country: UK</td>
      </tr>
      <tr>
        <td>Purchase Date</td>
        <td>Quantity</td>
        <td>Unit Price</td>
        <td>Total</td>
      </tr>
      <tr>
        <td>20000101</td>
        <td>10</td>
        <td>9.90</td>
        <td>99</td>
      </tr>
      <tr>
        <td>20000101</td>
        <td>5</td>
        <td>10.20</td>
        <td>51</td>
      </tr>
      <tr>
        <td>20000101</td>
        <td>8</td>
        <td>8.50</td>
        <td>68</td>
      </tr>
      <tr>
        <td>20000102</td>
        <td>3</td>
        <td>8.10</td>
        <td>24.3</td>
      </tr>
      <tr>
        <td>20000103</td>
        <td>16</td>
        <td>10.90</td>
        <td>174.4</td>
      </tr>
      <tr bgcolor="#9acd32">
        <td colspan="4">Subtotal: 416.7</td>
      </tr>
      <tr bgcolor="#9acd32">
        <td colspan="4">Country: USA</td>
      </tr>
      <tr>
        <td>Purchase Date</td>
        <td>Quantity</td>
        <td>Unit Price</td>
        <td>Total</td>
      </tr>
      <tr>
        <td>20000101</td>
        <td>20</td>
        <td>10.90</td>
        <td>218</td>
      </tr>
      <tr>
        <td>20000102</td>
        <td>15</td>
        <td>9.90</td>
        <td>148.5</td>
      </tr>
      <tr bgcolor="#9acd32">
        <td colspan="4">Subtotal: 366.5</td>
      </tr>
      <tr bgcolor="#9acd32">
        <td colspan="4">Total: 1166.6</td>
      </tr>
    </table>
  </body>
</html>

...これを HTML としてレンダリングすると、次のようになります。

ここに画像の説明を入力

このソリューションの秘訣は、それぞれの積<quantity><price>組み合わせを合計する再帰的な名前付きテンプレートです。このテンプレートは、各国の小計を計算し、最後にすべての国の合計を計算するために使用されます。Dimitre Novatchev にこの宝石 ( 2 つの数値を乗算してから合計) を提供してくれたことに感謝します。

于 2013-04-27T03:39:09.013 に答える