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:root
。 fo: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 的结构,否则我们无法帮助您。
这是我第一次体验 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:root
。 fo: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 的结构,否则我们无法帮助您。