Silmaril logo  Please ✉️ mail or 📞 call or 🦣 skeet to discuss your requirements.

This page is a placeholder. The ℞ system is new and the code and documentation are still being written.

The ℞ (recipe) ingredient management system

XML-based sanity-checking for recipes

Introduction

Figure 1: A prescription hand-written on 8th July 1970.℞ is short for the Latin word recīpe, pronounced ‘reh-see-pay’ or ‘reh-thee-pay’ or ‘reh-chee-pay’ depending on your culture. It means ‘take’ or ‘receive’, and it’s how doctors’ prescriptions used to begin, in the days when they were handwritten in Latin. It instructed the pharmacist what ingredients to take and how to mix them for your medicine. Old recipe books used to start each recipe with the same symbol, and old pharmacy counter-books often contained recipes for food done the same way.

Figure 1: A prescription hand-written on 8th July 1970.

Description

It has become very clear over the years that publishers are claiming that they can can no longer afford proof-readers or copy-editors. Authors certainly cannot, not on the percentages that publishers pay; and least of all cookery authors, who need to have every recipe tested many times, meaning there are constantly different versions floating around. Even if they do all the testing themselves, mistakes are bound to creep in.

℞ aims to help fix some of the usual suspects. These are common errors or problems that have been noted many times by cookery writers and editors (Flynn, 2020):

℞ can’t fix human problems. If you write that you need to “beat the eggs and sugar vigorously” when what you meant was to “stir the eggs and sugar gently”, no amount of software is going to correct you. Recipes need to be free of human errors before you think about publishing them.

How it works

℞ is an XML system. That means the recipe has to be expressed in XML. If you’re going to be publishing it, it will almost certanly be in some form of XML at some stage, possibly already. It’s straightforward: ℞ has only two principal functional parts:

  1. Each ingredient is specified with a unique one-word @xml:id attribute to identify it (you make these up, often the same as the common name of the ingredient, like ‘butter’ or ‘stock’ or ‘tomatoes’), and a particular set of other attributes to store the information, broken down into its component parts, eg

    <ingredient quantity="220" unit="g" dairy="butter" xml:id="butter"
      quality="unsalted"/>
    <ingredient quantity="2" unit="cloves" size="fat" vegetable="garlic" 
      treatment="crushed" xml:id="garlic"/>
    <ingredient quantity="1.5" unit="cups" meat="bacon" quality="diced" 
      xml:id="ham" comment="lardons"/>
    	    

    This lets the computer identify the ingredients accurately and also format them in the normal human-readable manner.

    • 220 g butter

    • 2 fat cloves garlic, crushed

    • 1½ cups diced bacon (lardons)

  2. Each time an ingredient is mentioned in the Method it uses the @xml:id value to refer to it in the @ids attribute of an <ingref> element.

    Fry the <ingref ids="butter garlic ham"/> gently for five minutes
    	    

    Multiple ingredient IDs are separated with spaces. ℞ formats the instructions using the names of the ingredients you gave, supplying punctuation as required:

    Fry the butter, garlic, and bacon gently for five minutes.

Don’t worry if this is all ελληνικά to you, your tech person will know what it means.

Because using XML is a standards-conformant approach, ℞ can be set up in any XML software on any system to be as raw or as sophisticated as you or your authors or editors need. Only the ingredient and reference attributes need to be set up, so it can work inside most existing XML publishing systems.

The software is written in XSLT3 and runs with any XSLT3 processor (eg Saxon). It’s currently beta (β) status, which means it works and is in use, but some of it is still being developed, using http://xml.silmaril.ie/recipes/ as pilot examples, and there are still bugs.

A useful side-effect of using the disaggregated ingredient data is that the XML files can be used directly as the print version of each recipe without any need for additional conversion, styling them with CSS (additional formats could of course be written to do this differently).

Benefits

℞ checks

that each ingredient gets used in the Method (or at least mentioned).

℞ checks

that all the ingredients mentioned in the Method are in the List of Ingredients.

℞ (re)generates the List of Ingredients

in the conventional recipe wording style (as in the example above)

℞ saves time

because it uses the standard XML ID/IDREFS cross-reference feature to refer to each ingredient instead of the author or editor having to retype the name of each item by hand.

℞ increases consistency and accuracy

because it formats the actual names of the ingredients regardless of the @xml:ids you give them.

℞ checks the order

of the items in the List of Ingredients, to make sure that they match the order in which they are used in the Method.

℞ can extract the ingredients into an index

so if you are making a recipes website or publishing a book, your readers can search reliably, in the knowledge that everything there is listed, and nothing is listed that isn't there; it could also be used to generate shopping lists or grocery-site lookups.

℞ can be programmed to look up food standards databases

because it is consistent in storing the details of each ingredient (quantity, units, size, name, etc). If you have access to such a database, this lets you get the calories, fats, sugars, carbohydrates, fibre, allergens, and other data for labelling, hygiene, legal, and food security requirements.

Workplan

A detailed paper describing the system (Flynn, 2020) was presented at the Balisage conference in July 2020. A development paper, on the use of CSS to format the XML for print versions, was presented in August 2021 (Flynn, 2021). A further paper, demonstrating the use of ℞ with another DTD/schema (TEI, for historical narrative recipes), was presented at Balisage in 2025 (Flynn, 2025)

Current status:

Development, suspended during the COVID-19 pandemic, has resumed and is ongoing:

Note on required and optional features

In this manual, the keywords MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL have a specific meaning when shown in THIS TYPESTYLE, and MUST be interpreted as described in Key words for use in RFCs to Indicate Requirement Levels  (Bradner, 1997).

When shown in normal type, these words keep their conventional contextual degree of meaning.

Special fonts and characters

In addition to the Requirement Levels mentioned above, the following typographic conventions are used to distinguish between different meanings:

Style Meaning
<ingredient> an XML element type name
@meat an XML attribute name
"beef" an XML attribute value
EMPTY an XML content model
recipe.dtd a file name

References

  1. Peter Flynn (2020) ‘Cooking up something new — An XML and XSLT experiment with recipe data’. In Balisage—The Markup Conference 2020, 27–31 July, Online. Balisage Series on Markup Technologies (25) https://doi.org/10.4242/BalisageVol25.Flynn01
  2. Peter Flynn (2021) ‘Printing recipes — Continuing adventures in XML and CSS for recipe data’. In Balisage—The Markup Conference 2021, 2–6 August, Online. Balisage Series on Markup Technologies (26) https://doi.org/10.4242/BalisageVol26.Flynn01
  3. Peter Flynn (2025) ‘Leveraging markup to process narrative recipes’. In Balisage—The Markup Conference 2025, 2–6 August, Online. Balisage Series on Markup Technologies (30) https://doi.org/10.4242/BalisageVol30.Flynn01
  4. Scott Bradner (1997) Key words for use in RFCs to Indicate Requirement Levels [RFC 2119], Internet Engineering Task Force, Reston, VA https://tools.ietf.org/rfc/rfc2119.txt

Peter Flynn, 22 April 2026