XSLT 1.0:计算每页的小计
XSLT 1.0: Calculating Subtotal on each page
来源XML:
<Root>
<Data>
<Value>10</Value>
</Data>
<Data>
<Value>10</Value>
</Data>
<Data>
<Value>15</Value>
</Data>
<Data>
<Value>2</Value>
</Data>
<Data>
<Value>32</Value>
</Data>
<Data>
<Value>5</Value>
</Data>
<Data>
<Value>40</Value>
</Data>
<Data>
<Value>18</Value>
</Data>
<Data>
<Value>50</Value>
</Data>
<Data>
<Value>1</Value>
</Data>
<Data>
<Value>43</Value>
</Data>
<Data>
<Value>5</Value>
</Data>
<Data>
<Value>21</Value>
</Data>
<Data>
<Value>87</Value>
</Data>
<Data>
<Value>8</Value>
</Data>
....
</Root>
XSL-FO 代码:
我的代码包含一个 table 行和一个 table- 页脚
<fo:table>
<fo:table-column column-width="50mm"/>
<fo:table-column column-width="50mm"/>
<fo:table-footer>
<fo:table-row>
<fo:table-cell>
<fo:block>Subtotal: </fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<fo:retrieve-table-marker retrieve-class-name="Subtotal" retrieve-position-within-table="last-starting"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-footer>
<fo:table-body>
<xsl:for-each select="/Root/Data">
<fo:table-row>
<fo:table-cell>
<fo:block>Value:</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<xsl:value-of select="Value"/>
<fo:marker marker-class-name="Subtotal">
<xsl:variable name="position" select="position()"/>
<xsl:value-of xpath="sum(../Data[position() <= $position]/Value)"/>
</fo:marker>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
我正在从上面的 table 生成 PDF 输出。在 PDF 中,table 每页最多可以有 15 table 行。在每一页上,需要计算小计,即仅对当前页面上显示的值求和。
我上面的 table(我找到的唯一解决方案是使用 table-标记)计算第 1 页的正确小计,但第 2 页失败,等等。它附加了所有以前的小计页到当前页。
例如:如果第1页显示的Value元素小计为10,第2页显示的Values小计为20,那么我的table将显示在第1页,小计为10,但是在第 2 页上,小计将是 30,而不是 20。有人可以帮助解决这个问题吗?
提前致谢
在 XSLT 1 中使用“位置分组”,如
<xsl:for-each select="Root/Data[position() mod 15 = 1]">
<xsl:variable name="data-of-page" select=". | following-sibling::Data[position() < 15]"/>
<xsl:for-each select="$data-of-page">
<fo:table-row>
<fo:table-cell>
<fo:block>Value:</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<xsl:value-of select="Value"/>
<xsl:if test="position() = last()">
<fo:marker marker-class-name="Subtotal">
<xsl:value-of xpath="sum($data-of-page/Value)"/>
</fo:marker>
</xsl:if>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</xsl:for-each>
这个版本的唯一优点是,如果第一页少于 15 行,它会给出正确的小计;例如,如果 table.
开头之前有标题或文本
<xsl:stylesheet
version="1.0"
xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*" />
<xsl:output indent="yes" />
<xsl:variable name="rows-per-page" select="15" />
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions"
xml:lang="en">
<fo:layout-master-set>
<fo:simple-page-master master-name="spm" size="A7">
<fo:region-body margin="20mm" margin-top="15mm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="spm">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates />
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="Root">
<fo:block />
<fo:table space-before="3lh">
<fo:table-column column-width="50%"/>
<fo:table-column column-width="50%"/>
<fo:table-footer>
<fo:table-row>
<fo:table-cell>
<fo:block>Subtotal: </fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block-container>
<fo:retrieve-table-marker retrieve-class-name="Remainder" retrieve-position-within-table="first-starting"/>
<fo:retrieve-table-marker retrieve-class-name="Subtotal" retrieve-position-within-table="last-starting"/>
</fo:block-container>
</fo:table-cell>
</fo:table-row>
</fo:table-footer>
<fo:table-body>
<xsl:apply-templates />
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="Data">
<fo:table-row>
<fo:table-cell>
<fo:block>Value:</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<fo:marker marker-class-name="Subtotal">
<xsl:if test="position() != last()">
<fo:block-container width="4em" background-color="white">
<fo:block>
<xsl:value-of
select="sum(preceding-sibling::Data[position() < $rows-per-page]) + Value"/>
</fo:block>
</fo:block-container>
</xsl:if>
</fo:marker>
<fo:marker marker-class-name="Remainder">
<fo:block-container width="4em" z-index="-1" absolute-position="absolute">
<fo:block>
<xsl:value-of
select="sum(following-sibling::Data) + Value"/>
</fo:block>
</fo:block-container>
</fo:marker>
<xsl:value-of select="Value"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:template>
</xsl:stylesheet>
来源XML:
<Root>
<Data>
<Value>10</Value>
</Data>
<Data>
<Value>10</Value>
</Data>
<Data>
<Value>15</Value>
</Data>
<Data>
<Value>2</Value>
</Data>
<Data>
<Value>32</Value>
</Data>
<Data>
<Value>5</Value>
</Data>
<Data>
<Value>40</Value>
</Data>
<Data>
<Value>18</Value>
</Data>
<Data>
<Value>50</Value>
</Data>
<Data>
<Value>1</Value>
</Data>
<Data>
<Value>43</Value>
</Data>
<Data>
<Value>5</Value>
</Data>
<Data>
<Value>21</Value>
</Data>
<Data>
<Value>87</Value>
</Data>
<Data>
<Value>8</Value>
</Data>
....
</Root>
XSL-FO 代码: 我的代码包含一个 table 行和一个 table- 页脚
<fo:table>
<fo:table-column column-width="50mm"/>
<fo:table-column column-width="50mm"/>
<fo:table-footer>
<fo:table-row>
<fo:table-cell>
<fo:block>Subtotal: </fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<fo:retrieve-table-marker retrieve-class-name="Subtotal" retrieve-position-within-table="last-starting"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-footer>
<fo:table-body>
<xsl:for-each select="/Root/Data">
<fo:table-row>
<fo:table-cell>
<fo:block>Value:</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<xsl:value-of select="Value"/>
<fo:marker marker-class-name="Subtotal">
<xsl:variable name="position" select="position()"/>
<xsl:value-of xpath="sum(../Data[position() <= $position]/Value)"/>
</fo:marker>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
我正在从上面的 table 生成 PDF 输出。在 PDF 中,table 每页最多可以有 15 table 行。在每一页上,需要计算小计,即仅对当前页面上显示的值求和。
我上面的 table(我找到的唯一解决方案是使用 table-标记)计算第 1 页的正确小计,但第 2 页失败,等等。它附加了所有以前的小计页到当前页。
例如:如果第1页显示的Value元素小计为10,第2页显示的Values小计为20,那么我的table将显示在第1页,小计为10,但是在第 2 页上,小计将是 30,而不是 20。有人可以帮助解决这个问题吗?
提前致谢
在 XSLT 1 中使用“位置分组”,如
<xsl:for-each select="Root/Data[position() mod 15 = 1]">
<xsl:variable name="data-of-page" select=". | following-sibling::Data[position() < 15]"/>
<xsl:for-each select="$data-of-page">
<fo:table-row>
<fo:table-cell>
<fo:block>Value:</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<xsl:value-of select="Value"/>
<xsl:if test="position() = last()">
<fo:marker marker-class-name="Subtotal">
<xsl:value-of xpath="sum($data-of-page/Value)"/>
</fo:marker>
</xsl:if>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</xsl:for-each>
这个版本的唯一优点是,如果第一页少于 15 行,它会给出正确的小计;例如,如果 table.
开头之前有标题或文本<xsl:stylesheet
version="1.0"
xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*" />
<xsl:output indent="yes" />
<xsl:variable name="rows-per-page" select="15" />
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions"
xml:lang="en">
<fo:layout-master-set>
<fo:simple-page-master master-name="spm" size="A7">
<fo:region-body margin="20mm" margin-top="15mm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="spm">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates />
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="Root">
<fo:block />
<fo:table space-before="3lh">
<fo:table-column column-width="50%"/>
<fo:table-column column-width="50%"/>
<fo:table-footer>
<fo:table-row>
<fo:table-cell>
<fo:block>Subtotal: </fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block-container>
<fo:retrieve-table-marker retrieve-class-name="Remainder" retrieve-position-within-table="first-starting"/>
<fo:retrieve-table-marker retrieve-class-name="Subtotal" retrieve-position-within-table="last-starting"/>
</fo:block-container>
</fo:table-cell>
</fo:table-row>
</fo:table-footer>
<fo:table-body>
<xsl:apply-templates />
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="Data">
<fo:table-row>
<fo:table-cell>
<fo:block>Value:</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<fo:marker marker-class-name="Subtotal">
<xsl:if test="position() != last()">
<fo:block-container width="4em" background-color="white">
<fo:block>
<xsl:value-of
select="sum(preceding-sibling::Data[position() < $rows-per-page]) + Value"/>
</fo:block>
</fo:block-container>
</xsl:if>
</fo:marker>
<fo:marker marker-class-name="Remainder">
<fo:block-container width="4em" z-index="-1" absolute-position="absolute">
<fo:block>
<xsl:value-of
select="sum(following-sibling::Data) + Value"/>
</fo:block>
</fo:block-container>
</fo:marker>
<xsl:value-of select="Value"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:template>
</xsl:stylesheet>