You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用XSL-FO与Apache FOP生成报表时,如何在后续页面块为空时隐藏前置LOGO块

解决Apache FOP中根据页面内容是否存在隐藏LOGO块的问题

这个问题我之前也碰到过,核心就是要让LOGO的渲染逻辑和对应页面内容的存在性绑定起来,而不是像现在这样无条件硬编码每个LOGO块和分页。我给你两种解决思路,你可以根据实际情况选择:

思路一:针对固定页数的精准处理

如果你的报表页数是固定的(比如最多3页),可以直接给每个页面组加上条件判断,只有当对应页面内容存在且非空时,才渲染LOGO和页面内容:

<xsl:template match="LOGO">
  <xsl:param name="imgLogo">
    <xsl:value-of select="IMG" />
  </xsl:param>
  <fo:external-graphic content-height="scale-to-fit" height="50pt" src="{$imgLogo}" />
</xsl:template>

<xsl:template match="MYREPORT">
  <!-- 处理第一页:无前置分页 -->
  <xsl:if test="PAG_1 and normalize-space(PAG_1) != ''">
    <fo:block>
      <xsl:apply-templates select="LOGO" />
    </fo:block>
    <fo:block>
      <xsl:value-of select="PAG_1" />
    </fo:block>
  </xsl:if>

  <!-- 处理第二页:前置分页 -->
  <xsl:if test="PAG_2 and normalize-space(PAG_2) != ''">
    <fo:block page-break-before="always">
      <xsl:apply-templates select="LOGO" />
    </fo:block>
    <fo:block>
      <xsl:value-of select="PAG_2" />
    </fo:block>
  </xsl:if>

  <!-- 处理第三页:前置分页 -->
  <xsl:if test="PAG_3 and normalize-space(PAG_3) != ''">
    <fo:block page-break-before="always">
      <xsl:apply-templates select="LOGO" />
    </fo:block>
    <fo:block>
      <xsl:value-of select="PAG_3" />
    </fo:block>
  </xsl:if>
</xsl:template>

关键说明:

  • 用<xsl:if>判断两个条件:PAG_x元素是否存在,以及经过normalize-space()处理后内容是否非空(避免只有空格的无效内容)
  • 第一页不需要前置分页,后续页面才添加page-break-before="always"
  • 只有满足条件时,才会渲染对应的LOGO和页面内容块,彻底避免空页面的LOGO

思路二:通用的动态处理(支持任意页数)

如果未来报表页数可能变化,或者页面元素是动态生成的(比如PAG_1、PAG_2...PAG_N),可以用更灵活的遍历方式:

<xsl:template match="LOGO">
  <xsl:param name="imgLogo">
    <xsl:value-of select="IMG" />
  </xsl:param>
  <fo:external-graphic content-height="scale-to-fit" height="50pt" src="{$imgLogo}" />
</xsl:template>

<xsl:template match="MYREPORT">
  <!-- 筛选出所有有效页面:以PAG_开头且内容非空的元素 -->
  <xsl:variable name="validPages" select="*[starts-with(local-name(), 'PAG_') and normalize-space(.) != '']" />
  
  <!-- 按页面编号排序(确保PAG_1、PAG_2、PAG_3的顺序) -->
  <xsl:for-each select="$validPages">
    <xsl:sort select="substring-after(local-name(), 'PAG_')" data-type="number" order="ascending" />
    
    <!-- 除了第一个页面,添加前置分页 -->
    <xsl:if test="position() > 1">
      <fo:block page-break-before="always" />
    </xsl:if>
    
    <!-- 渲染LOGO -->
    <fo:block>
      <xsl:apply-templates select="../LOGO" />
    </fo:block>
    
    <!-- 渲染页面内容 -->
    <fo:block>
      <xsl:value-of select="." />
    </fo:block>
  </xsl:for-each>
</xsl:template>

关键说明:

  • 先通过starts-with(local-name(), 'PAG_')筛选所有页面元素,再用normalize-space(.) != ''过滤空内容
  • 用<xsl:sort>按页面编号的数字顺序排序,避免因XML元素顺序混乱导致页面顺序错误
  • 遍历过程中,只有第一个页面不加分页,后续页面自动添加分页逻辑
  • 不管有多少个有效页面,都会自动匹配渲染,完全忽略空的或不存在的页面

这样修改后,当你输入只有PAG_1和PAG_2的XML时,就只会渲染对应的两组LOGO+内容,不会出现第三页的空LOGO了。

内容的提问来源于stack exchange,提问作者Alessandro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 11:42:34