简体   繁体   中英

creating xsl-fo with correct format

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

  • Generate fo:table from match="export" template.
  • Genrate each fo:table-row from match="year" template.
  • Use round() function to get each precision of values. (format-number() will be easier)
  • Use 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM