Hello,
I've a need to display certain XML content in tabular form (XSL-FO for pdf reports), and not all the columns to displayed are present in source XML. So, I was wondering if there is a way to transform source XML by embedding additional columns based on certain element values, and then process the resulting XML to display content?
As an example, for source data:
<projectteam> <member> <name>John Doe</name> <role>dev</role> <hrs>100</hrs> </member> <member> <name>Paul Coder</name> <role>dev</role> <hrs>40</hrs> </member> <member> <name>Henry Tester</name> <role>qa</role> <hrs>80</hrs> </member> <member> <name>Peter Tester</name> <role>qa</role> <hrs>40</hrs> </member> </projectteam>
I'd like the data to be displayed as :
Name Role Dev QA --------------------------- John Doe dev 100 Paul Coder dev 40 Henry Tester qa 80 Peter Tester qa 40 --------------------------- Role Totals: 140 120 ---------------------------
I would like to know if I can use something like:
<xsl:element name="{role}"> <xsl:value-of select="member/hrs"/> </xsl:element>
So that I can embed elements <dev>100</dev> and so on at run time during first pass, and then use the resulting XML to display data for new columsn 'dev' and 'qa', that way, calculating totals for each role type will be much simpler (for eg. "sum(preceding-sibling::member/dev)" for dev column), and the data for each cell in 'dev' and 'qa' colums could simply be the value-of these tags respectively.
It got the desired results the hard way using following stylesheet (page formatting details omitted to keep it brief), but am not convinced that this is the apt solution.
... <fo:table-body> <!-- fills table rows --> <xsl:apply-templates select="member"/> <!-- dislpay totals for each role --> <fo:table-row height="12pt" border-bottom="1pt solid black"> <fo:table-cell number-columns-spanned="2"> <fo:block>Role Totals:</fo:block> </fo:table-cell> <fo:table-cell text-align="right"> <xsl:call-template name="RoleTotals"> <xsl:with-param name="node" select="//member[1]"/> <xsl:with-param name="roleName" select="'dev'"/> </xsl:call-template> </fo:table-cell> <fo:table-cell text-align="right"> <xsl:call-template name="RoleTotals"> <xsl:with-param name="node" select="//member[1]"/> <xsl:with-param name="roleName" select="'qa'"/> </xsl:call-template> </fo:table-cell> </fo:table-row> </fo:table-body> ... </fo:root> </xsl:template> <xsl:template match="member"> <fo:table-row border-bottom="1pt solid black"> <fo:table-cell> <fo:block> <xsl:value-of select="name"/></fo:block></fo:table-cell> <fo:table-cell> <fo:block> <xsl:value-of select="role"/></fo:block></fo:table-cell> <fo:table-cell text-align="right"> <fo:block> <xsl:if test="role = 'dev'"><xsl:value-of select="hrs"/></xsl:if> </fo:block> </fo:table-cell> <fo:table-cell text-align="right"> <fo:block> <xsl:if test="role = 'qa'"><xsl:value-of select="hrs"/></xsl:if> </fo:block> </fo:table-cell> </fo:table-row> </xsl:template> <xsl:template name="RoleTotals"> <xsl:param name="node"/> <xsl:param name="roleName"/> <xsl:param name="RT" select="0"/> <xsl:variable name="newRT"> <xsl:choose> <xsl:when test="$node/role = $roleName"> <xsl:value-of select="$RT + $node/hrs"/> </xsl:when> <xsl:otherwise><xsl:value-of select="$RT"/></xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:choose> <xsl:when test="$node/following-sibling::member"> <xsl:call-template name="RoleTotals"> <xsl:with-param name="node" select="$node/following-sibling::member[1]"/> <xsl:with-param name="roleName" select="$roleName"/> <xsl:with-param name="RT" select="$newRT"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <fo:block><xsl:value-of select="$newRT"/></fo:block> </xsl:otherwise> </xsl:choose> </xsl:template>