XSL-FO 如何将页码从模板传播到另一个模板

XSL-FO how to propagate page numbering from template to another

这是我第一次体验 XSL-FO 打印。

有 2 个模板,每个模板都有自己的 layout.xsl

需要编辑第二个模板的页码以继承第一个模板。

例子

模板一有4页,那么模板二应该从第1页开始。 5 不是 1!

我有一个想法,但仍然行不通;是创建调用这两个模板的第三个模板

<xsl:template>
        <xsl:call-template name="templateOne" />
        <!-- <xsl:block break-after="page"/> -->
        <xsl:call-template name="templateTwo" />
        <!-- <xsl:block break-after="page"/> -->
</xsl:template>

templateOne 布局:

<xsl:template match="/">
        <fo:root>       
            <xsl:call-template name="LayoutMasterSet"/>
            <xsl:variable name="TheVeryLastPage" select="."/>
            <xsl:choose>
                <xsl:when test="$titel='Anwendungsprotokoll'">
                    <fo:page-sequence master-reference="landscape" initial-page-number="1" format="1">
                        <!-- Kopfzeile -->
                        <xsl:call-template name="StandardKopfzeile">
                            <xsl:with-param name="TheVeryLastPage"><xsl:value-of select="$TheVeryLastPage"/></xsl:with-param>
                        </xsl:call-template>
                        <!-- Fusszeile -->
                        <xsl:call-template name="StandardFusszeile">
                            <xsl:with-param name="TheVeryLastPage"><xsl:value-of select="$TheVeryLastPage"/></xsl:with-param>
                        </xsl:call-template>
                        <fo:flow flow-name="xsl-region-body">
                            <fo:block font-size="8pt" line-height="10pt">
                                <xsl:apply-templates select="/*"/>
                            </fo:block>
                            <fo:block id="{generate-id($TheVeryLastPage)}"/>
                        </fo:flow>
                    </fo:page-sequence>
                </xsl:when>
                <xsl:otherwise>
                    <fo:page-sequence master-reference="default-pages" initial-page-number="1" format="1">
                        <!-- Kopfzeile -->
                        <xsl:call-template name="StandardKopfzeile">
                            <xsl:with-param name="TheVeryLastPage"><xsl:value-of select="$TheVeryLastPage"/></xsl:with-param>
                        </xsl:call-template>
                        <!-- Fusszeile -->
                        <xsl:call-template name="StandardFusszeile">
                            <xsl:with-param name="TheVeryLastPage"><xsl:value-of select="$TheVeryLastPage"/></xsl:with-param>
                        </xsl:call-template>
                        <fo:flow flow-name="xsl-region-body">
                            <fo:block font-size="8pt" line-height="10pt">
                                <xsl:apply-templates select="/*"/>
                            </fo:block>
                            <fo:block id="{generate-id($TheVeryLastPage)}"/>
                        </fo:flow>
                    </fo:page-sequence>
                </xsl:otherwise>
            </xsl:choose>
        </fo:root>
    </xsl:template>

templateTwo 的布局:

<xsl:template match="/">
        <fo:root xsl:use-attribute-sets="font.arial.8.normal.black">
            <xsl:call-template name="LayoutMasterSet"/>
            <xsl:variable name="TheVeryLastPage" select="."/>
            <fo:page-sequence master-reference="default-pages" initial-page-number="1" format="1">
                <xsl:call-template name="StandardHeader"/>
                <xsl:call-template name="GeneralFooter">
                    <xsl:with-param name="TheVeryLastPage">
                        <xsl:value-of select="$TheVeryLastPage"/>
                    </xsl:with-param>
                </xsl:call-template>
                <xsl:apply-templates select="/*"/>
            </fo:page-sequence>
        </fo:root>
    </xsl:template>
    <!-- ++++++++++++++++++++++++++++++++++Layout Master Set+++++++++++++++++++++++++++++++++++++++++++++ -->
    <xsl:template name="LayoutMasterSet">
        <fo:layout-master-set>
            <fo:simple-page-master master-name="any-page" page-height="297mm" page-width="210mm" margin-top="1.5cm" margin-bottom="1.5cm" margin-left="1.5cm" margin-right="1.5cm">
                <fo:region-body margin-top="2cm" margin-bottom="2cm" column-count="{$columns}"/>
                <fo:region-before extent="2cm" region-name="region-before"/>
                <fo:region-after extent="2cm" region-name="region-after"/>
            </fo:simple-page-master>
            <fo:page-sequence-master master-name="default-pages">
                <fo:repeatable-page-master-alternatives>
                    <fo:conditional-page-master-reference page-position="any" master-reference="any-page"/>
                </fo:repeatable-page-master-alternatives>
            </fo:page-sequence-master>
        </fo:layout-master-set>
    </xsl:template>

这个想法行不通,它给了我:

saving .xsl. <anonymous development build> javax.xml.transform.TransformerException: org.apache.fop.fo.ValidationException: "{http://www.w3.org/1999/XSL/Format}table" is not a valid child of "fo:page-sequence"!

ERROR |17:33:05,752|DefaultExceptionHandler.logException:75 (WorkerThread 17:31:48)[-1] TRANSFORMATION_ERROR [] <anonymous development build>
de.vodafone.core.exception.BadProcessingException: [-1] TRANSFORMATION_ERROR []
    at de.vodafone.app.epos.shared.print.fop.FopPrintService.addToPageable(FopPrintService.java:165)
    at de.vodafone.app.epos.shared.print.fop.FopPrintService.print(FopPrintService.java:78)
    at de.vodafone.app.epos.shared.print.fop.PrintServiceDelegator.print(PrintServiceDelegator.java:53)
    at de.vodafone.app.epos.shared.print.activity.AbstractPrintAgent.execute(AbstractPrintAgent.java:213)
    at de.vodafone.app.epos.shared.activity.ActivityManager.execute(ActivityManager.java:78)
    at de.vodafone.app.epos.client.plugin.order.manager.common.presentation.AbstractOrderFacade.executeActivities(AbstractOrderFacade.java:210)
    at de.vodafone.app.epos.client.plugin.order.manager.common.presentation.SingleCustomerOrderFacade.handleAfterSave(SingleCustomerOrderFacade.java:101)
    at de.vodafone.app.epos.client.plugin.fixednet.activation.mvc.FNActivationFacade.handleAfterSave(FNActivationFacade.java:370)
    at de.vodafone.app.epos.client.plugin.order.manager.common.presentation.AbstractOrderFacade.save(AbstractOrderFacade.java:335)
    at de.vodafone.app.epos.client.plugin.order.manager.common.presentation.AbstractOrderFacade.save(AbstractOrderFacade.java:298)
    at de.vodafone.app.epos.client.plugin.order.manager.common.presentation.AbstractOrderFacade.send(AbstractOrderFacade.java:117)
    at de.vodafone.app.epos.client.plugin.order.manager.common.presentation.AbstractOrderController.send(AbstractOrderController.java:943)
    at de.vodafone.app.epos.client.plugin.order.manager.common.presentation.AbstractOrderController.onSend(AbstractOrderController.java:861)
    at de.vodafone.app.epos.client.plugin.order.manager.common.presentation.AbstractOrderController.doExecuteCommand(AbstractOrderController.java:1258)
    at de.vodafone.app.epos.client.framework.ui.action.AbstractWidgetActionUIJob.execute(AbstractWidgetActionUIJob.java:45)
    at de.vodafone.app.epos.client.framework.ui.action.RunnableBuilder$CommandRunnable.run(RunnableBuilder.java:196)
    at de.vodafone.app.epos.client.framework.ui.action.AbstractUIJob.run(AbstractUIJob.java:50)
    at EDU.oswego.cs.dl.util.concurrent.QueuedExecutor$RunLoop.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:748)
Caused by: javax.xml.transform.TransformerException: org.apache.fop.fo.ValidationException: "{http://www.w3.org/1999/XSL/Format}table" is not a valid child of "fo:page-sequence"! (Siehe Position 17:276)
    at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:469)
    at de.vodafone.app.epos.shared.print.fop.FopPrintService.addToPageable(FopPrintService.java:156)
    ... 18 more
Caused by: org.apache.fop.fo.ValidationException: "{http://www.w3.org/1999/XSL/Format}table" is not a valid child of "fo:page-sequence"! (Siehe Position 17:276)
    at org.apache.fop.events.ValidationExceptionFactory.createException(ValidationExceptionFactory.java:38)
    at org.apache.fop.events.EventExceptionManager.throwException(EventExceptionManager.java:54)
    at org.apache.fop.events.DefaultEventBroadcaster.invoke(DefaultEventBroadcaster.java:175)
    at com.sun.proxy.$Proxy1.invalidChild(Unknown Source)
    at org.apache.fop.fo.FONode.invalidChildError(FONode.java:534)
    at org.apache.fop.fo.FONode.invalidChildError(FONode.java:517)
    at org.apache.fop.fo.pagination.PageSequence.validateChildNode(PageSequence.java:147)
    at org.apache.fop.fo.FOTreeBuilder$MainFOHandler.startElement(FOTreeBuilder.java:267)
    at org.apache.fop.fo.FOTreeBuilder.startElement(FOTreeBuilder.java:171)
    at org.apache.xalan.transformer.TransformerIdentityImpl.startElement(TransformerIdentityImpl.java:1020)
    at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
    at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
    at org.apache.xalan.transformer.TransformerIdentityImpl.transform(TransformerIdentityImpl.java:452)
    ... 19 more

因为我不是编写这些巨大模板的人,所以我无法在 fo:page-sequence

中找到 fo:table 的错误位置

此外,页码不会传播。我想定义一个参数,最初由 1 并由 templateOne 的最后一页设置为递增 1,并在修复之前的形成异常后初始化 Template 2 的第一页。

您的帮助真的很实用 非常感谢 玛丽亚姆

要解决 fo:table 问题,您的 fo:page-sequence 中需要一个 fo:flow(参见 https://www.w3.org/TR/xsl11/#fo_page-sequence)。 templateOne 有它(但是 fo:flow 里面的 fo:block 的属性可以放在 fo:flow 上, fo:block 可以省略)。 templateTwo 在其 fo:page-sequence.

中没有 fo:flow

您的另一个问题是两个模板都创建了一个 fo:rootfo:root顾名思义就是FO文档的根目录。由于您正在生成的 FO 文档也是一个 XML 文档,因此该文档只能有一个 'document' 元素,即一个 fo:root.

请参阅 XSL 1.1 推荐标准第 6.4.1.6 节“分页树结构”中的图表 (https://www.w3.org/TR/xsl11/#d0e7181)

但是,图表未能显示 fo:root 可能包含多个 fo:page-sequence(请参阅 https://www.w3.org/TR/xsl11/#fo_root)。

要让 templateOne 和 templateTwo 协同工作,您应该生成一个 fo:root 和一个 fo:layout-master-set,并让 templateOne 和 templateTwo 从 fo:page-sequence 级别开始生成内容。类似于:

fo:root
  fo:layout-master-set
  fo:page-sequence (generated by templateOne)
  fo:page-sequence (generated by templateTwo)

如果你都做到了,那么你就解决了标题中的问题。每个 fo:page-sequence 上的 initial-page-number 属性(参见 https://www.w3.org/TR/xsl11/#initial-page-number)的默认值将使第二个 fo:page-sequence 从最后一个页码之后的页码开始前一个 fo:page-sequence.

另一个潜伏的问题是 templateOne 和 templateTwo 都包括:

<xsl:apply-templates select="/*"/>

如果您正在处理一份源文档,那么您将获得两份内容副本。除非我们更了解您要处理的 XML 的结构,否则我们无法帮助您。