如何修改XSL-FO样式表在A4页高效放置多份发票(Apache FOP)
问题根源
你当前的样式表中,每个<Invoice_Download>都会生成独立的<fo:page-sequence>,这是导致每份发票独占一页的核心原因——每个page-sequence对应PDF里的一页(即便发票内容仅占1/3页面)。
解决方案
要实现多发票紧凑排版且不拆分,需把所有发票放在**同一个page-sequence**中,同时给每个发票的容器块添加不拆分规则。具体修改如下:
1. 调整根模板,统一生成单个page-sequence
将原来分散生成多个page-sequence的逻辑,改为在一个page-sequence的flow里渲染所有发票,同时保留第一页显示标题的页眉规则:
<xsl:template match="/"> <fo:root> <fo:layout-master-set> <fo:simple-page-master master-name="invoice-page" page-width="21cm" margin="0.5cm"> <fo:region-body margin="1cm" /> <fo:region-before extent="3cm" /> <fo:region-after extent="0.5cm" /> </fo:simple-page-master> <!-- 区分第一页与后续页的模板引用,实现仅第一页显示标题 --> <fo:page-sequence-master master-name="invoice-sequence"> <fo:repeatable-page-master-alternatives> <fo:conditional-page-master-reference master-reference="invoice-page" page-position="first" /> <fo:conditional-page-master-reference master-reference="invoice-page" /> </fo:repeatable-page-master-alternatives> </fo:page-sequence-master> </fo:layout-master-set> <!-- 仅创建一个page-sequence,承载所有发票内容 --> <fo:page-sequence master-reference="invoice-sequence"> <fo:static-content flow-name="xsl-region-before"> <fo:block text-align="center" font-size="18pt"> <xsl:if test="page-position()='first'">INVOICES</xsl:if> </fo:block> </fo:static-content> <fo:flow flow-name="xsl-region-body"> <xsl:apply-templates select="Download/Invoice_Download"/> </fo:flow> </fo:page-sequence> </fo:root> </xsl:template>
2. 修改Invoice_Download模板,生成可堆叠的发票块
去掉原模板中的<fo:page-sequence>,改为生成包裹发票内容的块,并添加keep-together.within-page="always"确保整个发票不被拆分到两页:
<xsl:template match="Invoice_Download"> <!-- 用block包裹发票内容,添加不拆分规则与间距区分不同发票 --> <fo:block keep-together.within-page="always" margin-bottom="1cm"> <!-- 替换为你原来的发票具体内容 --> ........... </fo:block> </xsl:template>
关键说明
- 单个
page-sequence:所有发票都在同一个page-sequence的flow中,Apache FOP会自动将能放下的发票排在同一页,空间不足时自动分页。 keep-together.within-page="always":强制每个发票作为完整整体,不会被拆分到两页。- 页眉控制:通过
page-position()='first'实现仅第一页显示"INVOICES"标题,后续页页眉为空,匹配原需求。
完整修改后的样式表
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="/"> <fo:root> <fo:layout-master-set> <fo:simple-page-master master-name="invoice-page" page-width="21cm" margin="0.5cm"> <fo:region-body margin="1cm" /> <fo:region-before extent="3cm" /> <fo:region-after extent="0.5cm" /> </fo:simple-page-master> <fo:page-sequence-master master-name="invoice-sequence"> <fo:repeatable-page-master-alternatives> <fo:conditional-page-master-reference master-reference="invoice-page" page-position="first" /> <fo:conditional-page-master-reference master-reference="invoice-page" /> </fo:repeatable-page-master-alternatives> </fo:page-sequence-master> </fo:layout-master-set> <fo:page-sequence master-reference="invoice-sequence"> <fo:static-content flow-name="xsl-region-before"> <fo:block text-align="center" font-size="18pt"> <xsl:if test="page-position()='first'">INVOICES</xsl:if> </fo:block> </fo:static-content> <fo:flow flow-name="xsl-region-body"> <xsl:apply-templates select="Download/Invoice_Download"/> </fo:flow> </fo:page-sequence> </fo:root> </xsl:template> <xsl:template match="Invoice_Download"> <fo:block keep-together.within-page="always" margin-bottom="1cm"> <!-- 替换为你的发票具体内容 --> ........... </fo:block> </xsl:template> </xsl:stylesheet>
内容的提问来源于stack exchange,提问作者ashish
相关产品推荐
相关产品推荐

