Recipe fun
So here is my great-grandmother's recipe for those tasty little italian dumplings which have the power to cause joy beyond literary translation.
It's also cause for me to attempt to create a microformat and xml structure for recipes - both of which are bare-boned and probably lacked most of what a true recipe represents, but I will never claim to propose what I feel should be a standard - only something that works for me and allows me to learn something at this moment in time. So bear this in mind before you run away whining to the makers of this page.
Nevertheless, any suggestions would be appreciated.
The recipe
An explanation
Using PHP 5's XSL methods, I'm simply transforming my recipe XML document using XSL to output HTML (which contains the microformat). I could have used PHP 5's simpleXML instead of doing an XSL transformation - it would have been quicker - but I wanted to create something that does not require a specific scripting language. Any XML aggregator tool would work using the stylesheet provided.
I apologise for the lack of detail but man, I'm fungry! The code should speak for itself really.
The XML
<?xml version="1.0" encoding="iso-8859-1"?>
<recipes>
<recipe>
<title>Gnocchi</title>
<author>Bis Nonna</author>
<source></source>
<description><![CDATA[This is my great-grandmother's recipe for gnocchi. Gnocchi is an Italian winter favourite and while there is a little preparation time, it is a cheap meal that will impress your guests. Serve with your favourite sauce and parmeasan cheese. Any left over gnocchi dough can be frozen and cooked later. for extra zing add half a cup of grated parmeasan cheese to the dough mix. Buonissimi!]]></description>
<photo>gnocchi.jpg</photo>
<cuisine>Italian</cuisine>
<category>Main</category>
<yield unit="4">people</yield>
<difficulty>medium</difficulty>
<preptime unit="minutes">45 to 60</preptime>
<item name="gnocchi">
<ingredients>
<ingredient unit="kilogram" quantity="1" usage="required"><![CDATA[old potatoes (Desiré potatoes work well)]]></ingredient>
<ingredient unit="cups" quantity="3" usage="required"><![CDATA[plain flour]]></ingredient>
<ingredient unit="teaspoon" quantity="1/2" usage="optional"><![CDATA[salt]]></ingredient>
<ingredient unit="cup" quantity="1/2" usage="optional"><![CDATA[parmeasan cheese]]></ingredient>
</ingredients>
</item>
<method>
<step><![CDATA[Peel, chop and boil potatoes]]></step>
<step><![CDATA[When they are soft, drain the potatoes well and return to the pot to evaporate any excess liquid. It's important that you remove as much water as possible. This helps to give the gnocchi a lighter texture.]]></step>
<step><![CDATA[Mash the potato to a fine pureé and remove and hard pieces if possible.]]></step>
<step><![CDATA[When the potato is comfortable to handle, flour a flat surface and place the mashed potato on top. Add 500 grams of flour, optional cheese, and the salt and and knead to a smooth dough.]]></step>
<step><![CDATA[Separate the dough into portions with floured hands roll the portions into long, even cylinders about one and a half times the thickness of your index finger or about two and a half centimetres, ensuring that the dough doesn't stick to the surface.]]></step>
<step><![CDATA[Using a knife cut the cylinders into small pieces, no more than 3 centimetres long. To add texture and shape you can roll the gnocchi lightly off the back of a fork or cheese grater.]]></step>
<step><![CDATA[Bring some water to the boil and add enough gnocchi to cover one layer of the pot. When the gnocchi rise to the surface, wait about half a minute and remove from the pot. Repeat with remaining gnocchi. Uncooked gnocchi can be frozen and cooked later.]]></step>
<step><![CDATA[Dish out gnocchi and add your favourite cheese or sauce. Buen appetito!]]></step>
</method>
</recipe>
</recipes>
The XSL
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="ISO-8859-1" indent="yes"/>
<xsl:template match="/">
<xsl:for-each select="recipes/recipe">
<div class="hRecipe">
<h3 class="hRecipe-title"><xsl:value-of disable-output-escaping="yes" select="title"/></h3>
<img class="hRecipe-photo" alt="{title}" src="{photo}" />
<p class="cuisine"><xsl:value-of disable-output-escaping="yes" select="cuisine"/></p>
<p class="hRecipe-author">Author: <xsl:value-of disable-output-escaping="yes" select="author"/></p>
<p class="hRecipe-preptime">Preparation time: <xsl:value-of disable-output-escaping="yes" select="preptime"/> <xsl:text> </xsl:text> <xsl:value-of select="preptime/@unit"/> </p>
<p class="hRecipe-yield">Serves <xsl:value-of select="yield/@unit"/> <xsl:text> </xsl:text> <xsl:value-of disable-output-escaping="yes" select="yield"/> </p>
<p class="hRecipe-summary"><xsl:value-of disable-output-escaping="yes" select="description"/></p>
<h4>Ingredients</h4>
<ul class="hRecipe-ingredients">
<xsl:apply-templates select="item"/>
</ul>
<h4>Preparation</h4>
<ol class="hRecipe-method">
<xsl:apply-templates select="method"/>
</ol>
</div>
</xsl:for-each>
</xsl:template>
<xsl:template match="item">
<li> <h4><xsl:value-of select="@name"/></h4>
<ul>
<xsl:for-each select="ingredients/ingredient">
<li class="ingredient <xsl:value-of select="@usage"/>"><span class="ingredient-quantity"><xsl:value-of select="@quantity"/></span><xsl:text> </xsl:text><span class="ingredient-unit"><xsl:value-of select="@unit"/></span> of <span class="ingredient-name"><xsl:value-of disable-output-escaping="yes" select="."/></span></li>
</xsl:for-each>
</ul>
</li>
</xsl:template>
<xsl:template match="method">
<xsl:for-each select="step">
<li class="step"><xsl:value-of disable-output-escaping="yes" select="."/></li>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
The PHP
<?php
$xsl_filename = "recipe.xsl";
$xml_filename = "recipe.xml";
// Load the XML source
$xml = new DOMDocument;
$xml->load($xml_filename);
$xsl = new DOMDocument;
$xsl->load($xsl_filename);
// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // attach the xsl rules
$newXml = $proc->transformToXML($xml);
echo $newXml;
?>
Ideas for the future?
- Allow the creation of recipe XML by users
- Create a widget for Google or Netvibes with a recipes feed, or maybe not
- Allow users to create a custom recipe "book" or feed by bringing together several recipes. The backend will aggregate the XML, style it into a mini site, allow the user to customise the look and feel and then download it, ready for printing.