使用 XSL 合并 PDF 中的常用行

Posted

技术标签:

【中文标题】使用 XSL 合并 PDF 中的常用行【英文标题】:Merge common rows in PDF using XSL 【发布时间】:2021-02-25 09:13:29 【问题描述】:

我是 XSL 的新手。我有一个 XML 文件,我正在使用 XSL 从中生成 pdf。我可以使用 Fo、FO 块以 PDF 格式显示下表,

这会完美地生成包含不同行中所有数据的表格。

但是,我需要通过合并显示下面的格式

以下是我尝试过的 xml 和 XSL 代码:

XML

"<DocumentElement>
  <Student>
    <Roll>1</Roll>
    <NAME>Mark</NAME>
    <Subject>1000502</Subject>
    <DESCRIPTION>Test_2046_1</DESCRIPTION>
    <Total>20</Total>
  </Student>
  <Student>
    <Roll>1</Roll>
    <NAME>Mark</NAME>
    <Subject>1117697</Subject>
    <DESCRIPTION>Test_2046_2</DESCRIPTION>
    <Total>20</Total>
  </Student>
  <Student>
    <Roll>2</Roll>
    <NAME>Henry</NAME>
    <Subject>1271267</Subject>
    <DESCRIPTION>Test_2046_3</DESCRIPTION>
    <Total>20</Total>
  </Student>
  <Student>
    <Roll>2</Roll>
    <NAME>Henry</NAME>
    <Subject>5013025</Subject>
    <Total>20</Total>
  </Student>
</DocumentElement>"

XSL

"<xsl:template match="DocumentElement">
    <fo:block break-before="page">
      <fo:table xsl:use-attribute-sets="data_table">
        <xsl:call-template name="StudentItemsHeading"/>
        <fo:table-body>
          <xsl:apply-templates select="Student"/>
        </fo:table-body>
      </fo:table>
    </fo:block>
  </xsl:template>
  <xsl:template name="StudentItemsHeading">
    <fo:table-header>
      <fo:table-row xsl:use-attribute-sets="table_headers">
        <fo:table-cell xsl:use-attribute-sets="bordered">
          <fo:block>Student ID#</fo:block>
        </fo:table-cell>
        <fo:table-cell xsl:use-attribute-sets="bordered">
          <fo:block>Student Name</fo:block>
        </fo:table-cell>
        <fo:table-cell xsl:use-attribute-sets="bordered">
          <fo:block>Subjects</fo:block>
        </fo:table-cell>
        <fo:table-cell xsl:use-attribute-sets="bordered">
          <fo:block>Subject Description</fo:block>
        </fo:table-cell>
        <fo:table-cell xsl:use-attribute-sets="bordered">
          <fo:block>Total Marks</fo:block>
        </fo:table-cell>
        <fo:table-cell xsl:use-attribute-sets="bordered">
          <fo:block>Min.</fo:block>
        </fo:table-cell>
        <fo:table-cell xsl:use-attribute-sets="bordered">
          <fo:block>Max.</fo:block>
        </fo:table-cell>
      </fo:table-row>
    </fo:table-header>
  </xsl:template>
  <xsl:template match="Student">
    <fo:table-row>
      <fo:table-cell xsl:use-attribute-sets="bordered">
        <fo:block white-space-collapse="false" xsl:use-attribute-sets="bold">
          <xsl:value-of select="Roll"/>
        </fo:block>
      </fo:table-cell>
      <fo:table-cell xsl:use-attribute-sets="bordered">
        <fo:block>
          <xsl:value-of select="NAME"/>
        </fo:block>
      </fo:table-cell>
      <fo:table-cell xsl:use-attribute-sets="bordered">
        <fo:block white-space-collapse="false" xsl:use-attribute-sets="bold">
          <xsl:value-of select="Subject"/>
        </fo:block>
      </fo:table-cell>
      <fo:table-cell xsl:use-attribute-sets="bordered">
        <fo:block white-space-collapse="false" xsl:use-attribute-sets="bold">
          <xsl:value-of select="DESCRIPTION"/>
        </fo:block>
      </fo:table-cell>
      <fo:table-cell xsl:use-attribute-sets="number_format bordered">
        <fo:block>
          <xsl:value-of select="Total"/>
        </fo:block>
      </fo:table-cell>
      <fo:table-cell xsl:use-attribute-sets="number_format bordered">
        <fo:block>
        </fo:block>
      </fo:table-cell>
      <fo:table-cell xsl:use-attribute-sets="number_format bordered">
        <fo:block>
        </fo:block>
      </fo:table-cell>
    </fo:table-row>
  </xsl:template>

请帮助了解如何实现这一目标。

【问题讨论】:

【参考方案1】:

代替

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

使用

<xsl:for-each-group select="Student" group-by="Roll">
  <xsl:apply-templates select="current-group()"/>
</xsl:for-each-group>

然后在Student 的模板中使用例如

  <xsl:template match="Student">
    <fo:table-row>
      <xsl:if test="position() = 1">
       <fo:table-cell xsl:use-attribute-sets="bordered" number-rows-spanned="count(current-group())">
        <fo:block white-space-collapse="false" xsl:use-attribute-sets="bold">
          <xsl:value-of select="Roll"/>
        </fo:block>
       </fo:table-cell>
       <fo:table-cell xsl:use-attribute-sets="bordered" number-rows-spanned="count(current-group())">
        <fo:block>
          <xsl:value-of select="NAME"/>
        </fo:block>
       </fo:table-cell>
      </xsl:if>
      <fo:table-cell xsl:use-attribute-sets="bordered">
        <fo:block white-space-collapse="false" xsl:use-attribute-sets="bold">
          <xsl:value-of select="Subject"/>
        </fo:block>
      </fo:table-cell>
      <fo:table-cell xsl:use-attribute-sets="bordered">
        <fo:block white-space-collapse="false" xsl:use-attribute-sets="bold">
          <xsl:value-of select="DESCRIPTION"/>
        </fo:block>
      </fo:table-cell>
      <xsl:if test="position() = 1">
       <fo:table-cell xsl:use-attribute-sets="number_format bordered" number-rows-spanned="count(current-group())">
        <fo:block>
          <xsl:value-of select="Total"/>
        </fo:block>
       </fo:table-cell>
      </xsl:if>
      <fo:table-cell xsl:use-attribute-sets="number_format bordered">
        <fo:block>
        </fo:block>
      </fo:table-cell>
      <fo:table-cell xsl:use-attribute-sets="number_format bordered">
        <fo:block>
        </fo:block>
      </fo:table-cell>
    </fo:table-row>
  </xsl:template>

假设使用 XSLT 2 或 3,例如撒克逊 9 或 10。

【讨论】:

我尝试了上述解决方案,但出现错误:'xsl:for-each-group' 不能是 'fo:table-body' 元素的子元素。 @Avinash,XSLT 使用 Saxon 9 还是 10?哪个工具给出了这个错误,它可能只是基于模式的验证器不准备处理 XSLT 2 或 3 的警告或过分热心的错误?

以上是关于使用 XSL 合并 PDF 中的常用行的主要内容,如果未能解决你的问题,请参考以下文章

如何使用PDF编辑器将多个PDF合并成一个?

PDF 中的 XSL-FO 超链接 - 打印关闭查看打开 - 天线之家

XSL FO 表中的粗边框线问题 - 使用 Apache FOP 创建 PDF

XSL 转换后在 PDF 中保留空白

如何为 xsl-fo 中的每个页面添加页眉和页脚以生成 pdf

有没有办法使用xsl模板合并列表中的多值索引?