I need to create an xsl-fo document from an xml document which displays information of the the export ammount (profits) for each year and, within each year, for every region.
in order to produce a table which contains, for each year, the earnings for that year and how it compares to the previous year, in a three column table displaying such information.
this problem seems to have the whole class stumped and the teacher isn't currently available for consultation. Any help would be greatly appreciated. Thanks in advance.
I have prepared the following XSLT, I hope this helps you.
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="/">
<html>
<body>
<table style="width:100%" border="1" >
<tr bgcolor="#9acd32">
<th>Year</th>
<th>Total</th>
<th>Delta</th>
</tr>
<xsl:for-each select="exports/year">
<tr>
<td><xsl:value-of select="./text()"/></td>
<td><xsl:value-of select='format-number(./total, "#.0")'/></td>
<xsl:choose>
<xsl:when test="position()=1">
<td><xsl:text>-</xsl:text></td>
</xsl:when>
<xsl:otherwise>
<td><xsl:value-of select='format-number((xs:decimal(./total)- xs:decimal(preceding-sibling::*[ 1]/total)) div xs:decimal(preceding-sibling::*[ 1]/total),"#.00%")'/></td>
</xsl:otherwise>
</xsl:choose>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
the main parts of it are:
for-each select="exports/year"
that will loop on each year of your input data and generate one line in the output table ./text()
to get the year 'format-number(./total, "#.0")'
to get the one decimal precision of your total then the last part, a choose when/otherwise
to check if your element is the first of not using position()=1
if it is the case output "-" else do the following computation :
'format-number((xs:decimal(./total)- xs:decimal(preceding-sibling::*[ 1]/total)) div xs:decimal(preceding-sibling::*[ 1]/total),"#.00%")'
where div
is the divisor operator and preceding-sibling
allows you to get the previous sibling node in your DOM tree, before formatting the result in percentage with 2 decimals
Another example that generates XSL-FO using round() function.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="/">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions" xml:lang="en-US"
id="id_document">
<fo:layout-master-set>
<fo:simple-page-master master-name="spm" page-width="6in" page-height="5in">
<fo:region-body margin-top="0.5in" margin-bottom="0.5in" margin-left="0.5in"
margin-right="0.5in" overflow="error-if-overflow"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="spm" reference-orientation="from-page-master-region()"
writing-mode="from-page-master-region()">
<fo:flow flow-name="xsl-region-body" font-family="Arial" font-size="11pt">
<xsl:apply-templates/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="exports">
<fo:table>
<fo:table-column column-number="1" column-width="5em"/>
<fo:table-column column-number="2" column-width="7em"/>
<fo:table-column column-number="3" column-width="5em"/>
<fo:table-body>
<xsl:apply-templates/>
</fo:table-body>
</fo:table>
</xsl:template>
<xsl:template match="year">
<xsl:variable name="currTotal" as="xs:decimal" select="xs:decimal(total)"/>
<fo:table-row>
<fo:table-cell>
<fo:block>
<xsl:value-of select="./text()"/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<xsl:value-of select="concat('$',round($currTotal * 10) div 10)"/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<xsl:choose>
<xsl:when test="empty(preceding-sibling::*)">
<xsl:text>-</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="prevTotal" as="xs:decimal" select="xs:decimal(preceding-sibling::*[1]/total)"/>
<xsl:variable name="totalDiff" as="xs:decimal" select="$currTotal - $prevTotal"/>
<xsl:variable name="percentage" as="xs:decimal" select="round($totalDiff div $prevTotal * 10000) div 100"/>
<xsl:value-of select="concat($percentage,'%')"/>
</xsl:otherwise>
</xsl:choose>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:template>
</xsl:stylesheet>
The main feature are
match="export"
template. match="year"
template. round()
function to get each precision of values. (format-number() will be easier) empty(preceding-sibling::*)
to judge the first year
element in exports
. The sample result:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.