How to cite this paper

Flynn, Peter. “Leveraging markup to process narrative recipes.” Presented at Balisage: The Markup Conference 2024, Washington, DC, July 29 - August 2, 2024. In Proceedings of Balisage: The Markup Conference 2024. Balisage Series on Markup Technologies, vol. 29 (2024). https://doi.org/10.4242/BalisageVol29.Flynn01.

Balisage: The Markup Conference 2024
July 29 - August 2, 2024

Balisage Paper: Leveraging markup to process narrative recipes

Peter Flynn

Peter Flynn managed the Academic and Collaborative Technologies Group in IT Services at University College Cork, Ireland until his retirement in 2018. He trained at the London College of Printing and did his MA in computerized planning systems at Central London Polytechnic (now the University of Westminster). He worked in the UK for the Printing and Publishing Industry Training Board as a DP Manager and for United Information Services of Kansas as IT consultant before joining UCC as Project Manager for academic and research computing. In 1990 he installed Ireland’s first Web server and concentrated on academic and research publishing support. He has been Secretary of the TeX Users Group, Deputy Director for Ireland of EARN, and a member both of the IETF Working Group on HTML and of the W3C XML SIG; and he has published books on HTML, SGML/XML, and LaTeX. Peter also runs the markup and typesetting consultancy Silmaril, and is editor of the XML FAQ as well as an irregular contributor to conferences and journals in electronic publishing, markup, and Humanities computing, and has been a regular speaker and session chair at the XML Summer School in Oxford. He completed a PhD in 2015 on User Interfaces to Structured Documents with the Human Factors Research Group in Applied Psychology in UCC. He maintains a fairly random semi-technical blog at https://blogs.silmaril.ie/peter.

Article copyright © 2024 by Peter Flynn. Application code copyright © 2019-2024 by Silmaril Consultants

Abstract

In two earlier papers I described the implementation of ‘’ (pronounced /ˈɹɛs.ɪ.pē/ ‘reSEEpay’), an XML/XSLT system for checking and reproducing structured cookery recipes. Since then, work has been ongoing: a) to refine the categories used in the metadata; b) to improve the implementation in CSS; and c) to extend the markup to narrative recipes encoded in other schemas. This paper describes the third of these, with a working implementation in TEI P5. The categorization task is out of scope for markup conferences, and is best discussed over a good dinner (the CSS is in scope but barely addressed here).

Table of Contents

Structure and narrative
Implementation
Results and conclusions

Note: Program Notes

When is a narrative not a story? When it’s a recipe! Publishing recipes with distinct sections enumerating the ingredients and preparation steps is a 19th century invention. Historically, recipes were just narrative prose. Can we leverage markup and style to present narrative recipes in a modern style?

Note: Acknowledgements

My thanks go again to all my friends and colleagues in kitchens, laboratories, and libraries, especially on BlueSky and Discord, for their help and suggestions, with a special mention to Beatrix Färber, Editor of the CELT Project and culinary historian Regina Sexton of the Department of Adult Continuing Education, UCC

Structure and narrative

Modern recipes, in print as on the web, contain two major components: the List of Ingredients and the Method. These were discussed extensively in the earlier papers on this topic [Flynn 2020][Flynn 2021]. They exist in one form or another in every layout, design, schema, and handwritten note for modern recipes, and a recipe would be considered virtually useless without both of them.

Figure 1: Simple recipes with list of ingredients and method in the modern style

Ingredients Method Handwritten
<ul>
  <li>1lb Sugar</li>
  <li>½pt Cream</li>
  <li>¼lb Chocolate</li>
  <li>2oz Butter</li>
</ul>
		
  • 1lb Sugar

  • ½pt Cream

  • ¼lb Chocolate

  • 2oz Butter

<ol>
  <li>Mix ingredients</li>
  <li>Boil to 235°F</li>
  <li>Stir to cool</li>
  <li>Pour into dish</li>
</ol>
		
  1. Mix ingredients

  2. Boil to 235°F

  3. Stir to cool

  4. Pour into dish

Recipe for fudge used as a markup example in Formatting Information [Flynn 2024], with MS for a family recipe.

Before the expansion of the cookery book from niche publication to mass market during the second half of the 19th century, recipes were narrative [Scully 2002][Nonymous 2018]. The Roman cookery writer Apicius used a narrative form (from what we can judge), and this became the convention for later writers. The arrival of printing just made reproduction easier, so Marx Rumpolt, Hannah Glasse, and Marie-Antonin Carême all followed the tradition of writing in narrative form [Figure 2].

Figure 2: Narrative recipe with ingredients and method intertwined

Gebratene Leber (№.5) from Marx Rumpolt’s Ein new Kochbuch of 1581, p.76 [Rumpolt 1581] (L); A Turkey, &c. in Jelly from Hannah Glasse’s The Art Of Cookery of 1753, p.258 [Glasse 1753] (C); and Galantine of Turkey in Aspic, from Carême’s Le cuisinier parisien of 1828, p.145 [Carême 1828] (L).

The early cookery authors like Rumpolt were writing for professional cooks with large kitchens and kitchen staff in wealthy houses: the cooks were assumed to be able to read, or have access to someone who could, and who knew enough to be able to decide on materials and quantities from experience. Like the modern Répertoire de la Cuisine for French cooking [Gringoire 1914], recipes were terse because that was all that was needed.

Hannah Glasse was an exception: she explicitly addressed the non-professional cook, and it is worth quoting her intent:

If I have not wrote in the high polite ſtyle, I hope ſhall be forgiven; for my intention is to inſtruct the lower ſort and therefore muſt treat them in their own way. For example: when I bid them lard a fowl, if I ſhould bid them lard with large lardoons, they would not know what I meant; but when I ſay they muſt lard with little pieces of bacon, they know what I mean. So, in many other things in Cookery, the great cooks have ſuch a high way of expreſſing themſelves, that the poor girls are at a loſs to know what they mean:[…][Glasse 1753]

This all changed rapidly after the middle of the 19th century: Eliza Acton (1845) is usually credited with inventing the separation of Ingredients from Method, and her lead was followed by others including Isabella Beeton (1861) in England and Fanny Farmer (1896) in the USA; although Mrs Beeton notoriously gave ingredients but no quantities.

The ℞ software was written with the modern structured recipe in mind, but an encounter with a German colleague with a copy of Rumpolt’s recipes from the 16th century resulted in a decision to try the same techniques with narrative recipes.

Implementation

The recipe marked No.5 in [Figure 2] from the book by Rumpolt [Rumpolt 1581] was chosen because it seemed to have the qualities needed to test the system: a narrative for a simple dish, containing at least one mention of all the ingredients, in order, with details of what to do with each. No quantities are given apart from the bread, but they can be deduced.

The original was scanned and a transcription composed (OCR was attempted with tesseract but was not successful). After proofing, the XML encoding was applied in TEI P5 according to the tei_all.dtd to avoid the need for generating a custom schema at this stage [Figure 3] ([section “Results and conclusions”]).

Figure 3: Recipe encoded in TEI (before ℞ markup)

<!DOCTYPE list SYSTEM "/dtds/tei/p5/tei_all.dtd">
<list>
  <label>Gebratene Leber.</label>
  <item>
    <list rend="Method">
      <item>Nim̄ die Leber</item>
      <item>vnnd quell ſie in heiſſem Waſſer</item>
      <item>buꜩ ſie fein ſauber auß</item>
      <item>vnd ſteck ſie an ein holꜩern Spieß</item>
      <item>ſampt dem Ma‧gen</item>
      <item>leg ſie auff ein Roßt</item>
      <item>vnd brat ſie geſchwindt hinweg.</item>
    </list>
    <list rend="Serving">
      <item>Wenn du ſie wilt anrichten</item>
      <item>ſo nim̄ gebehte Schnitten drey oder vier
	in die Schüſſel</item>
      <item>geuß darein ein gute Hennenbrüh</item>
      <item>mit Petterſilgen Wurꜩel
	geſotten.</item>
    </list>
    <list rend="Comment">
      <item>Und wenn du haſt angerichtet</item>
      <item>ſo leg ſie auff die Brüh</item>
      <item>ſo iſt es gut vnd zierlich.</item>
    </list>
  </item>
</list>
		

Grilled Liver.

Take the liver

and rinse it in hot water

cleaning it well out

and stick it on a wooden skewer

along with the stomach¹

lay it on the griddle

and quickly grill it off.

When you are ready to dress it

lay 3–4 slices of toasted bread on the plate

pour over a good chicken stock

steeped with root-parsley.

And when you have everything prepared

lay it [the liver] on the stock

so that it is good and dainty.

¹ Caul?

The categorization and measurement metadata provided by ℞ is carried exclusively in attributes. This means that they can be applied to any schema or DTD in a modification layer or shim without the need to rewrite any of the element type structure. It does, however, mean that one otherwise unused element type valid in mixed content is available for hijacking to carry the ingredient metadata, and possibly another to carry the method metadata, although in the case of narrative recipes, the whole text is the method. Alternatively, if no unused element types are available, some additional attribute could be used to flag the instances when ingredient or recipe metadata is being carried on an element type in existing use.

In the case of TEI, for the purposes of testing, the material element type was chosen for the ingredients. The attributes defined in ℞ were added as a shim to the tei_all.dtd using the same enumerated attribute token list files of categories used for the development system [Flynn 2020] and the recipe was completed as a TEI P5 document with a TEI Header [Figure 4].

Figure 4: Recipe encoded in TEI with ingredients marked in the material element type

<!DOCTYPE list SYSTEM "recipe-tei.dtd">
<list>
  <label serves="4" n="5">Gebratene Leber.</label>
  <item>
    <list rend="Method">
      <item>Nim̄ die <material quantity="500" unit="g" meat="veal"
            part="liver" xml:id="liver">Leber</material></item>
      <item>vnnd quell ſie in <material quantity="1" unit="ℓ" 
            basic="water" treatment="hand-hot" 
            xml:id="water">heiſſem Waſſer</material></item>
      <item>buꜩ ſie fein ſauber auß</item>
      <item>vnd ſteck ſie an ein holꜩern Spieß</item>
      <item>ſampt dem <material quantity="1" meat="veal" part="stomach"
            xml:id="magen">Ma‧gen</material></item>
      <item>leg ſie auff ein Roßt</item>
      <item>vnd brat ſie geſchwindt hinweg.</item>
    </list>
    <list rend="Serving">
      <item>Wenn du ſie wilt anrichten</item>
      <item>ſo nim̄ <material quantity="3–4" unit="slice" quality="white" 
            basic="bread" treatment="warmed" xml:id="bread">gebehte 
            Schnitten drey oder vier</material> in die Schüſſel</item>
      <item>geuß darein ein gute <material quantity="150" unit="ml" 
            meat="chicken" part="stock" 
            xml:id="stock">Hennenbrüh</material></item>
      <item>mit <material quantity="25" unit="g" 
            vegetable="root-parsley" treatment="grated and cooked in 
            the stock" xml:id="parsley">Petterſilgen Wurꜩel</material> 
            geſotten.</item>
    </list>
    <list rend="Comment">
      <item>Und wenn du haſt angerichtet</item>
      <item>ſo leg ſie auff die Brüh</item>
        <item>ſo iſt es gut vnd zierlich.</item>
    </list>
  </item>
</list>
		

The TEI Header has been omitted from this fragment for space reasons.

<!ENTITY % tei SYSTEM "/dtds/tei/p5/tei_all.dtd">
<!ATTLIST material
  quantity CDATA #IMPLIED
  unit (%units-list;OMIT) #IMPLIED
  unit-weight CDATA #IMPLIED
  container (%package-list;OMIT) #IMPLIED
  size (%sizes-list;OMIT) #IMPLIED
  colour CDATA #IMPLIED
  quality CDATA #IMPLIED
  nature (%nature-list;OMIT) #IMPLIED
  meat (%meat-list;OMIT) #IMPLIED
  seafood (%seafood-list;OMIT) #IMPLIED
  part (%part-list;OMIT) #IMPLIED
  dairy (%dairy-list;OMIT) #IMPLIED
  fruit (%fruit-list;OMIT) #IMPLIED
  alcohol (%alcohol-list;OMIT) #IMPLIED
  herb (%herb-list;OMIT) #IMPLIED
  vegetable (%vegetable-list;OMIT) #IMPLIED
  bean (%beans-list;OMIT) #IMPLIED
  nut (%nuts-list;OMIT) #IMPLIED
  seed (%seeds-list;OMIT) #IMPLIED
  pasta (%pasta-list;OMIT) #IMPLIED
  spice (%spice-list;OMIT) #IMPLIED
  basic (%basic-list;OMIT) #IMPLIED
  sprinkles (%sprinkles-list;OMIT) #IMPLIED
  form (%form-list;OMIT) #IMPLIED
  prep CDATA #IMPLIED
  treatment CDATA #IMPLIED
  note (1|2|3) #IMPLIED
  comment CDATA #IMPLIED
  symbol CDATA #IMPLIED
  alt CDATA #IMPLIED
  calories CDATA #IMPLIED
  status (optional|required) #IMPLIED>
%tei;	      

The units, weights, and all ingredient categorizations for ℞ are held in token list files so that users can make local changes.

The resulting TEI document (with some site-associated decoration) was enabled in the author’s recipe site and transformed to the same HTML format as all the other recipes by adapting the existing XSLT to handle the TEI element types. This consisted largely of adding the TEI element type names as unions to the existing XPaths in the match attributes of the relevant XSL-templates. The resulting web page is online at https://xml.silmaril.ie/recipes/grilled-liver.html and the source (which serves as the print version, using CSS as in [Flynn 2021]) is at https://xml.silmaril.ie/recipes/grilled-liver.xml [Figure 5].

Figure 5: The recipe in TEI displayed in a recipe web site in display format (L) and print format (R)

Results and conclusions

This part of the ℞ development has been another learning curve:

Encoding

The process of encoding was relatively straightforward, much of which is due to the accessibility and adaptability of the TEI, its documentation, and the copious provision of element types. There is always an element of chance in selecting element types for this kind of temporary ‘abuse’, in that someone, somewhere, will be depending absolutely on the unmodified existence of the very one that you have chosen to carry your metadata. In my experience, however, it is a rare TEI document that, from the many modules available, uses all 32,768 element types available in mixed content.

Implementation

The adaptation of the existing web site XSLT to process a TEI document instead of the homebrew recipe schema used for development was also unproblematic, as both follow the traditional structured document concepts of heading—metadata—sectioning found in other systems [Flynn 2017].

Alternative approaches

The TEI Consortium provides ODD [TEI Consortium 2004], a language for modifying the TEI schema (or indeed any schema), so it could virtually be rewritten to create a specialist vocabulary for recipes. This would probably only make sense for a project encoding large numbers of recipes such as the entire Rumpolt book, and it would perhaps then be a possible scenario for commercial publication. The author is interested to hear of TEI encodings of recipes as part of other ptojects.

Still to do

Readers may have noticed that the formal list of ingredients is missing from the print version of the test recipe in [Figure 5] (R). The fully-formatted page in [Figure 5] (L) is generated by XSLT, so performing a collation of the ingredients to populate the list programmatically is possible. But the print view is (by design) raw XML with CSS. Performing the CSS collation has been possible for recipes using the regular DTD, as they occur inline to the normal progression of events. Doing it out-of-line for a narrative recipe needs further work.

The current experiment was a proof-of-concept, and has been mainly successful. If anyone has recipes encoded in, for example, DocBook or JATS, I would be interested to hear from them.

References

[Nonymous 2018] Nonymous, A (2018). ‘The evolution of recipe writing style’. Slices of Blue Sky, URI: https://slicesofbluesky.com/the-evolution-of-recipe-writing-style/ .

[Carême 1828] Carême, Marie Antonin (1828). Le cuisinier parisien. Published Gallerie de Bossange Père, Paris, 480pp. URI: https://archive.org/details/b29298581/page/n7/mode/2up .

[Flynn 2017] Flynn, Peter (2017). ‘Your Standard Average Document Grammar: just not your average standard’. Presented at Balisage: The Markup Conference 2017, Washington, DC, August 1–4 2017. In Proceedings of Balisage: The Markup Conference 2017. Balisage Series on Markup Technologies, vol.19. doi:https://doi.org/10.4242/BalisageVol19.Flynn01. URI: https://balisage.net/Proceedings/vol19/html/Flynn01/BalisageVol19-Flynn01.html .

[Flynn 2020] Flynn, Peter (2020). ‘Cooking up something new: An XML and XSLT experiment with recipe data’. Presented at Balisage: The Markup Conference 2020, Washington, DC, July 27–31 2020. In Proceedings of Balisage: The Markup Conference 2020. Balisage Series on Markup Technologies, vol.25 (2020). doi:https://doi.org/10.4242/BalisageVol25.Flynn01. URI: https://balisage.net/Proceedings/vol25/html/Flynn01/BalisageVol25-Flynn01.html .

[Flynn 2021] Flynn, Peter (2021). ‘Printing recipes: Continuing adventures in XML and CSS for recipe data’. Presented at Balisage: The Markup Conference 2021, Washington, DC, August 2–6 2021. In Proceedings of Balisage: The Markup Conference 2021. Balisage Series on Markup Technologies, vol.26. doi:https://doi.org/10.4242/BalisageVol26.Flynn01. URI: https://balisage.net/Proceedings/vol26/html/Flynn01/BalisageVol26-Flynn01.html .

[Flynn 2024] Flynn, Peter (2024). Formatting Information. Silmaril, Cork, Ireland. URI: http://latex.silmaril.ie/formattinginformation .

[Glasse 1753] Glasse, Hannah (1753). The Art of Cookery made Plain and Easy. John Exshaw, The Bible at Cork-Hill, Dublin, 358pp. URI: https://archive.org/details/TheArtOfCookery/page/n1/mode/2up [1775 edition online].

[Gringoire 1914] Gringoire, Théodore and Saulnier, Louis (1914). Le Répertoire de la Cuisine. Allard, London, 270pp.

[Rumpolt 1581] Rumpolt, Marx (1581). Ein new Kochbuch. Sigmundt Fenerabendt, Peter Fischer, and Heinrich Tacken, Frankfurt an Main, 520pp. URI: https://archive.org/details/ein-new-kochbuch.-das-ist-ein-grundliche-beschreibung-wie-man-recht-und-wolnicht .

[Scully 2002] Scully, D Eleanor and Scully, Terence Peter (2002). Early French Cookery. University of Michigan Press, Ann Arbor, MI, 377pp. ISBN:9780472088775. doi:https://doi.org/10.3998/mpub.14570. URI: https://press.umich.edu/Books/E/Early-French-Cookery .

[TEI Consortium 2004] TEI Consortium (2004). One Document Does-it-all. TEI Consortium, tei-c.org. URI: https://wiki.tei-c.org/index.php/ODD#.22Pure_ODD.22 .

×

Nonymous, A (2018). ‘The evolution of recipe writing style’. Slices of Blue Sky, URI: https://slicesofbluesky.com/the-evolution-of-recipe-writing-style/ .

×

Carême, Marie Antonin (1828). Le cuisinier parisien. Published Gallerie de Bossange Père, Paris, 480pp. URI: https://archive.org/details/b29298581/page/n7/mode/2up .

×

Flynn, Peter (2017). ‘Your Standard Average Document Grammar: just not your average standard’. Presented at Balisage: The Markup Conference 2017, Washington, DC, August 1–4 2017. In Proceedings of Balisage: The Markup Conference 2017. Balisage Series on Markup Technologies, vol.19. doi:https://doi.org/10.4242/BalisageVol19.Flynn01. URI: https://balisage.net/Proceedings/vol19/html/Flynn01/BalisageVol19-Flynn01.html .

×

Flynn, Peter (2020). ‘Cooking up something new: An XML and XSLT experiment with recipe data’. Presented at Balisage: The Markup Conference 2020, Washington, DC, July 27–31 2020. In Proceedings of Balisage: The Markup Conference 2020. Balisage Series on Markup Technologies, vol.25 (2020). doi:https://doi.org/10.4242/BalisageVol25.Flynn01. URI: https://balisage.net/Proceedings/vol25/html/Flynn01/BalisageVol25-Flynn01.html .

×

Flynn, Peter (2021). ‘Printing recipes: Continuing adventures in XML and CSS for recipe data’. Presented at Balisage: The Markup Conference 2021, Washington, DC, August 2–6 2021. In Proceedings of Balisage: The Markup Conference 2021. Balisage Series on Markup Technologies, vol.26. doi:https://doi.org/10.4242/BalisageVol26.Flynn01. URI: https://balisage.net/Proceedings/vol26/html/Flynn01/BalisageVol26-Flynn01.html .

×

Flynn, Peter (2024). Formatting Information. Silmaril, Cork, Ireland. URI: http://latex.silmaril.ie/formattinginformation .

×

Glasse, Hannah (1753). The Art of Cookery made Plain and Easy. John Exshaw, The Bible at Cork-Hill, Dublin, 358pp. URI: https://archive.org/details/TheArtOfCookery/page/n1/mode/2up [1775 edition online].

×

Gringoire, Théodore and Saulnier, Louis (1914). Le Répertoire de la Cuisine. Allard, London, 270pp.

×

Rumpolt, Marx (1581). Ein new Kochbuch. Sigmundt Fenerabendt, Peter Fischer, and Heinrich Tacken, Frankfurt an Main, 520pp. URI: https://archive.org/details/ein-new-kochbuch.-das-ist-ein-grundliche-beschreibung-wie-man-recht-und-wolnicht .

×

Scully, D Eleanor and Scully, Terence Peter (2002). Early French Cookery. University of Michigan Press, Ann Arbor, MI, 377pp. ISBN:9780472088775. doi:https://doi.org/10.3998/mpub.14570. URI: https://press.umich.edu/Books/E/Early-French-Cookery .

×

TEI Consortium (2004). One Document Does-it-all. TEI Consortium, tei-c.org. URI: https://wiki.tei-c.org/index.php/ODD#.22Pure_ODD.22 .

Author's keywords for this paper:
xml; css; recipes; narrative; structure; historical