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>