Reputation: 35
I am New to XSL. I have an XML file and I am using XSL to Generate pdf from it. I am able to display the below table in PDF using Fo, FO block,
This generates the table perfectly with all data in different rows.
However, I need to display the Below format with merging
Below is the xml and The XSL code I have Tried:
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>
Please Help on how to Achieve this.
Upvotes: 1
Views: 149
Reputation: 167716
Instead of
<xsl:apply-templates select="Student"/>
use
<xsl:for-each-group select="Student" group-by="Roll">
<xsl:apply-templates select="current-group()"/>
</xsl:for-each-group>
then in the template for Student
use e.g.
<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>
That assumes using XSLT 2 or 3 with e.g. Saxon 9 or 10.
Upvotes: 2