使用 XSL-FO 在下一个兄弟为空时隐藏块

Posted

技术标签:

【中文标题】使用 XSL-FO 在下一个兄弟为空时隐藏块【英文标题】:Hiding block when the next sibiling is empty with XSL-FO 【发布时间】:2021-11-05 21:59:27 【问题描述】:

我正在使用 Apache FOP 生成报告,我的模板是这样的:

<xsl:template match="LOGO">
    <xsl:param name="imgLogo">
        <xsl:value-of select="IMG" />
    </xsl:param>
    <fo:external-graphic content-
         src="$imgLogo" />
</xsl:template>

<xsl:template match="MYREPORT">
    <fo:block>
        <xsl:apply-templates select="LOGO" />
    </fo:block>
    <fo:block>
        <xsl:value-of select="PAG_1" />
    </fo:block>
    <fo:block page-break-before="always">
        <xsl:apply-templates select="LOGO" />
    </fo:block>
    <fo:block>
        <xsl:value-of select="PAG_2" />
    </fo:block>
    <fo:block page-break-before="always">
        <xsl:apply-templates select="LOGO" />
    </fo:block>
    <fo:block>
        <xsl:value-of select="PAG_3" />
    </fo:block>
</xsl:template>

如果下一个兄弟块 (PAGE) 为空,我必须隐藏“LOGO”块(在每个 PAGE 之前)。

例如,使用以下输入:

<MYREPORT>
  <LOGO>
    <IMG>data:image/png;base64,[cutted]</IMG>
  </LOGO>
  <PAG_1>Page 1</PAG_1>
  <PAG_2>Page 2</PAG_2>
</MYREPORT>

应该打印出来:

LOGO
Page 1
(new page)
LOGO
Page 2

它正在打印以下内容:

LOGO
Page 1
(new page)
LOGO
Page 2
(new page)
LOGO

有什么想法吗?谢谢

【问题讨论】:

仅供参考。本题纯属XSL,与XSL FO无关。 仅供参考。本题纯属XSL,与XSL FO无关。 【参考方案1】:

最直接的方法是在PAG_3的代码周围加上xsl:if

<xsl:template match="MYREPORT">
    <fo:block>
        <xsl:apply-templates select="LOGO" />
    </fo:block>
    <fo:block>
        <xsl:value-of select="PAG_1" />
    </fo:block>
    <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 test="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:apply-templates 选择 PAG_* 元素,以便仅为存在的元素生成结果:

<xsl:template match="MYREPORT">
  <xsl:apply-templates select="PAG_1 | PAG_2 | PAG_3" />
</xsl:template>

<xsl:template match="PAG_1 | PAG_2 | PAG_3">
  <fo:block>
    <xsl:if test="position() != 1">
      <xsl:attribute name="page-break-before">always</xsl:attribute>
    </xsl:if>
    <xsl:apply-templates select="../LOGO" />
  </fo:block>
  <fo:block>
    <xsl:apply-templates />
  </fo:block>
</xsl:template>

【讨论】:

这对我来说是一种魔法,但这正是我想要的……谢谢! 使用xsl:apply-templates可以更容易地使用源文档的结构来确定结果。它通常比尝试预测每个可能的源文档的结构(如您所发现的)更简单。任何对 XSLT 的良好介绍都会向您展示如何使用 xsl:apply-templates 和多个模板规则,而不是试图在一个模板中完成所有事情。 (我还将第二个示例中的xsl:value-of 更改为xsl:apply-templates:如果PAG_1 等都有任何内联元素,xsl:value-of 只会为您提供它们的字符串值。)

以上是关于使用 XSL-FO 在下一个兄弟为空时隐藏块的主要内容,如果未能解决你的问题,请参考以下文章

隐藏为空时隐藏

angularjs中模型为空时如何隐藏下拉列表?

如何在值为空时更新,否则在下一行更新

当其中一个为空时隐藏 ACF 字段

文本字段为空时隐藏自动完成表格视图

新闻为空时隐藏标题