需要动态更改 simple-page-master 的 master-name

Need to dynamically change the simple-page-master's master-name

我有一个 xml 文档,如下所示。每个重复文档是 PDF 文件中的一页

<AFPXMLFile>
    <docs>
      <regList>
           <region>1</region>
           <secList>
               <col>1</col>
               <lines></lines>
          </secList>
     </regList>
     <regList>
         <region>2</region>
         <secList>
               <col>2</col>
               <lines>
                  <line>IBM BELGIUM xxx</line>
                  <line>xxxxxx</line>
                  <line>xxxx</line>
              </lines>
         </secList>
     </regList>
     <regList></regList>
     <regList></regList>
  </docs>
  <docs></docs>
 </AFPXMLFile>

我的XSL如下:

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

<xsl:template match="AFPXMLFile">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master page-width="21cm" page-height="29.7cm"  margin-top="1.27cm" margin-bottom="1.27cm" margin-left="1.75cm" master-name="A4">
  <fo:region-body   margin-top="1mm" margin-bottom="1mm"/>
  <fo:region-before extent="0mm"/>
  <fo:region-after  extent="0mm"/>
  <fo:region-start  writing-mode="tb-rl" precedence="true" extent="10mm" />  
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4" font-family="sans-serif">
<xsl:for-each select="docs">
    <xsl:for-each select="./regList">
        <xsl:choose>
            <xsl:when test="region = 1">
               <fo:static-content flow-name="xsl-region-before">
                    <xsl:for-each select="./secList/lines">
                        <xsl:for-each select="node()">
                            <fo:block font-size="8pt" color="purple">
                                <xsl:value-of select="."/>
                           </fo:block>                                 
                        </xsl:for-each>
                     </xsl:for-each>
                </fo:static-content>
            </xsl:when>
            <xsl:when test="region = 2">
               <fo:static-content flow-name="xsl-region-start">
                    <xsl:for-each select="./secList/lines">
                        <xsl:for-each select="node()">
                                <fo:block font-size="4pt" padding-before="4pt" text-align="left" color="green">
                                    <xsl:value-of select="."/>
                                </fo:block> 
                        </xsl:for-each>
                     </xsl:for-each>
                 </fo:static-content>    
            </xsl:when>
            <xsl:when test="region = 3">
                <fo:static-content flow-name="xsl-region-body">
                    <xsl:for-each select="./secList/lines">
                        <xsl:for-each select="node()">
                            <fo:block font-size="8pt" color="blue">
                                <xsl:value-of select="."/>
                            </fo:block>
                         </xsl:for-each>
                    </xsl:for-each>
                </fo:static-content>
            </xsl:when>
            <xsl:when test="region = 4">
               <fo:flow flow-name="xsl-region-after">
                    <xsl:for-each select="./secList">
                        <xsl:for-each select="./lines">
                            <xsl:for-each select="node()">
                                <fo:block font-size="8pt" color="orange">
                                    <xsl:value-of select="."/>
                               </fo:block>
                            </xsl:for-each>
                        </xsl:for-each>
                     </xsl:for-each>
               </fo:flow>      
            </xsl:when>  
        </xsl:choose>                        
    </xsl:for-each>
</xsl:for-each>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>

当我 运行 转换时,出现以下错误:

org.apache.fop.fo.ValidationException: For "fo:page-sequence", "fo:static-content" must be declared before "fo:flow"! (No context info available)

我怀疑这是因为它在为每个页面重复静态内容区域。所以我相信我需要为每个页面更改 simple-page-master:master-name 我需要帮助。

根据XSL-FO recommendation,'fo:page-sequence'的内容是:

(title?,folio-prefix?,folio-suffix?,static-content*,flow+)

这意味着所有 fo:static-content 元素必须 之前 fo:flow 元素。

您的样式表动态创建 fo:static-content(如果 region 为 1、2 或 3)或 fo:flow(如果 region 为 4)。从您问题中减少的输入文件中,无法查看 regList 元素是否始终正确排序,以便它们在顺序处理时产生有效输出。

此外,由于每个 docs 元素代表具有不同 headers/footers 的不同文档,您必须创建不同的 fo:page-sequence 而不是一个(否则您会得到太多静态单页序列的内容和流程):

<xsl:for-each select="docs">
    <fo:page-sequence master-reference="A4" font-family="sans-serif">
        <xsl:for-each select="./regList">
            ....
        </xsl:for-each>
    </fo:page-sequence>
</xsl:for-each>

此外,样式表中有一个 奇怪的东西 :您将 fo:static-content 映射到 xsl-region-body 区域,而 fo:flowxsl-region-after 区域,这很不寻常。如果body区域的"real"内容是region=3的内容,则必须先处理region1、2、4,然后然后区域3:

<xsl:for-each select="docs">
    <fo:page-sequence master-reference="A4" font-family="sans-serif">
        <!-- create static contents -->
        <xsl:apply-templates select="./regList[region != '3']"/>
        <!-- create flow -->
        <xsl:apply-templates select="./regList[region = '3']"/>
    </fo:page-sequence>
</xsl:for-each>

用一个额外的模板来匹配 reglist:

<xsl:template match="regList">
    <xsl:choose>
        <xsl:when test="region = '1'">
           <fo:static-content flow-name="xsl-region-before">
                <xsl:for-each select="./secList/lines">
                    <xsl:for-each select="node()">
                        <fo:block font-size="8pt" color="purple">
                            <xsl:value-of select="."/>
                       </fo:block>                                 
                    </xsl:for-each>
                 </xsl:for-each>
            </fo:static-content>
        </xsl:when>
        <xsl:when test="region = '2'">
           <fo:static-content flow-name="xsl-region-start">
                <xsl:for-each select="./secList/lines">
                    <xsl:for-each select="node()">
                            <fo:block font-size="4pt" padding-before="4pt" text-align="left" color="green">
                                <xsl:value-of select="."/>
                            </fo:block> 
                    </xsl:for-each>
                 </xsl:for-each>
             </fo:static-content>    
        </xsl:when>
        <xsl:when test="region = '3'">
            <fo:flow flow-name="xsl-region-body">
                <xsl:for-each select="./secList/lines">
                    <xsl:for-each select="node()">
                        <fo:block font-size="8pt" color="blue">
                            <xsl:value-of select="."/>
                        </fo:block>
                     </xsl:for-each>
                </xsl:for-each>
            </fo:flow>
        </xsl:when>
        <xsl:when test="region = '4'">
           <fo:static-content flow-name="xsl-region-after">
                <xsl:for-each select="./secList">
                    <xsl:for-each select="./lines">
                        <xsl:for-each select="node()">
                            <fo:block font-size="8pt" color="orange">
                                <xsl:value-of select="."/>
                           </fo:block>
                        </xsl:for-each>
                    </xsl:for-each>
                 </xsl:for-each>
           </fo:static-content>      
        </xsl:when>
    </xsl:choose>
</xsl:template>

或几个较小的模板:

<xsl:template match="reglist[region = '1']">
   <fo:static-content flow-name="xsl-region-before">
        <xsl:for-each select="./secList/lines">
            <xsl:for-each select="node()">
                <fo:block font-size="8pt" color="purple">
                    <xsl:value-of select="."/>
                </fo:block>                                 
            </xsl:for-each>
        </xsl:for-each>
    </fo:static-content>
</xsl:template>

<xsl:template match="reglist[region = '2']">
    ...
</xsl:template>

...