使用XSLT显示每12列(已排序)并填充缺少的列

时间:2015-03-19 12:09:29

标签: xslt

我需要在包含12列的表中显示以下XML。如果有超过12行数据,我需要在下表中显示接下来的12行,依此类推。如果少于12行数据,我需要创建具有正确标题的额外行。

XML:

<Accounts>
    <Account>
        <AccountHistories>
            <AccountHistory bal="93750" m="2015-03"/>
            <AccountHistory bal="94500" m="2015-02"/>
            <AccountHistory bal="95250" m="2015-01"/>
            <AccountHistory bal="96000" m="2014-12"/>
            <AccountHistory bal="96750" m="2014-11"/>
            <AccountHistory bal="97500" m="2014-10"/>
            <AccountHistory bal="98250" m="2014-09"/>
            <AccountHistory bal="99000" m="2014-08"/>
            <AccountHistory bal="99750" m="2014-07"/>
            <AccountHistory bal="100500" m="2014-06"/>
            <AccountHistory bal="101250" m="2014-05"/>
            <AccountHistory bal="102000" m="2014-04"/>
            <AccountHistory bal="102750" m="2014-03"/>
            <AccountHistory bal="103500" m="2014-02"/>
            <AccountHistory bal="104250" m="2014-01"/>
            <AccountHistory bal="105000" m="2013-12"/>
            <AccountHistory bal="105750" m="2013-11"/>
            <AccountHistory bal="106500" m="2013-10"/>
            <AccountHistory bal="107250" m="2013-09"/>
            <AccountHistory bal="108000" m="2013-08"/>
            <AccountHistory bal="108750" m="2013-07"/>
            <AccountHistory bal="109500" m="2013-06"/>
            <AccountHistory bal="110250" m="2013-05"/>
            <AccountHistory bal="111000" m="2013-04"/>
            <AccountHistory bal="111750" m="2013-03"/>
            <AccountHistory bal="112500" m="2013-02"/>
            <AccountHistory bal="113250" m="2013-01"/>
            <AccountHistory bal="114000" m="2012-12"/>
            <AccountHistory bal="114750" m="2012-11"/>
            <AccountHistory bal="115500" m="2012-10"/>
            <AccountHistory bal="116250" m="2012-09"/>
            <AccountHistory bal="117000" m="2012-08"/>
            <AccountHistory bal="117750" m="2012-07"/>
            <AccountHistory bal="118500" m="2012-06"/>
            <AccountHistory bal="119250" m="2012-05"/>
        </AccountHistories>
    </Account>
    <Account>
        <AccountHistories>
            <AccountHistory bal="500" m="2015-03"/>
            <AccountHistory bal="500" m="2015-02"/>
            <AccountHistory bal="500" m="2015-01"/>
        </AccountHistories>
    </Account>
</Accounts>

所以你可以看到第一个帐户应该呈现3个表,第二个帐户应该呈现1个表,如下所示: Account history tables

所以逻辑是这样的:

  1. 获取前12行,按@m升序排序并在列中显示行数据
  2. 如果小于12,请填充生成正确@m值的行
  3. 如果超过12,则获得接下来的12行等(按照1)。重复。
  4. 我已经找到了日期/货币格式,但我真的在努力解决这个问题。有什么想法吗?

    编辑 - 这是我所拥有的 - 它没有正确排序,没有处理其他表格,也没有添加缺少的日期列。所以不是很远,真的!

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
        <xsl:output method="html" indent="yes"/>
    
        <xsl:template match="/">
            <xsl:apply-templates select="Accounts/Account"/>
        </xsl:template>
    
        <xsl:template match="Account">
            <div><xsl:value-of select="position()"/></div>
            <xsl:apply-templates select="AccountHistories"/>
        </xsl:template>
    
        <xsl:template match="AccountHistories">
            <table>
                <tbody>
                    <tr>
                        <td>
                            <strong>Date: </strong>
                        </td>
                        <xsl:for-each select="AccountHistory">
                            <xsl:if test="position() &lt; 13">
                                <td>
                                    <xsl:call-template name="toMonthYear">
                                        <xsl:with-param name="DateTime" select="@m"/>
                                    </xsl:call-template>
                                </td>
                            </xsl:if>
                        </xsl:for-each>
                    </tr>
                    <tr>
                        <td>
                            <strong>Balance: </strong>
                        </td>
                        <xsl:for-each select="AccountHistory">
                            <xsl:if test="position() &lt; 13">
                                <td>
                                    <xsl:call-template name="toCurrency">
                                        <xsl:with-param name="val" select="@bal"/>
                                    </xsl:call-template>
                                </td>
                            </xsl:if>
                        </xsl:for-each>
                    </tr>
                </tbody>
            </table>
        </xsl:template>
    
        <xsl:template name="toMonthYear">
            <!-- convert from 1999-12 format to Dec 1999 -->
            <xsl:param name="DateTime" />
    
            <xsl:if test="$DateTime != ''">
                <xsl:variable name="year">
                    <xsl:value-of select="substring($DateTime,1,4)" />
                </xsl:variable>
                <xsl:variable name="mo">
                    <xsl:value-of select="substring($DateTime,6,2)" />
                </xsl:variable>
    
                <xsl:choose>
                    <xsl:when test="$mo = '01'">Jan</xsl:when>
                    <xsl:when test="$mo = '02'">Feb</xsl:when>
                    <xsl:when test="$mo = '03'">Mar</xsl:when>
                    <xsl:when test="$mo = '04'">Apr</xsl:when>
                    <xsl:when test="$mo = '05'">May</xsl:when>
                    <xsl:when test="$mo = '06'">Jun</xsl:when>
                    <xsl:when test="$mo = '07'">Jul</xsl:when>
                    <xsl:when test="$mo = '08'">Aug</xsl:when>
                    <xsl:when test="$mo = '09'">Sep</xsl:when>
                    <xsl:when test="$mo = '10'">Oct</xsl:when>
                    <xsl:when test="$mo = '11'">Nov</xsl:when>
                    <xsl:when test="$mo = '12'">Dec</xsl:when>
                </xsl:choose>
                <xsl:text> </xsl:text>
                <xsl:value-of select="$year"/>
            </xsl:if>
        </xsl:template>
    
        <xsl:template name="toCurrency">
            <xsl:param name="val">0</xsl:param>
            <xsl:param name="displaySign">0</xsl:param>
            <xsl:if test="$val &lt; 0">
                <xsl:text>-</xsl:text>
            </xsl:if>
            <xsl:if test="($val &gt; 0) and ($displaySign = 1)">
                <xsl:text>+</xsl:text>
            </xsl:if>
            <xsl:text>£ </xsl:text>
            <xsl:choose>
                <xsl:when test="$val &gt; 0">
                    <xsl:value-of select="format-number($val, '#,###')"/>
                </xsl:when>
                <xsl:when test="$val &lt; 0">
                    <!-- turn negative number into positive -->
                    <xsl:value-of select="format-number($val * (1 - 2 * ($val &lt; 0)), '#,###')"/>
                </xsl:when>
                <xsl:otherwise>0</xsl:otherwise>
            </xsl:choose>
        </xsl:template>
    </xsl:stylesheet>
    

1 个答案:

答案 0 :(得分:1)

这一点都不简单,尤其是不在XSLT 1.0中。希望这会让你走上正轨:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">

<xsl:variable name="doc" select="/" />
<xsl:key name="balance" match="AccountHistory/@bal" use="concat(ancestor::Account/@id, '|', ../@m)" />
<xsl:decimal-format name="coerce" NaN="&#160;" />

<xsl:template match="/Accounts">
    <html>
        <body>
            <xsl:apply-templates select="Account/AccountHistories"/>
        </body>
    </html>
</xsl:template>

<xsl:template match="AccountHistories">
    <xsl:variable name="n" select="count(AccountHistory)" />
    <h2>Account: <xsl:value-of select="ancestor::Account/@id"/></h2>
    <table border="1" width="80%">
        <xsl:call-template name="generate-rows">
            <xsl:with-param name="acct" select="ancestor::Account/@id" />
            <xsl:with-param name="years" select="ceiling($n div 12)" />
            <xsl:with-param name="last-year" select="substring-before(AccountHistory[1]/@m, '-')" />
            <xsl:with-param name="last-month" select="substring-after(AccountHistory[1]/@m, '-')" />
        </xsl:call-template>
    </table>
</xsl:template>

<xsl:template name="generate-rows">
    <xsl:param name="acct"/>
    <xsl:param name="years"/>
    <xsl:param name="last-year"/>
    <xsl:param name="last-month"/>
    <xsl:if test="$years">
        <xsl:variable name="cols">
            <xsl:call-template name="generate-cols">
                <xsl:with-param name="year" select="$last-year" />
                <xsl:with-param name="last-month" select="$last-month" />
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="cols-set" select="exsl:node-set($cols)/col" />
        <tr>
            <th>Date:</th>
            <xsl:for-each select="$cols-set">
                <th>
                    <xsl:value-of select="@m"/>
                    <xsl:text>/</xsl:text>
                    <xsl:value-of select="@y"/>
                </th>
            </xsl:for-each>     
        </tr>
        <tr>
            <th>Balance:</th>
            <xsl:for-each select="$cols-set">
                <xsl:variable name="key" select="concat($acct, '|', @y, '-', format-number(@m, '00'))" />
                <td>
                    <!-- switch context back to document -->
                    <xsl:for-each select="$doc">
                        <xsl:value-of select="format-number(key('balance', $key), '#,##0', 'coerce')"/>
                    </xsl:for-each> 
                </td>
            </xsl:for-each>     
        </tr>
            <!-- recursive call -->
            <xsl:call-template name="generate-rows">
            <xsl:with-param name="acct" select="$acct" />
            <xsl:with-param name="years" select="$years - 1" />
            <xsl:with-param name="last-year" select="$last-year - 1" />
            <xsl:with-param name="last-month" select="$last-month" />
        </xsl:call-template>
    </xsl:if>   
</xsl:template>

<xsl:template name="generate-cols">
    <xsl:param name="year"/>
    <xsl:param name="last-month"/>
    <xsl:param name="i" select="12" />
    <xsl:variable name="month" select="$last-month - $i"/>
    <xsl:if test="$i">
        <col y="{$year - ($month &lt; 0 )}" m="{($month + 12) mod 12 + 1}"/>
        <!-- recursive call -->
        <xsl:call-template name="generate-cols">
            <xsl:with-param name="year" select="$year" />
            <xsl:with-param name="last-month" select="$last-month" />
            <xsl:with-param name="i" select="$i - 1" />
        </xsl:call-template>
    </xsl:if>   
</xsl:template>

</xsl:stylesheet>

我必须为每个@id添加account属性来修改输入

<强> XML

<Accounts>
    <Account id="123">
        <AccountHistories>
            <AccountHistory bal="93750" m="2015-03"/>
            <AccountHistory bal="94500" m="2015-02"/>
            <AccountHistory bal="95250" m="2015-01"/>
            <AccountHistory bal="96000" m="2014-12"/>
            <AccountHistory bal="96750" m="2014-11"/>
            <AccountHistory bal="97500" m="2014-10"/>
            <AccountHistory bal="98250" m="2014-09"/>
            <AccountHistory bal="99000" m="2014-08"/>
            <AccountHistory bal="99750" m="2014-07"/>
            <AccountHistory bal="100500" m="2014-06"/>
            <AccountHistory bal="101250" m="2014-05"/>
            <AccountHistory bal="102000" m="2014-04"/>
            <AccountHistory bal="102750" m="2014-03"/>
            <AccountHistory bal="103500" m="2014-02"/>
            <AccountHistory bal="104250" m="2014-01"/>
            <AccountHistory bal="105000" m="2013-12"/>
            <AccountHistory bal="105750" m="2013-11"/>
            <AccountHistory bal="106500" m="2013-10"/>
            <AccountHistory bal="107250" m="2013-09"/>
            <AccountHistory bal="108000" m="2013-08"/>
            <AccountHistory bal="108750" m="2013-07"/>
            <AccountHistory bal="109500" m="2013-06"/>
            <AccountHistory bal="110250" m="2013-05"/>
            <AccountHistory bal="111000" m="2013-04"/>
            <AccountHistory bal="111750" m="2013-03"/>
            <AccountHistory bal="112500" m="2013-02"/>
            <AccountHistory bal="113250" m="2013-01"/>
            <AccountHistory bal="114000" m="2012-12"/>
            <AccountHistory bal="114750" m="2012-11"/>
            <AccountHistory bal="115500" m="2012-10"/>
            <AccountHistory bal="116250" m="2012-09"/>
            <AccountHistory bal="117000" m="2012-08"/>
            <AccountHistory bal="117750" m="2012-07"/>
            <AccountHistory bal="118500" m="2012-06"/>
            <AccountHistory bal="119250" m="2012-05"/>
        </AccountHistories>
    </Account>
    <Account id="45">
        <AccountHistories>
            <AccountHistory bal="503" m="2015-03"/>
            <AccountHistory bal="502" m="2015-02"/>
            <AccountHistory bal="501" m="2015-01"/>
        </AccountHistories>
    </Account>
</Accounts>

<强>结果

<html>
   <body>
      <h2>Account: 123</h2>
      <table border="1" width="80%">
         <tr>
            <th>Date:</th>
            <th>4/2014</th>
            <th>5/2014</th>
            <th>6/2014</th>
            <th>7/2014</th>
            <th>8/2014</th>
            <th>9/2014</th>
            <th>10/2014</th>
            <th>11/2014</th>
            <th>12/2014</th>
            <th>1/2015</th>
            <th>2/2015</th>
            <th>3/2015</th>
         </tr>
         <tr>
            <th>Balance:</th>
            <td>102,000</td>
            <td>101,250</td>
            <td>100,500</td>
            <td>99,750</td>
            <td>99,000</td>
            <td>98,250</td>
            <td>97,500</td>
            <td>96,750</td>
            <td>96,000</td>
            <td>95,250</td>
            <td>94,500</td>
            <td>93,750</td>
         </tr>
         <tr>
            <th>Date:</th>
            <th>4/2013</th>
            <th>5/2013</th>
            <th>6/2013</th>
            <th>7/2013</th>
            <th>8/2013</th>
            <th>9/2013</th>
            <th>10/2013</th>
            <th>11/2013</th>
            <th>12/2013</th>
            <th>1/2014</th>
            <th>2/2014</th>
            <th>3/2014</th>
         </tr>
         <tr>
            <th>Balance:</th>
            <td>111,000</td>
            <td>110,250</td>
            <td>109,500</td>
            <td>108,750</td>
            <td>108,000</td>
            <td>107,250</td>
            <td>106,500</td>
            <td>105,750</td>
            <td>105,000</td>
            <td>104,250</td>
            <td>103,500</td>
            <td>102,750</td>
         </tr>
         <tr>
            <th>Date:</th>
            <th>4/2012</th>
            <th>5/2012</th>
            <th>6/2012</th>
            <th>7/2012</th>
            <th>8/2012</th>
            <th>9/2012</th>
            <th>10/2012</th>
            <th>11/2012</th>
            <th>12/2012</th>
            <th>1/2013</th>
            <th>2/2013</th>
            <th>3/2013</th>
         </tr>
         <tr>
            <th>Balance:</th>
            <td>&nbsp;</td>
            <td>119,250</td>
            <td>118,500</td>
            <td>117,750</td>
            <td>117,000</td>
            <td>116,250</td>
            <td>115,500</td>
            <td>114,750</td>
            <td>114,000</td>
            <td>113,250</td>
            <td>112,500</td>
            <td>111,750</td>
         </tr>
      </table>
      <h2>Account: 45</h2>
      <table border="1" width="80%">
         <tr>
            <th>Date:</th>
            <th>4/2014</th>
            <th>5/2014</th>
            <th>6/2014</th>
            <th>7/2014</th>
            <th>8/2014</th>
            <th>9/2014</th>
            <th>10/2014</th>
            <th>11/2014</th>
            <th>12/2014</th>
            <th>1/2015</th>
            <th>2/2015</th>
            <th>3/2015</th>
         </tr>
         <tr>
            <th>Balance:</th>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>501</td>
            <td>502</td>
            <td>503</td>
         </tr>
      </table>
   </body>
</html>

呈现为:

enter image description here

相关问题