xsl-list
[Top] [All Lists]

[xsl] Pivot Reports

2007-01-17 08:30:12
Hello all!

We met a strange problem with XML transformation.

Let us describe our task first:
We need to generate complex xml based reports which could contains multiple crosstab parts.
We have next requirements:

  1. Each crosstab could contains arbitrary number of rows and columns.
  2. Crosstab report can include other crosstabs
  3. Position of the crosstab is unknown  on design phase (user can
     build complex report using already designed blocks. crosstab is
     the one of the blocks)
  4. The highest level of XSLT is hardcoded so we can't change it for
     every report
  5. Each block have its own unique ID
  6. Several blocks can contain same columns and/or rows

Ours assumptions:

  1. Key tags for all crosstabs are standard (<item> - atomic set of
     information, <row> - name of the item's row, <col> - name of the
     item's col, <val> - value of the item)
  2. Combination of the row and the col is unique in scope of the block
  3. Source data doesn't cover all the combinations of rows and cols.
     So missing items should be interpreted as - or 0

Problem is the next:
First block is generated absolutely correct, all the next blocks contain only combinations of rows and cols which haven't been met in any of already generated blocks.

Sample:

We need take this
_____________________________
*     | C1    | C2   | Total |
------+-------+------+-------
R1    |    1  |   2  |     3 |
------+-------+------+-------
R2    |    2  |   -  |     2 |
------+-------+------+-------
Total |    3  |   2  |     5 |
-----------------------------

_____________________________
*     | C2    | C3   | Total |
------+-------+------+-------
R2    |   4   |   3  |     7 |
------+-------+------+-------
R3    |   21  |   2  |    23 |
------+-------+------+-------
Total |   25  |   5  |    30 |
-----------------------------


But we take this
_____________________________
*     | C1    | C2   | Total |
------+-------+------+-------
R1    |    1  |   2  |     3 |
------+-------+------+-------
R2    |    2  |   -  |     2 |
------+-------+------+-------
Total |    3  |   2  |     5 |
-----------------------------

________________________
*     | C3    |  Total  |
------+-------+---------
R3    |    4  |    7    |
------+-------+---------
Total |    25 |    5    |
------------------------



Sample XML

<?xml version="1.0" encoding="iso-8859-1"?>
<?xml-stylesheet type='text/xsl' href='1.xsl'?>
<notice>
<pivots>

<pivot>
 <item>
  <col>C1</col>
  <row>R1</row>
  <val>1</val>
 </item>
 <item>
  <col>C1</col>
  <row>R2</row>
  <val>3</val>
 </item>
 <item>
  <col>C2</col>
  <row>R1</row>
  <val>5</val>
 </item>
 <item>
  <col>C2</col>
  <row>R2</row>
  <val>2</val>
 </item>
</pivot>

<pivot>
 <item>
  <col>C2</col>
  <row>R2</row>
  <val>1</val>
 </item>
 <item>
  <col>C2</col>
  <row>R3</row>
  <val>3</val>
 </item>
 <item>
  <col>C3</col>
  <row>R2</row>
  <val>2</val>
 </item>
</pivot>
</pivots>

</notice>


Sample XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:key name="b" match="row" use="."/>
<xsl:key name="c" match="col" use="."/>
<xsl:template match="/">
<xsl:for-each select="/notice/pivots">
 <br/>
 <xsl:variable name="inc" select="0" />
<xsl:for-each select="pivot"> <table border="1" cellspacing="0" class="stn">
         <tr>
           <th>*</th>
<xsl:for-each select="item/row[generate-id(.)=generate-id(key('b',.)[1])]">
             <xsl:sort select="."/>
             <xsl:variable name="vrow" select="."/>
             <th>
               <xsl:value-of select="."/>
             </th>
           </xsl:for-each>
           <th>total</th>
         </tr>
<xsl:for-each select="item/col[generate-id(.)=generate-id(key('c',.)[1])]">
         <xsl:sort select="."/>
         <xsl:variable name="vcol" select="."/>
         <tr>
           <th><xsl:value-of select="."/></th>
<xsl:for-each select="../../item/row[generate-id(.)=generate-id(key('b',.)[1])]">
             <xsl:variable name="vrow" select="."/>
             <td>
<xsl:if test="not(../../item[col=$vcol and row=$vrow])">-</xsl:if> <xsl:if test="../../item[col=$vcol and row=$vrow]"><xsl:value-of select="../../item[col=$vcol and row=$vrow]/val"/></xsl:if>
             </td>
           </xsl:for-each>
           <td><xsl:value-of select="sum(../../item[col=$vcol]/val)"/></td>
         </tr>
       </xsl:for-each>
         <tr>
           <th>total</th>
<xsl:for-each select="item/row[generate-id(.)=generate-id(key('b',.)[1])]">
             <xsl:sort select="."/>
             <xsl:variable name="vrow" select="."/>
             <td>
               <xsl:value-of select="sum(../../item[row=$vrow]/val)"/>
             </td>
           </xsl:for-each>
           <td><xsl:value-of select="sum(item/val)"/></td>
         </tr>
     </table>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>


--
*/Best regards,
Vitaliy Paykov/*
e-mail: vpay(_at_)isd(_dot_)dp(_dot_)ua
ext: 1120
ICQ: 220022522
*/ISD QA/*

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>