使用 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 中的 XSL-FO 超链接 - 打印关闭查看打开 - 天线之家
XSL FO 表中的粗边框线问题 - 使用 Apache FOP 创建 PDF