XSLT Conversion from XML to Formatting Objects
If you want to try this file, which is part of the conversion
from XML to PDF, copy and paste the code into a file
called nutrition_fo.xslt in the nutrition
directory. (See Linux
and Windows setup instructions.)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" indent="yes"https://alistapart.com/>
<xsl:key name="category" match="nutrition/daily-values/*"
use="local-name()"https://alistapart.com/>
<xsl:template match="nutrition">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="cover"
page-height="10cm"
page-width="8cm"
margin-top="0.25cm"
margin-bottom="0.25cm"
margin-left="0.5cm"
margin-right="0.25cm">
<fo:region-body
margin-top="0.3cm" />
</fo:simple-page-master>
<fo:simple-page-master master-name="leftPage"
page-height="10cm"
page-width="8cm"
margin-left="0.25cm"
margin-right="0.5cm"
margin-top="0.25cm"
margin-bottom="0.25cm">
<fo:region-after extent="0.5cm"https://alistapart.com/>
<fo:region-body
margin-top="0.25cm"
margin-bottom="0.25cm" />
</fo:simple-page-master>
<fo:simple-page-master master-name="rightPage"
page-height="10cm"
page-width="8cm"
margin-left="0.5cm"
margin-right="0.25cm"
margin-top="0.25cm"
margin-bottom="0.25cm">
<fo:region-after extent="0.5cm"https://alistapart.com/>
<fo:region-body
margin-top="0.25cm"
margin-bottom="0.25cm" />
</fo:simple-page-master>
<xsl:comment>Set up the sequence of pages</xsl:comment>
<fo:page-sequence-master master-name="contents">
<fo:repeatable-page-master-alternatives>
<fo:conditional-page-master-reference
master-reference="leftPage"
odd-or-even="even"https://alistapart.com/>
<fo:conditional-page-master-reference
master-reference="rightPage"
odd-or-even="odd"https://alistapart.com/>
</fo:repeatable-page-master-alternatives>
</fo:page-sequence-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="cover">
<fo:flow flow-name="xsl-region-body">
<fo:block font-family="Helvetica" font-size="18pt"
text-align="end" space-before="2cm">
Nutrition Facts
</fo:block>
<fo:block font-family="Helvetica" font-size="12pt"
text-align="end">
for Selected Foods
</fo:block>
<xsl:comment>Inside front cover is blank</xsl:comment>
<fo:block break-before="page"> </fo:block>
</fo:flow>
</fo:page-sequence>
<fo:page-sequence master-reference="contents"
initial-page-number="1">
<fo:static-content flow-name="xsl-region-after">
<fo:block font-family="Helvetica" font-size="9pt"
text-align="center">
- <fo:page-number /> -
</fo:block>
</fo:static-content>
<fo:flow flow-name="xsl-region-body">
<fo:block font-family="Helvetica" font-size="9pt">
<xsl:apply-templates select="food"https://alistapart.com/>
</fo:block>
<fo:block break-before="page"
font-size="12pt" text-align="center">Notes</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="food">
<fo:block font-size="12pt" font-weight="bold">
<xsl:value-of select="mfr"https://alistapart.com/><xsl:text> </xsl:text>
<xsl:value-of select="name"https://alistapart.com/>
</fo:block>
<fo:block>
Serving size: <xsl:value-of select="serving"https://alistapart.com/>
<xsl:text> </xsl:text>
<xsl:value-of select="serving/@units"https://alistapart.com/>
</fo:block>
<xsl:call-template name="thick-line"https://alistapart.com/>
<fo:block font-weight="bold">Amount/Serving</fo:block>
<fo:block>
Calories: <xsl:value-of select="calories/@total"https://alistapart.com/>
·
Fat Calories: <xsl:value-of select="calories/@fat"https://alistapart.com/>
</fo:block>
<xsl:call-template name="thick-line"https://alistapart.com/>
<fo:table table-layout="fixed"
inline-progression-dimension.maximum="100%">
<fo:table-column width="5cm"https://alistapart.com/>
<fo:table-column width="1cm"https://alistapart.com/>
<fo:table-body>
<fo:table-row>
<fo:table-cell padding-top="1pt" padding-bottom="1pt"
border-bottom-style="solid"
border-bottom-width="1px">
<fo:block> </fo:block>
</fo:table-cell>
<fo:table-cell padding-top="1pt" padding-bottom="1pt"
border-bottom-style="solid"
border-bottom-width="1px">
<fo:block text-align="end">% Daily Value</fo:block>
</fo:table-cell>
</fo:table-row>
<xsl:call-template name="info-row">
<xsl:with-param name="msg">Total Fat</xsl:with-param>
<xsl:with-param name="node" select="total-fat"https://alistapart.com/>
</xsl:call-template>
<xsl:call-template name="info-row">
<xsl:with-param
name="msg"> Saturated Fat</xsl:with-param>
<xsl:with-param name="node" select="saturated-fat"https://alistapart.com/>
</xsl:call-template>
<xsl:call-template name="info-row">
<xsl:with-param name="msg">Cholesterol</xsl:with-param>
<xsl:with-param name="node" select="cholesterol"https://alistapart.com/>
</xsl:call-template>
<xsl:call-template name="info-row">
<xsl:with-param name="msg">Sodium</xsl:with-param>
<xsl:with-param name="node" select="sodium"https://alistapart.com/>
</xsl:call-template>
<xsl:call-template name="info-row">
<xsl:with-param
name="msg">Total Carbohydrates</xsl:with-param>
<xsl:with-param name="node" select="carb"https://alistapart.com/>
</xsl:call-template>
<xsl:call-template name="info-row">
<xsl:with-param
name="msg">Dietary Fiber</xsl:with-param>
<xsl:with-param name="node" select="fiber"https://alistapart.com/>
</xsl:call-template>
<xsl:call-template name="info-row">
<xsl:with-param name="msg">Protein</xsl:with-param>
<xsl:with-param name="node" select="protein"https://alistapart.com/>
</xsl:call-template>
</fo:table-body>
</fo:table>
<fo:block space-before="6pt" text-align="center">
Vitamin A <xsl:value-of select="vitamins/a"https://alistapart.com/>%
<xsl:text disable-output-escaping="yes">·</xsl:text>
Vitamin C <xsl:value-of select="vitamins/c"https://alistapart.com/>%
</fo:block>
<fo:block text-align="center">
<xsl:if test="position()!=last()">
<xsl:attribute name="break-after">page</xsl:attribute>
</xsl:if>
Calcium <xsl:value-of select="minerals/ca"https://alistapart.com/>%
<xsl:text disable-output-escaping="yes">·</xsl:text>
Iron <xsl:value-of select="minerals/fe"https://alistapart.com/>%
</fo:block>
</xsl:template>
<xsl:template name="thick-line">
<fo:block space-before="0px">
<fo:leader leader-pattern="rule"
leader-length="100%"
rule-style="solid"
rule-thickness="0.1cm"https://alistapart.com/>
</fo:block>
</xsl:template>
<xsl:template name="info-row">
<xsl:param name="msg"https://alistapart.com/>
<xsl:param name="node"https://alistapart.com/>
<fo:table-row>
<fo:table-cell>
<fo:block padding-top="1pt" padding-bottom="1pt"
border-bottom-style="solid"
border-bottom-width="1px">
<xsl:value-of select="$msg"https://alistapart.com/>
<xsl:text> </xsl:text>
<xsl:value-of select="$node"https://alistapart.com/>
<xsl:value-of select="key('category',name($node))/@units"https://alistapart.com/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block text-align="end"
padding-top="1pt" padding-bottom="1pt"
border-bottom-style="solid"
border-bottom-width="1px">
<xsl:value-of select="round(100 * $node div
key('category',name($node)))"https://alistapart.com/>
<xsl:text>%</xsl:text>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:template>
</xsl:stylesheet>
