XSLT:小计

时间:2012-01-03 17:14:42

标签: xslt xslt-1.0 xsl-fo

源XML:

<Root>
    <Data>
        <Code>A</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>A</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>B</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>A</Code>
        <Value>2</Value>
    </Data>
    <Data>
        <Code>C</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>A</Code>
        <Value>5</Value>
    </Data>
    <Data>
        <Code>B</Code>
        <Value>4</Value>
    </Data>
    <Data>
        <Code>A</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>C</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>B</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>A</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>C</Code>
        <Value>5</Value>
    </Data>
....
</Root>

XSL-FO代码:

我的代码(XSL-FO)包含3列,其中每列包含'A','B','C'的内容

<fo:table-body>
    <xfd:table-row-repeat xpath="Root/Data" font-family="Arial Narrow" font-size="10pt" padding-after="0.55cm">
        <xsl:if test="Code='A'">
        <fo:table-cell>
        <fo:block height="12pt">Value
        </fo:block>
        </fo:table-cell>
        <fo:table-cell>
        <fo:block height="12pt" border="0.1pt solid black" text-align="center">
            <xsl:value-of select="Value" /> 
        </fo:block>
        </fo:table-cell>
        <fo:table-cell>
        <fo:block height="12pt">Points</fo:block> 
        </fo:table-cell>
        </xsl:if>
    </xfd:table-row-repeat>
</fo:table-body>

每列的相同代码显示'B'和&amp;的值。 'C' 在表格页脚中,我要得到“A”,“B”,“C”

这些小计
<fo:table-body>
    <xfd:table-row-repeat xpath="Root/Data" font-family="Arial Narrow" font-size="10pt" padding-after="0.55cm">
        <xsl:if test="Code='A'">
        <fo:table-cell>
        <fo:block height="12pt">SubTotal
        </fo:block>
        </fo:table-cell>
        <fo:table-cell>
        <fo:block height="12pt" border="0.1pt solid black" text-align="center">
            <--Here Sum of first 15 A's. if the A's or B's or C's exceed by 15, then the table flows to 2nd Page. In that case, 1st Page table-footer shows individual subtotals of first 15 A's, 15 B's and C's. In 2nd Page, the subtotals should contain Subtotal of first 15 A's+ Succeeding A's, in the same way B's and C's --> 
        </fo:block>
        </fo:table-cell>
        <fo:table-cell>
        <fo:block height="12pt">Points</fo:block> 
        </fo:table-cell>
        </xsl:if>
    </xfd:table-row-repeat>
</fo:table-body>

此处XSL-FO代码仅显示一列(For Root / Data / Code ='A'),其他2列('B'和'C')由相同的代码组成。

条件详情:

Condition 1): when Root/Data/Code = 'A' or 'B' or 'C'
   i need individual totals of 'A', 'B' and 'C' in Table-Footer individual Column.

Condition 2): inturn if individual count(Root/Data/Code) of 'A', 'B' & 'C' crosses 15.          Then Page flows to 2nd Page then Table-Footer in 2nd Page needs to contains subtotal of first 15 A's + the sum of succeeding A's in the same way for B's And C's

即,如果源XML中存在20个A,10个B和25个C.

In 1st Page, Table-Footer

SubtotalI(Value of 15 A's)=
SubtotalII(Value 10 B's)=   
SubtotalIII(Value 15 C's)=

In 2nd Page, Table-Footer

SubtotalI(15 A's+ next 5 A's)=   
SubtotalII(Value 10 B's)= <!--No Change as count of B's is less than 15 -->
SubtotalIII(15 C's + next 10 C's)=

我正在尝试使用xsl:key通过代码标记进行分组来评估“A”,“B”和“C”的总和。由于我是XSLT的新手,我发现使用xsl:key解决这个逻辑太难了。任何人都可以帮助解决这个逻辑吗?

先谢谢

1 个答案:

答案 0 :(得分:0)

您尝试实现的目标存在一些困难。实际上,计算给定点的小计是最简单的。你只需要前面的轴和一个和来计算它:

sum(preceding::Value[../Code = 'A'])

要包含当前值,请使用union运算符,如下所示:

sum(Value[../Code = 'A'] | preceding::Value[../Code = 'A'])

更大的难点是在每个页面上显示不同的表格“页脚”。页眉和页脚会自动在页面上重复,但表格跨越的所有页面的内容都是相同的。我看到的唯一解决方案是自己打破桌面,每次都添加一个不同的表格页脚。

到目前为止,最简单的方法是一次只获取固定数量的数据元素,并将它们显示在单独的表中。您可以在一个for-each中循环遍历A,B和C类型,为每个值分别设置一行。这样,表总是具有相同的行数。您可以尝试使用可以包含的数字来确定一页上适合的数量。

以下代码返回包含前10个Data值的表。 A,B和C值彼此笔直地放置,但如果您愿意,可以分别将它们分别放置在左侧,中间和右侧。在表格的底部添加了三行,包括A,B和C的小计。

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fo="http://www.w3.org/1999/XSL/Format">

    <xsl:template match="/">
        <fo:root>
            <fo:layout-master-set>
                <fo:simple-page-master master-name="global">
                    <fo:region-body/>
                </fo:simple-page-master>
            </fo:layout-master-set>

            <fo:page-sequence master-reference="global">
                <fo:flow flow-name="xsl-region-body">

                    <fo:block>
                        <fo:table table-layout="fixed" width="150mm" border-style="solid">
                            <fo:table-column column-width="50mm"/>
                            <fo:table-column column-width="50mm"/>
                            <fo:table-column column-width="50mm"/>

                            <fo:table-body font-size="7pt">
                                <xsl:for-each select="/Root/Data[10 >= position()]">
                                    <fo:table-row border-style="solid">
                                        <fo:table-cell> 
                                            <fo:block height="12pt">
                                                <xsl:value-of select="Code" />
                                            </fo:block> 
                                        </fo:table-cell> 
                                        <fo:table-cell>
                                            <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
                                                <xsl:value-of select="Value" />  
                                            </fo:block> 
                                        </fo:table-cell> 
                                        <fo:table-cell> 
                                            <fo:block height="12pt">Points</fo:block>  
                                        </fo:table-cell> 
                                    </fo:table-row>

                                    <xsl:if test="position() = last()">
                                        <fo:table-row border-style="solid">
                                            <fo:table-cell> 
                                                <fo:block height="12pt">Subtotal A</fo:block> 
                                            </fo:table-cell> 
                                            <fo:table-cell>
                                                <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
                                                    <xsl:value-of select="sum(preceding::Value[../Code = 'A'] | Value[../Code = 'A'])" />  
                                                </fo:block> 
                                            </fo:table-cell> 
                                            <fo:table-cell> 
                                                <fo:block height="12pt">Points</fo:block>  
                                            </fo:table-cell> 
                                        </fo:table-row>
                                        <fo:table-row border-style="solid">
                                            <fo:table-cell> 
                                                <fo:block height="12pt">Subtotal B</fo:block> 
                                            </fo:table-cell> 
                                            <fo:table-cell>
                                                <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
                                                    <xsl:value-of select="sum(preceding::Value[../Code = 'B'] | Value[../Code = 'B'])" />  
                                                </fo:block> 
                                            </fo:table-cell> 
                                            <fo:table-cell> 
                                                <fo:block height="12pt">Points</fo:block>  
                                            </fo:table-cell> 
                                        </fo:table-row>
                                        <fo:table-row border-style="solid">
                                            <fo:table-cell> 
                                                <fo:block height="12pt">Subtotal C</fo:block> 
                                            </fo:table-cell> 
                                            <fo:table-cell>
                                                <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
                                                    <xsl:value-of select="sum(preceding::Value[../Code = 'C'] | Value[../Code = 'C'])" />  
                                                </fo:block> 
                                            </fo:table-cell> 
                                            <fo:table-cell> 
                                                <fo:block height="12pt">Points</fo:block>  
                                            </fo:table-cell> 
                                        </fo:table-row>
                                    </xsl:if>
                                </xsl:for-each>
                            </fo:table-body>
                        </fo:table>
                    </fo:block>

                </fo:flow>
            </fo:page-sequence>

        </fo:root>
    </xsl:template>

</xsl:stylesheet>

您仍然需要一些东西来确定您需要的n个数据项的表数,然后执行一些递归调用以输出所有这些表。希望这足以让你再次前进!

PS:我注意到你正在使用xfd前缀。看起来您正在使用Ecrion的XF Designer。我对它不太熟悉。上面的代码是一个简单的XSLT 1.0解决方案。不确定它是否适用于XF Designer,请告诉我..