2

次のようなxmlドキュメントがあります。

<units>
    <unit>
       <year></year>
       <month></month>
       <qty></qty>
    </unit>
</units>

このデータのクロス集計ビューをhtmlで作成します。各行は年で表され、各列は月で表され、各値には特定の年/月の数量の合計が含まれます。このようなもの:

      Jan  Feb   Mar   Apr.... etc
2010  345    0    12     0
2011    1   23   344     0
2012   99    1    23     0.... etc

私の主な質問はこれです:クロス集計はxsltでも可能ですか?

私のフォローアップの質問は、私などのxslt初心者に、この作業を開始するための正しい方向を示すことができるかどうかです。

サンプルデータ:

<units>
    <unit>
        <year>2010</year>
        <month>9</month>
        <qty>13320</qty>
    </unit>
    <unit>
        <year>2010</year>
        <month>9</month>
        <qty>2445</qty>
    </unit>
    <unit>
        <year>2010</year>
        <month>10</month>
        <qty>8949</qty>
    </unit>
    <unit>
        <year>2010</year>
        <month>10</month>
        <qty>13650</qty>
    </unit>
    <unit>
        <year>2010</year>
        <month>11</month>
        <qty>4091</qty>
    </unit>
    <unit>
        <year>2010</year>
        <month>11</month>
        <qty>6600</qty>
    </unit>
    <unit>
        <year>2010</year>
        <month>12</month>
        <qty>686</qty>
    </unit>
    <unit>
        <year>2010</year>
        <month>12</month>
        <qty>678</qty>
    </unit>

    <unit>
        <year>2011</year>
        <month>1</month>
        <qty>1234</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>1</month>
        <qty>12345</qty>
    </unit>
    <unit>
         <year>2011</year>
        <month>2</month>
        <qty>4500</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>2</month>
        <qty>999</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>3</month>
        <qty>166</qty>
    </unit>
    <unit>
         <year>2011</year>
        <month>3</month>
        <qty>456666</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>4</month>
        <qty>41113</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>4</month>
        <qty>1150</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>5</month>
        <qty>4150</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>5</month>
        <qty>491</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>6</month>
        <qty>11250</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>6</month>
        <qty>3400</qty>
    </unit>
    <unit>
         <year>2011</year>
        <month>7</month>
        <qty>485</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>7</month>
        <qty>90</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>8</month>
        <qty>1606</qty>
    </unit>
    <unit>
         <year>2011</year>
        <month>8</month>
        <qty>202000</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>9</month>
        <qty>45333</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>9</month>
        <qty>13650</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>10</month>
        <qty>4050</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>10</month>
        <qty>431</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>11</month>
        <qty>45713</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>11</month>
        <qty>13690</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>12</month>
        <qty>4050</qty>
    </unit>
    <unit>
        <year>2011</year>
        <month>12</month>
        <qty>431</qty>
    </unit>

    <unit>
        <year>2012</year>
        <month>1</month>
        <qty>2500</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>1</month>
        <qty>34100</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>2</month>
        <qty>400</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>2</month>
        <qty>99</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>3</month>
        <qty>1606</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>3</month>
        <qty>202000</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>4</month>
        <qty>53773</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>4</month>
        <qty>13650</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>5</month>
        <qty>4150</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>5</month>
        <qty>4231</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>6</month>
        <qty>278</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>6</month>
        <qty>6100</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>7</month>
        <qty>406</qty>
    </unit>
    <unit>
        <year>2012</year>
        <month>7</month>
        <qty>95</qty>
    </unit>

</units>
4

3 に答える 3

2

XSLT 1.0ソリューションは次のとおりです(数値を適切に揃えるには、いくつかの作業が必要になる場合があります)。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kUnitByY" match="unit" use="year"/>
 <xsl:key name="kUnitByYM" match="unit" use="concat(year,'|',month)"/>

 <xsl:template match="/*">
<xsl:text>      Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec</xsl:text>
  <xsl:apply-templates select=
   "unit[generate-id()=generate-id(key('kUnitByY',year)[1])]">
    <xsl:sort select="year" data-type="number"/>
   </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="unit">
  <xsl:value-of select="concat('&#xA;',year,'  ')"/>

  <xsl:variable name="vCur" select="."/>

  <xsl:for-each select="(//node()|//namespace::*)[not(position() >12)]">
    <xsl:value-of select=
    "sum(key('kUnitByYM', concat($vCur/year,'|',position()))/qty)"/>
    <xsl:text>    </xsl:text>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

この変換が次のXMLドキュメントに適用される場合(何も提供されませんでした!!!):

2010 2 3 2010 3 44 2010 9 44 2011 1 5 2011 3 11 2011 6 11 2011 4 15

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

      Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec
2010  0    3    44    0    0    0    0    0    44    0    0    0    
2011  5    0    11    15    0    11    0    0    0    0    0    0 
于 2012-09-13T04:19:13.200 に答える
1

XSLT1.0ソリューション

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="row" match="unit" use="year" />

<xsl:template match="/">
  <xsl:text>     Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec&#x0A;</xsl:text>
  <xsl:apply-templates select="*/unit[
    generate-id() = generate-id( key('row',year)[1])]">
      <xsl:sort select="year" data-type="number" />
  </xsl:apply-templates>    
</xsl:template>

<xsl:template match="unit">
  <xsl:variable name="year" select="year" />
  <xsl:value-of select="concat($year,' ')" />
  <xsl:for-each select="((/)//@*|(/)//node())[position() &lt; 13]">
    <xsl:variable name="month-num" select="position()" />
    <xsl:variable name="sum" select="sum(/*/unit[year=$year][month=$month-num]/qty)" />
    <xsl:value-of select="concat(substring('   ',1,3 - string-length($sum)),$sum,' ')" />
  </xsl:for-each>  
  <xsl:value-of select="'&#x0A;'" />
</xsl:template>

</xsl:stylesheet>

...このような入力を受け取ります...

<units>
    <unit>
       <year>2010</year>
       <month>2</month>
       <qty>3</qty>
    </unit>
    <unit>
       <year>2010</year>
       <month>3</month>
       <qty>44</qty>
    </unit>
    <unit>
       <year>2011</year>
       <month>1</month>
       <qty>5</qty>
    </unit>
    <unit>
       <year>2011</year>
       <month>3</month>
       <qty>11</qty>
    </unit>
    <unit>
       <year>2011</year>
       <month>4</month>
       <qty>15</qty>
    </unit>
</units>

...そしてこのようなテキストを生成します...

     Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
2010   0   3  44   0   0   0   0   0   0   0   0   0 
2011   5   0  11  15   0   0   0   0   0   0   0   0 

XSLT2.0ソリューション

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>

<xsl:template match="/">
       Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
  <xsl:for-each-group select="*/unit" group-by="year">
    <xsl:sort select="year" data-type="number" />
    <xsl:value-of select="concat(current-grouping-key(),' ')" />  
      <xsl:value-of select="        
          (string-join(
          for $month-num in 1 to 12 return
                for $sum in sum(current-group()/qty) return
                  concat(substring('   ',1,3 - string-length($sum)),$sum),
          ' '), '&#x0A;')" />
 </xsl:for-each-group>    
</xsl:template>

</xsl:stylesheet>

アップデート1

Dimitreによって提案された回線終了の修正を追加しました。


アップデート2

出力の先行ゼロを削除しましたが、列の配置は保持しています。


警告

  1. XSLT 1.0ソリューションは、最大合計が1000未満の場合にのみ機能します。そうでない場合は、それに応じて調整します。
  2. '/ * / unit [year = $ year] [month = $ month-num]'を再計算するのではなく、キーを活用するDimitreのソリューションが優れています。おそらく最適な解決策は、合計を計算するために彼のkey()スタイルの解決策を使用することですが、私のコードの断片は、先行ゼロ以外の列の配置に使用します。
于 2012-09-12T16:03:56.113 に答える
0

あなたはこれを使用してこれを行うことができますMuenchian Method

于 2012-09-12T15:23:38.193 に答える