XSL:FO 为 PDF 生成应用 html 定义规则时出现问题

XSL:FO Problem in applying html definition rules for PDF generation

我正在通过 apache FOP 从模型 class 读取动态数据,从 xsl:fo 生成 pdf。以下是 xsl:fo 结构:

<xsl:template match="ProductData">
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
        <fo:layout-master-set>
            <fo:simple-page-master master-name="simple"
                page-height="20cm" page-width="10.5cm" margin-left="0.2cm"
                margin-right="0.2cm">
                <fo:region-body margin-top="0.5cm" />
            </fo:simple-page-master>
        </fo:layout-master-set>
        <fo:page-sequence master-reference="simple">
            <fo:flow flow-name="xsl-region-body">

                <fo:block font-family="Arial" font-size="7pt" font-weight="normal">

                    <fo:table border-left-style="double" border-right-style="double"
                        border-top-style="double" border-width="1mm" width="18.0cm">
                        <fo:table-body height="2cm">
                            <fo:table-row border-top="solid 0.3mm #E0E0E0">
                                <fo:table-cell>
                                    <fo:block margin-left="" margin-right="1.5cm"
                                        margin-top="0.0cm">
                                        <fo:external-graphic width="3cm" height="2cm">
                                            <xsl:attribute name="src"><xsl:value-of
                                                select="pdfLogo" /></xsl:attribute>
                                        </fo:external-graphic>
                                    </fo:block>
                                </fo:table-cell>
                            </fo:table-row>
                        </fo:table-body>
                    </fo:table>

                    <fo:table>
                        <fo:table-column column-number="1" column-width="3cm" />
                        <fo:table-column column-number="2" column-width="2cm" />
                        <fo:table-column column-number="3" column-width="5cm" />
                        <fo:table-body height="10cm">
                            <xsl:for-each select="./productList/product">
                                <fo:table-row border="solid 0.1mm black">

                                    <fo:table-cell text-align="left">
                                        <fo:block>
                                            <xsl:value-of select="name" />
                                        </fo:block>

                                    </fo:table-cell>
                                    <fo:table-cell text-align="center">
                                        <fo:block>
                                            <xsl:value-of select="productDescription" />
                                        </fo:block>

                                    </fo:table-cell>
                                    <fo:table-cell text-align="left">
                                        <fo:block>
                                            <xsl:value-of select="price" />
                                        </fo:block>

                                    </fo:table-cell>

                                </fo:table-row>
                            </xsl:for-each>
                        </fo:table-body>
                    </fo:table>
                </fo:block>
            </fo:flow>
        </fo:page-sequence>
    </fo:root>
</xsl:template>

这里 <xsl:value-of select="productDescription" /> 是一个文本数据,它有 html 个标签,因此要保留格式。所以我创建了一组规则如下:

<xsl:template match="p">
  <fo:block font-size="12pt" line-height="15pt"
    space-after="12pt">
    <xsl:apply-templates select="*|text()"/>
  </fo:block>
</xsl:template>
    <xsl:template match="br">
        <fo:block>
        </fo:block>
    </xsl:template>
    <xsl:template match="ul">
  <fo:list-block provisional-distance-between-starts="1cm"
    provisional-label-separation="0.5cm">
    <xsl:attribute name="space-after">
      <xsl:choose>
        <xsl:when test="ancestor::ul or ancestor::ol">
          <xsl:text>0pt</xsl:text>
        </xsl:when>
        <xsl:otherwise>
          <xsl:text>12pt</xsl:text>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:attribute>
    <xsl:attribute name="start-indent">
      <xsl:variable name="ancestors">
        <xsl:choose>
          <xsl:when test="count(ancestor::ol) or count(ancestor::ul)">
            <xsl:value-of select="1 + 
                                  (count(ancestor::ol) + 
                                   count(ancestor::ul)) * 
                                  1.25"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:text>1</xsl:text>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>
      <xsl:value-of select="concat($ancestors, 'cm')"/>
    </xsl:attribute>
    <xsl:apply-templates select="*"/>
  </fo:list-block>
</xsl:template>

<xsl:template match="ul/li">
  <fo:list-item>
    <fo:list-item-label end-indent="label-end()">
      <fo:block>•</fo:block>
    </fo:list-item-label>
    <fo:list-item-body start-indent="body-start()">
      <fo:block>
        <xsl:apply-templates select="*|text()"/>
      </fo:block>
    </fo:list-item-body>
  </fo:list-item>
</xsl:template>

但是,我不知道如何将它们全部应用到 productDescription 文本,因为 html 定义的这些模板必须驻留在主模板之外?

原样 How do I display output variable text in XSL,替换为:

<xsl:value-of select="productDescription" />

与:

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

由于 FOP 使用 Xalan,并且如 XSLT 1.0 规范中所述(参见 https://www.w3.org/TR/1999/REC-xslt-19991116#section-Applying-Template-Rules and https://www.w3.org/TR/1999/REC-xslt-19991116#built-in-rule):

  1. 当内置 Xalan 到达 <xsl:apply-templates select="productDescription" /> 时,它将尝试为 productDescription.
  2. 寻找模板规则
  3. productDescription没有模板规则的情况下,会回退到元素的内置模板规则,处理productDescription元素的子节点。
  4. 当 Xalan 处理 pproductDescription 的子元素时,它会优先使用样式表中的模板,而不是回退到内置规则(因为规则关于模板优先级的设置就是这样。
  5. 文本节点的内置模板规则会将文本节点复制到结果树。